• 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/Memory.hpp"
29 #include "Common/Timer.hpp"
30 #include "../common/debug.h"
31 
32 namespace es2
33 {
34 	using namespace sw;
35 
Device(Context * context)36 	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
37 	{
38 		for(int i = 0; i < RENDERTARGETS; i++)
39 		{
40 			renderTarget[i] = nullptr;
41 		}
42 
43 		depthBuffer = nullptr;
44 		stencilBuffer = nullptr;
45 
46 		setDepthBufferEnable(true);
47 		setFillMode(FILL_SOLID);
48 		setShadingMode(SHADING_GOURAUD);
49 		setDepthWriteEnable(true);
50 		setAlphaTestEnable(false);
51 		setSourceBlendFactor(BLEND_ONE);
52 		setDestBlendFactor(BLEND_ZERO);
53 		setCullMode(CULL_COUNTERCLOCKWISE, true);
54 		setDepthCompare(DEPTH_LESSEQUAL);
55 		setAlphaReference(127.5f);
56 		setAlphaCompare(ALPHA_ALWAYS);
57 		setAlphaBlendEnable(false);
58 		setFogEnable(false);
59 		setSpecularEnable(false);
60 		setFogColor(0);
61 		setPixelFogMode(FOG_NONE);
62 		setFogStart(0.0f);
63 		setFogEnd(1.0f);
64 		setFogDensity(1.0f);
65 		setRangeFogEnable(false);
66 		setStencilEnable(false);
67 		setStencilFailOperation(OPERATION_KEEP);
68 		setStencilZFailOperation(OPERATION_KEEP);
69 		setStencilPassOperation(OPERATION_KEEP);
70 		setStencilCompare(STENCIL_ALWAYS);
71 		setStencilReference(0);
72 		setStencilMask(0xFFFFFFFF);
73 		setStencilWriteMask(0xFFFFFFFF);
74 		setVertexFogMode(FOG_NONE);
75 		setClipFlags(0);
76 		setPointSize(1.0f);
77 		setPointSizeMin(0.125f);
78         setPointSizeMax(8192.0f);
79 		setBlendOperation(BLENDOP_ADD);
80 		scissorEnable = false;
81 		setSlopeDepthBias(0.0f);
82 		setTwoSidedStencil(false);
83 		setStencilFailOperationCCW(OPERATION_KEEP);
84 		setStencilZFailOperationCCW(OPERATION_KEEP);
85 		setStencilPassOperationCCW(OPERATION_KEEP);
86 		setStencilCompareCCW(STENCIL_ALWAYS);
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 		setColorLogicOpEnabled(false);
96 		setLogicalOperation(LOGICALOP_COPY);
97 
98 		for(int i = 0; i < 16; i++)
99 		{
100 			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
101 			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
102 			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
103 			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
104 			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
105 			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
106 			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
107 		}
108 
109 		for(int i = 0; i < 4; i++)
110 		{
111 			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
112 			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
113 			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
114 			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
115 			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
116 			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
117 			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
118 		}
119 
120 		for(int i = 0; i < 6; i++)
121 		{
122 			float plane[4] = {0, 0, 0, 0};
123 
124 			setClipPlane(i, plane);
125 		}
126 
127 		pixelShader = nullptr;
128 		vertexShader = nullptr;
129 
130 		pixelShaderDirty = true;
131 		pixelShaderConstantsFDirty = 0;
132 		vertexShaderDirty = true;
133 		vertexShaderConstantsFDirty = 0;
134 
135 		for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++)
136 		{
137 			float zero[4] = {0, 0, 0, 0};
138 
139 			setPixelShaderConstantF(i, zero, 1);
140 		}
141 
142 		for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++)
143 		{
144 			float zero[4] = {0, 0, 0, 0};
145 
146 			setVertexShaderConstantF(i, zero, 1);
147 		}
148 	}
149 
~Device()150 	Device::~Device()
151 	{
152 		for(int i = 0; i < RENDERTARGETS; i++)
153 		{
154 			if(renderTarget[i])
155 			{
156 				renderTarget[i]->release();
157 				renderTarget[i] = nullptr;
158 			}
159 		}
160 
161 		if(depthBuffer)
162 		{
163 			depthBuffer->release();
164 			depthBuffer = nullptr;
165 		}
166 
167 		if(stencilBuffer)
168 		{
169 			stencilBuffer->release();
170 			stencilBuffer = nullptr;
171 		}
172 
173 		delete context;
174 	}
175 
176 	// This object has to be mem aligned
operator new(size_t size)177 	void* Device::operator new(size_t size)
178 	{
179 		ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
180 		return sw::allocate(sizeof(Device), 16);
181 	}
182 
operator delete(void * mem)183 	void Device::operator delete(void * mem)
184 	{
185 		sw::deallocate(mem);
186 	}
187 
clearColor(float red,float green,float blue,float alpha,unsigned int rgbaMask)188 	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
189 	{
190 		if(!rgbaMask)
191 		{
192 			return;
193 		}
194 
195 		float rgba[4];
196 		rgba[0] = red;
197 		rgba[1] = green;
198 		rgba[2] = blue;
199 		rgba[3] = alpha;
200 
201 		for(int i = 0; i < RENDERTARGETS; ++i)
202 		{
203 			if(renderTarget[i])
204 			{
205 				sw::Rect clearRect = renderTarget[i]->getRect();
206 
207 				if(scissorEnable)
208 				{
209 					clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
210 				}
211 
212 				clear(rgba, FORMAT_A32B32G32R32F, renderTarget[i], clearRect, rgbaMask);
213 			}
214 		}
215 	}
216 
clearDepth(float z)217 	void Device::clearDepth(float z)
218 	{
219 		if(!depthBuffer)
220 		{
221 			return;
222 		}
223 
224 		z = clamp01(z);
225 		sw::Rect clearRect = depthBuffer->getRect();
226 
227 		if(scissorEnable)
228 		{
229 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
230 		}
231 
232 		depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
233 	}
234 
clearStencil(unsigned int stencil,unsigned int mask)235 	void Device::clearStencil(unsigned int stencil, unsigned int mask)
236 	{
237 		if(!stencilBuffer)
238 		{
239 			return;
240 		}
241 
242 		sw::Rect clearRect = stencilBuffer->getRect();
243 
244 		if(scissorEnable)
245 		{
246 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
247 		}
248 
249 		stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
250 	}
251 
drawIndexedPrimitive(sw::DrawType type,unsigned int indexOffset,unsigned int primitiveCount)252 	void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
253 	{
254 		if(!bindResources() || !primitiveCount)
255 		{
256 			return;
257 		}
258 
259 		draw(type, indexOffset, primitiveCount);
260 	}
261 
drawPrimitive(sw::DrawType type,unsigned int primitiveCount)262 	void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
263 	{
264 		if(!bindResources() || !primitiveCount)
265 		{
266 			return;
267 		}
268 
269 		setIndexBuffer(nullptr);
270 
271 		draw(type, 0, primitiveCount);
272 	}
273 
setPixelShader(const PixelShader * pixelShader)274 	void Device::setPixelShader(const PixelShader *pixelShader)
275 	{
276 		this->pixelShader = pixelShader;
277 		pixelShaderDirty = true;
278 	}
279 
setPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)280 	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
281 	{
282 		for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++)
283 		{
284 			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
285 			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
286 			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
287 			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
288 		}
289 
290 		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
291 		pixelShaderDirty = true;   // Reload DEF constants
292 	}
293 
setScissorEnable(bool enable)294 	void Device::setScissorEnable(bool enable)
295 	{
296 		scissorEnable = enable;
297 	}
298 
setRenderTarget(int index,egl::Image * renderTarget,unsigned int layer)299 	void Device::setRenderTarget(int index, egl::Image *renderTarget, unsigned int layer)
300 	{
301 		if(renderTarget)
302 		{
303 			renderTarget->addRef();
304 		}
305 
306 		if(this->renderTarget[index])
307 		{
308 			this->renderTarget[index]->release();
309 		}
310 
311 		this->renderTarget[index] = renderTarget;
312 
313 		Renderer::setRenderTarget(index, renderTarget, layer);
314 	}
315 
setDepthBuffer(egl::Image * depthBuffer,unsigned int layer)316 	void Device::setDepthBuffer(egl::Image *depthBuffer, unsigned int layer)
317 	{
318 		if(this->depthBuffer == depthBuffer)
319 		{
320 			return;
321 		}
322 
323 		if(depthBuffer)
324 		{
325 			depthBuffer->addRef();
326 		}
327 
328 		if(this->depthBuffer)
329 		{
330 			this->depthBuffer->release();
331 		}
332 
333 		this->depthBuffer = depthBuffer;
334 
335 		Renderer::setDepthBuffer(depthBuffer, layer);
336 	}
337 
setStencilBuffer(egl::Image * stencilBuffer,unsigned int layer)338 	void Device::setStencilBuffer(egl::Image *stencilBuffer, unsigned int layer)
339 	{
340 		if(this->stencilBuffer == stencilBuffer)
341 		{
342 			return;
343 		}
344 
345 		if(stencilBuffer)
346 		{
347 			stencilBuffer->addRef();
348 		}
349 
350 		if(this->stencilBuffer)
351 		{
352 			this->stencilBuffer->release();
353 		}
354 
355 		this->stencilBuffer = stencilBuffer;
356 
357 		Renderer::setStencilBuffer(stencilBuffer, layer);
358 	}
359 
setScissorRect(const sw::Rect & rect)360 	void Device::setScissorRect(const sw::Rect &rect)
361 	{
362 		scissorRect = rect;
363 	}
364 
setVertexShader(const VertexShader * vertexShader)365 	void Device::setVertexShader(const VertexShader *vertexShader)
366 	{
367 		this->vertexShader = vertexShader;
368 		vertexShaderDirty = true;
369 	}
370 
setVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)371 	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
372 	{
373 		for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++)
374 		{
375 			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
376 			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
377 			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
378 			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
379 		}
380 
381 		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
382 		vertexShaderDirty = true;   // Reload DEF constants
383 	}
384 
setViewport(const Viewport & viewport)385 	void Device::setViewport(const Viewport &viewport)
386 	{
387 		this->viewport = viewport;
388 	}
389 
copyBuffer(byte * sourceBuffer,byte * destBuffer,unsigned int width,unsigned int height,unsigned int sourcePitch,unsigned int destPitch,unsigned int bytes,bool flipX,bool flipY)390 	void Device::copyBuffer(byte *sourceBuffer, byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY)
391 	{
392 		if(flipX)
393 		{
394 			if(flipY)
395 			{
396 				sourceBuffer += (height - 1) * sourcePitch;
397 				for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
398 				{
399 					byte *srcX = sourceBuffer + (width - 1) * bytes;
400 					byte *dstX = destBuffer;
401 					for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes)
402 					{
403 						memcpy(dstX, srcX, bytes);
404 					}
405 				}
406 			}
407 			else
408 			{
409 				for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
410 				{
411 					byte *srcX = sourceBuffer + (width - 1) * bytes;
412 					byte *dstX = destBuffer;
413 					for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes)
414 					{
415 						memcpy(dstX, srcX, bytes);
416 					}
417 				}
418 			}
419 		}
420 		else
421 		{
422 			unsigned int widthB = width * bytes;
423 
424 			if(flipY)
425 			{
426 				sourceBuffer += (height - 1) * sourcePitch;
427 				for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
428 				{
429 					memcpy(destBuffer, sourceBuffer, widthB);
430 				}
431 			}
432 			else
433 			{
434 				for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
435 				{
436 					memcpy(destBuffer, sourceBuffer, widthB);
437 				}
438 			}
439 		}
440 	}
441 
stretchRect(sw::Surface * source,const sw::SliceRectF * sourceRect,sw::Surface * dest,const sw::SliceRect * destRect,unsigned char flags)442 	bool Device::stretchRect(sw::Surface *source, const sw::SliceRectF *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, unsigned char flags)
443 	{
444 		if(!source || !dest)
445 		{
446 			ERR("Invalid parameters");
447 			return false;
448 		}
449 
450 		int sWidth = source->getWidth();
451 		int sHeight = source->getHeight();
452 		int dWidth = dest->getWidth();
453 		int dHeight = dest->getHeight();
454 
455 		if(sourceRect && destRect &&
456 			(sourceRect->width() == 0.0f || !std::isfinite(sourceRect->width()) ||
457 			sourceRect->height() == 0.0f || !std::isfinite(sourceRect->height()) ||
458 			destRect->width() == 0.0f || destRect->height() == 0.0f))
459 		{
460 			return true; // No work to do.
461 		}
462 
463 		bool flipX = false;
464 		bool flipY = false;
465 		if(sourceRect && destRect)
466 		{
467 			flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1);
468 			flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1);
469 		}
470 		else if(sourceRect)
471 		{
472 			flipX = (sourceRect->x0 > sourceRect->x1);
473 			flipY = (sourceRect->y0 > sourceRect->y1);
474 		}
475 		else if(destRect)
476 		{
477 			flipX = (destRect->x0 > destRect->x1);
478 			flipY = (destRect->y0 > destRect->y1);
479 		}
480 
481 		SliceRectF sRect;
482 		SliceRect dRect;
483 
484 		if(sourceRect)
485 		{
486 			sRect.x0 = sourceRect->x0;
487 			sRect.x1 = sourceRect->x1;
488 			sRect.y0 = sourceRect->y0;
489 			sRect.y1 = sourceRect->y1;
490 			sRect.slice = sourceRect->slice;
491 
492 			if(sRect.x0 > sRect.x1)
493 			{
494 				swap(sRect.x0, sRect.x1);
495 			}
496 
497 			if(sRect.y0 > sRect.y1)
498 			{
499 				swap(sRect.y0, sRect.y1);
500 			}
501 		}
502 		else
503 		{
504 			sRect.y0 = 0.0f;
505 			sRect.x0 = 0.0f;
506 			sRect.y1 = (float)sHeight;
507 			sRect.x1 = (float)sWidth;
508 		}
509 
510 		if(destRect)
511 		{
512 			dRect = *destRect;
513 
514 			if(dRect.x0 > dRect.x1)
515 			{
516 				swap(dRect.x0, dRect.x1);
517 			}
518 
519 			if(dRect.y0 > dRect.y1)
520 			{
521 				swap(dRect.y0, dRect.y1);
522 			}
523 		}
524 		else
525 		{
526 			dRect.y0 = 0;
527 			dRect.x0 = 0;
528 			dRect.y1 = dHeight;
529 			dRect.x1 = dWidth;
530 		}
531 
532 		sw::Rect srcClipRect(0, 0, sWidth, sHeight);
533 		if (!ClipSrcRect(sRect, dRect, srcClipRect, flipX, flipY))
534 		{
535 			return true;
536 		}
537 
538 		sw::Rect dstClipRect(0, 0, dWidth, dHeight);
539 		if (!ClipDstRect(sRect, dRect, dstClipRect, flipX, flipY))
540 		{
541 			return true;
542 		}
543 
544 		if((sRect.width() == 0) || (sRect.height() == 0) ||
545 		   (dRect.width() == 0) || (dRect.height() == 0) ||
546 		   !std::isfinite(sRect.width()) || !std::isfinite(sRect.height()))
547 		{
548 			return true; // no work to do
549 		}
550 
551 		if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest))
552 		{
553 			ERR("Invalid parameters");
554 			return false;
555 		}
556 
557 		bool isDepth = (flags & Device::DEPTH_BUFFER) && Surface::isDepth(source->getInternalFormat());
558 		bool isStencil = (flags & Device::STENCIL_BUFFER) && Surface::isStencil(source->getInternalFormat());
559 		bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER;
560 
561 		if(!isColor && !isDepth && !isStencil)
562 		{
563 			return true;
564 		}
565 
566 		int sourceSliceB = isStencil ? source->getStencilSliceB() : source->getInternalSliceB();
567 		int destSliceB = isStencil ? dest->getStencilSliceB() : dest->getInternalSliceB();
568 		int sourcePitchB = isStencil ? source->getStencilPitchB() : source->getInternalPitchB();
569 		int destPitchB = isStencil ? dest->getStencilPitchB() : dest->getInternalPitchB();
570 
571 		bool isOutOfBounds = (sRect.x0 < 0.0f) || (sRect.y0 < 0.0f) || (sRect.x1 > (float)sWidth) || (sRect.y1 > (float)sHeight);
572 		bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height());
573 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
574 		bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat());
575 		bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) &&
576 		                (sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y1 == dHeight);
577 		bool alpha0xFF = false;
578 		bool equalSlice = (sourceSliceB == destSliceB) && (source->getBorder() == 0) && (dest->getBorder() == 0);
579 		bool smallMargin = sourcePitchB <= source->getWidth() * Surface::bytes(source->getInternalFormat()) + 16;
580 
581 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
582 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
583 		{
584 			equalFormats = true;
585 			alpha0xFF = true;
586 		}
587 
588 		if(fullCopy && !scaling && !isOutOfBounds && equalFormats && !alpha0xFF && equalSlice && smallMargin && !flipX && !flipY)
589 		{
590 			byte *sourceBuffer = isStencil ? (byte*)source->lockStencil(0, 0, 0, PUBLIC) : (byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
591 			byte *destBuffer = isStencil ? (byte*)dest->lockStencil(0, 0, 0, PUBLIC) : (byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
592 
593 			memcpy(destBuffer, sourceBuffer, sourceSliceB);
594 
595 			isStencil ? source->unlockStencil() : source->unlockInternal();
596 			isStencil ? dest->unlockStencil() : dest->unlockInternal();
597 		}
598 		else if(isDepth && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
599 		{
600 			byte *sourceBuffer = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC);
601 			byte *destBuffer = (byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
602 
603 			copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
604 
605 			source->unlockInternal();
606 			dest->unlockInternal();
607 		}
608 		else if((flags & Device::COLOR_BUFFER) && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
609 		{
610 			byte *sourceBytes = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
611 			byte *destBytes = (byte*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
612 
613 			unsigned int width = dRect.x1 - dRect.x0;
614 			unsigned int height = dRect.y1 - dRect.y0;
615 
616 			copyBuffer(sourceBytes, destBytes, width, height, sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
617 
618 			if(alpha0xFF)
619 			{
620 				for(unsigned int y = 0; y < height; y++)
621 				{
622 					for(unsigned int x = 0; x < width; x++)
623 					{
624 						destBytes[4 * x + 3] = 0xFF;
625 					}
626 
627 					destBytes += destPitchB;
628 				}
629 			}
630 
631 			source->unlockInternal();
632 			dest->unlockInternal();
633 		}
634 		else if(isColor || isDepth || isStencil)
635 		{
636 			if(flipX)
637 			{
638 				swap(dRect.x0, dRect.x1);
639 			}
640 			if(flipY)
641 			{
642 				swap(dRect.y0, dRect.y1);
643 			}
644 
645 			blit(source, sRect, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil);
646 		}
647 		else UNREACHABLE(false);
648 
649 		return true;
650 	}
651 
stretchCube(sw::Surface * source,sw::Surface * dest)652 	bool Device::stretchCube(sw::Surface *source, sw::Surface *dest)
653 	{
654 		if(!source || !dest || Surface::isDepth(source->getInternalFormat()) || Surface::isStencil(source->getInternalFormat()))
655 		{
656 			ERR("Invalid parameters");
657 			return false;
658 		}
659 
660 		int sWidth  = source->getWidth();
661 		int sHeight = source->getHeight();
662 		int sDepth  = source->getDepth();
663 		int dWidth  = dest->getWidth();
664 		int dHeight = dest->getHeight();
665 		int dDepth  = dest->getDepth();
666 
667 		if((sWidth == 0) || (sHeight == 0) || (sDepth == 0) ||
668 		   (dWidth == 0) || (dHeight == 0) || (dDepth == 0))
669 		{
670 			return true; // no work to do
671 		}
672 
673 		bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);
674 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
675 		bool alpha0xFF = false;
676 
677 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
678 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
679 		{
680 			equalFormats = true;
681 			alpha0xFF = true;
682 		}
683 
684 		if(!scaling && equalFormats)
685 		{
686 			unsigned int sourcePitch = source->getInternalPitchB();
687 			unsigned int destPitch = dest->getInternalPitchB();
688 			unsigned int bytes = dWidth * Surface::bytes(source->getInternalFormat());
689 
690 			for(int z = 0; z < dDepth; z++)
691 			{
692 				unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);
693 				unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);
694 
695 				for(int y = 0; y < dHeight; y++)
696 				{
697 					memcpy(destBytes, sourceBytes, bytes);
698 
699 					if(alpha0xFF)
700 					{
701 						for(int x = 0; x < dWidth; x++)
702 						{
703 							destBytes[4 * x + 3] = 0xFF;
704 						}
705 					}
706 
707 					sourceBytes += sourcePitch;
708 					destBytes += destPitch;
709 				}
710 
711 				source->unlockInternal();
712 				dest->unlockInternal();
713 			}
714 		}
715 		else
716 		{
717 			blit3D(source, dest);
718 		}
719 
720 		return true;
721 	}
722 
bindResources()723 	bool Device::bindResources()
724 	{
725 		if(!bindViewport() && !context->transformFeedbackEnabled)
726 		{
727 			return false;   // Zero-area target region
728 		}
729 
730 		bindShaderConstants();
731 
732 		return true;
733 	}
734 
bindShaderConstants()735 	void Device::bindShaderConstants()
736 	{
737 		if(pixelShaderDirty)
738 		{
739 			if(pixelShader)
740 			{
741 				if(pixelShaderConstantsFDirty)
742 				{
743 					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
744 				}
745 
746 				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF
747 				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
748 			}
749 			else
750 			{
751 				setPixelShader(0);
752 			}
753 
754 			pixelShaderDirty = false;
755 		}
756 
757 		if(vertexShaderDirty)
758 		{
759 			if(vertexShader)
760 			{
761 				if(vertexShaderConstantsFDirty)
762 				{
763 					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
764 				}
765 
766 				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF
767 				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
768 			}
769 			else
770 			{
771 				setVertexShader(0);
772 			}
773 
774 			vertexShaderDirty = false;
775 		}
776 	}
777 
bindViewport()778 	bool Device::bindViewport()
779 	{
780 		if(viewport.width <= 0 || viewport.height <= 0)
781 		{
782 			return false;
783 		}
784 
785 		if(scissorEnable)
786 		{
787 			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
788 			{
789 				return false;
790 			}
791 
792 			sw::Rect scissor;
793 			scissor.x0 = scissorRect.x0;
794 			scissor.x1 = scissorRect.x1;
795 			scissor.y0 = scissorRect.y0;
796 			scissor.y1 = scissorRect.y1;
797 
798 			setScissor(scissor);
799 		}
800 		else
801 		{
802 			sw::Rect scissor;
803 			scissor.x0 = viewport.x0;
804 			scissor.x1 = viewport.x0 + viewport.width;
805 			scissor.y0 = viewport.y0;
806 			scissor.y1 = viewport.y0 + viewport.height;
807 
808 			for(int i = 0; i < RENDERTARGETS; ++i)
809 			{
810 				if(renderTarget[i])
811 				{
812 					scissor.x0 = max(scissor.x0, 0);
813 					scissor.x1 = min(scissor.x1, renderTarget[i]->getWidth());
814 					scissor.y0 = max(scissor.y0, 0);
815 					scissor.y1 = min(scissor.y1, renderTarget[i]->getHeight());
816 				}
817 			}
818 
819 			if(depthBuffer)
820 			{
821 				scissor.x0 = max(scissor.x0, 0);
822 				scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
823 				scissor.y0 = max(scissor.y0, 0);
824 				scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
825 			}
826 
827 			if(stencilBuffer)
828 			{
829 				scissor.x0 = max(scissor.x0, 0);
830 				scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
831 				scissor.y0 = max(scissor.y0, 0);
832 				scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
833 			}
834 
835 			// Ensure scissor range is positive
836 			scissor.x0 = max(scissor.x0, 0);
837 			scissor.x1 = max(scissor.x1, 0);
838 			scissor.y0 = max(scissor.y0, 0);
839 			scissor.y1 = max(scissor.y1, 0);
840 
841 			setScissor(scissor);
842 		}
843 
844 		sw::Viewport view;
845 		view.x0 = (float)viewport.x0;
846 		view.y0 = (float)viewport.y0;
847 		view.width = (float)viewport.width;
848 		view.height = (float)viewport.height;
849 		view.minZ = viewport.minZ;
850 		view.maxZ = viewport.maxZ;
851 
852 		Renderer::setViewport(view);
853 
854 		return true;
855 	}
856 
validRectangle(const sw::Rect * rect,sw::Surface * surface)857 	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
858 	{
859 		if(!rect)
860 		{
861 			return true;
862 		}
863 
864 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
865 		{
866 			return false;
867 		}
868 
869 		if(rect->x0 < 0 || rect->y0 < 0)
870 		{
871 			return false;
872 		}
873 
874 		if(rect->x1 >(int)surface->getWidth() || rect->y1 >(int)surface->getHeight())
875 		{
876 			return false;
877 		}
878 
879 		return true;
880 	}
881 
validRectangle(const sw::RectF * rect,sw::Surface * surface)882 	bool Device::validRectangle(const sw::RectF *rect, sw::Surface *surface)
883 	{
884 		if(!rect)
885 		{
886 			return true;
887 		}
888 
889 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
890 		{
891 			return false;
892 		}
893 
894 		if (!std::isfinite(rect->x0) || !std::isfinite(rect->x1) ||
895 			!std::isfinite(rect->y0) || !std::isfinite(rect->y1))
896 		{
897 			return false;
898 		}
899 
900 		return true;
901 	}
902 
ClipDstRect(sw::RectF & srcRect,sw::Rect & dstRect,sw::Rect & clipRect,bool flipX,bool flipY)903 	bool Device::ClipDstRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
904 	{
905 		if(dstRect.x0 < clipRect.x0)
906 		{
907 			float offset = (static_cast<float>(clipRect.x0 - dstRect.x0) / static_cast<float>(dstRect.width())) * srcRect.width();
908 			if (!std::isfinite(offset))
909 			{
910 				return false;
911 			}
912 			if(flipX)
913 			{
914 				srcRect.x1 -= offset;
915 			}
916 			else
917 			{
918 				srcRect.x0 += offset;
919 			}
920 			dstRect.x0 = clipRect.x0;
921 		}
922 		if(dstRect.x1 > clipRect.x1)
923 		{
924 			float offset = (static_cast<float>(dstRect.x1 - clipRect.x1) / static_cast<float>(dstRect.width())) * srcRect.width();
925 			if (!std::isfinite(offset))
926 			{
927 				return false;
928 			}
929 			if(flipX)
930 			{
931 				srcRect.x0 += offset;
932 			}
933 			else
934 			{
935 				srcRect.x1 -= offset;
936 			}
937 			dstRect.x1 = clipRect.x1;
938 		}
939 		if(dstRect.y0 < clipRect.y0)
940 		{
941 			float offset = (static_cast<float>(clipRect.y0 - dstRect.y0) / static_cast<float>(dstRect.height())) * srcRect.height();
942 			if (!std::isfinite(offset))
943 			{
944 				return false;
945 			}
946 			if(flipY)
947 			{
948 				srcRect.y1 -= offset;
949 			}
950 			else
951 			{
952 				srcRect.y0 += offset;
953 			}
954 			dstRect.y0 = clipRect.y0;
955 		}
956 		if(dstRect.y1 > clipRect.y1)
957 		{
958 			float offset = (static_cast<float>(dstRect.y1 - clipRect.y1) / static_cast<float>(dstRect.height())) * srcRect.height();
959 			if (!std::isfinite(offset))
960 			{
961 				return false;
962 			}
963 			if(flipY)
964 			{
965 				srcRect.y0 += offset;
966 			}
967 			else
968 			{
969 				srcRect.y1 -= offset;
970 			}
971 			dstRect.y1 = clipRect.y1;
972 		}
973 		return true;
974 	}
975 
ClipSrcRect(sw::RectF & srcRect,sw::Rect & dstRect,sw::Rect & clipRect,bool flipX,bool flipY)976 	bool Device::ClipSrcRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
977 	{
978 		if(srcRect.x0 < static_cast<float>(clipRect.x0))
979 		{
980 			float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
981 			float offsetf = roundf((static_cast<float>(clipRect.x0) - srcRect.x0) * ratio);
982 			if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
983 			{
984 				return false;
985 			}
986 			int offset = static_cast<int>(offsetf);
987 			if(flipX)
988 			{
989 				dstRect.x1 -= offset;
990 			}
991 			else
992 			{
993 				dstRect.x0 += offset;
994 			}
995 			srcRect.x0 += offsetf / ratio;
996 		}
997 		if(srcRect.x1 > static_cast<float>(clipRect.x1))
998 		{
999 			float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
1000 			float offsetf = roundf((srcRect.x1 - static_cast<float>(clipRect.x1)) * ratio);
1001 			if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
1002 			{
1003 				return false;
1004 			}
1005 			int offset = static_cast<int>(offsetf);
1006 			if(flipX)
1007 			{
1008 				dstRect.x0 += offset;
1009 			}
1010 			else
1011 			{
1012 				dstRect.x1 -= offset;
1013 			}
1014 			srcRect.x1 -= offsetf / ratio;
1015 		}
1016 		if(srcRect.y0 < static_cast<float>(clipRect.y0))
1017 		{
1018 			float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
1019 			float offsetf = roundf((static_cast<float>(clipRect.y0) - srcRect.y0) * ratio);
1020 			if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
1021 			{
1022 				return false;
1023 			}
1024 			int offset = static_cast<int>(offsetf);
1025 			if(flipY)
1026 			{
1027 				dstRect.y1 -= offset;
1028 			}
1029 			else
1030 			{
1031 				dstRect.y0 += offset;
1032 			}
1033 			srcRect.y0 += offsetf / ratio;
1034 		}
1035 		if(srcRect.y1 > static_cast<float>(clipRect.y1))
1036 		{
1037 			float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
1038 			float offsetf = roundf((srcRect.y1 - static_cast<float>(clipRect.y1)) * ratio);
1039 			if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
1040 			{
1041 				return false;
1042 			}
1043 			int offset = static_cast<int>(offsetf);
1044 			if(flipY)
1045 			{
1046 				dstRect.y0 += offset;
1047 			}
1048 			else
1049 			{
1050 				dstRect.y1 -= offset;
1051 			}
1052 			srcRect.y1 -= offsetf / ratio;
1053 		}
1054 		return true;
1055 	}
1056 
finish()1057 	void Device::finish()
1058 	{
1059 		synchronize();
1060 	}
1061 }
1062