• 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 		bool flipX = false;
456 		bool flipY = false;
457 		if(sourceRect && destRect)
458 		{
459 			flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1);
460 			flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1);
461 		}
462 		else if(sourceRect)
463 		{
464 			flipX = (sourceRect->x0 > sourceRect->x1);
465 			flipY = (sourceRect->y0 > sourceRect->y1);
466 		}
467 		else if(destRect)
468 		{
469 			flipX = (destRect->x0 > destRect->x1);
470 			flipY = (destRect->y0 > destRect->y1);
471 		}
472 
473 		SliceRectF sRect;
474 		SliceRect dRect;
475 
476 		if(sourceRect)
477 		{
478 			sRect.x0 = sourceRect->x0;
479 			sRect.x1 = sourceRect->x1;
480 			sRect.y0 = sourceRect->y0;
481 			sRect.y1 = sourceRect->y1;
482 			sRect.slice = sourceRect->slice;
483 
484 			if(sRect.x0 > sRect.x1)
485 			{
486 				swap(sRect.x0, sRect.x1);
487 			}
488 
489 			if(sRect.y0 > sRect.y1)
490 			{
491 				swap(sRect.y0, sRect.y1);
492 			}
493 		}
494 		else
495 		{
496 			sRect.y0 = 0.0f;
497 			sRect.x0 = 0.0f;
498 			sRect.y1 = (float)sHeight;
499 			sRect.x1 = (float)sWidth;
500 		}
501 
502 		if(destRect)
503 		{
504 			dRect = *destRect;
505 
506 			if(dRect.x0 > dRect.x1)
507 			{
508 				swap(dRect.x0, dRect.x1);
509 			}
510 
511 			if(dRect.y0 > dRect.y1)
512 			{
513 				swap(dRect.y0, dRect.y1);
514 			}
515 		}
516 		else
517 		{
518 			dRect.y0 = 0;
519 			dRect.x0 = 0;
520 			dRect.y1 = dHeight;
521 			dRect.x1 = dWidth;
522 		}
523 
524 		sw::Rect srcClipRect(0, 0, sWidth, sHeight);
525 		ClipSrcRect(sRect, dRect, srcClipRect, flipX, flipY);
526 
527 		sw::Rect dstClipRect(0, 0, dWidth, dHeight);
528 		ClipDstRect(sRect, dRect, dstClipRect, flipX, flipY);
529 
530 		if((sRect.width() == 0) || (sRect.height() == 0) ||
531 		   (dRect.width() == 0) || (dRect.height() == 0))
532 		{
533 			return true; // no work to do
534 		}
535 
536 		if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest))
537 		{
538 			ERR("Invalid parameters");
539 			return false;
540 		}
541 
542 		bool isDepth = (flags & Device::DEPTH_BUFFER) && Surface::isDepth(source->getInternalFormat());
543 		bool isStencil = (flags & Device::STENCIL_BUFFER) && Surface::isStencil(source->getInternalFormat());
544 		bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER;
545 
546 		if(!isColor && !isDepth && !isStencil)
547 		{
548 			return true;
549 		}
550 
551 		int sourceSliceB = isStencil ? source->getStencilSliceB() : source->getInternalSliceB();
552 		int destSliceB = isStencil ? dest->getStencilSliceB() : dest->getInternalSliceB();
553 		int sourcePitchB = isStencil ? source->getStencilPitchB() : source->getInternalPitchB();
554 		int destPitchB = isStencil ? dest->getStencilPitchB() : dest->getInternalPitchB();
555 
556 		bool isOutOfBounds = (sRect.x0 < 0.0f) || (sRect.y0 < 0.0f) || (sRect.x1 > (float)sWidth) || (sRect.y1 > (float)sHeight);
557 		bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height());
558 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
559 		bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat());
560 		bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) &&
561 		                (sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y1 == dHeight);
562 		bool alpha0xFF = false;
563 		bool equalSlice = sourceSliceB == destSliceB;
564 		bool smallMargin = sourcePitchB <= source->getWidth() * Surface::bytes(source->getInternalFormat()) + 16;
565 
566 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
567 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
568 		{
569 			equalFormats = true;
570 			alpha0xFF = true;
571 		}
572 
573 		if(fullCopy && !scaling && !isOutOfBounds && equalFormats && !alpha0xFF && equalSlice && smallMargin && !flipX && !flipY)
574 		{
575 			byte *sourceBuffer = isStencil ? (byte*)source->lockStencil(0, 0, 0, PUBLIC) : (byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
576 			byte *destBuffer = isStencil ? (byte*)dest->lockStencil(0, 0, 0, PUBLIC) : (byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
577 
578 			memcpy(destBuffer, sourceBuffer, sourceSliceB);
579 
580 			isStencil ? source->unlockStencil() : source->unlockInternal();
581 			isStencil ? dest->unlockStencil() : dest->unlockInternal();
582 		}
583 		else if(isDepth && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
584 		{
585 			byte *sourceBuffer = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC);
586 			byte *destBuffer = (byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
587 
588 			copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
589 
590 			source->unlockInternal();
591 			dest->unlockInternal();
592 		}
593 		else if((flags & Device::COLOR_BUFFER) && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
594 		{
595 			byte *sourceBytes = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
596 			byte *destBytes = (byte*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
597 
598 			unsigned int width = dRect.x1 - dRect.x0;
599 			unsigned int height = dRect.y1 - dRect.y0;
600 
601 			copyBuffer(sourceBytes, destBytes, width, height, sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
602 
603 			if(alpha0xFF)
604 			{
605 				for(unsigned int y = 0; y < height; y++)
606 				{
607 					for(unsigned int x = 0; x < width; x++)
608 					{
609 						destBytes[4 * x + 3] = 0xFF;
610 					}
611 
612 					destBytes += destPitchB;
613 				}
614 			}
615 
616 			source->unlockInternal();
617 			dest->unlockInternal();
618 		}
619 		else if(isColor || isDepth || isStencil)
620 		{
621 			if(flipX)
622 			{
623 				swap(dRect.x0, dRect.x1);
624 			}
625 			if(flipY)
626 			{
627 				swap(dRect.y0, dRect.y1);
628 			}
629 
630 			blit(source, sRect, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil);
631 		}
632 		else UNREACHABLE(false);
633 
634 		return true;
635 	}
636 
stretchCube(sw::Surface * source,sw::Surface * dest)637 	bool Device::stretchCube(sw::Surface *source, sw::Surface *dest)
638 	{
639 		if(!source || !dest || Surface::isDepth(source->getInternalFormat()) || Surface::isStencil(source->getInternalFormat()))
640 		{
641 			ERR("Invalid parameters");
642 			return false;
643 		}
644 
645 		int sWidth  = source->getWidth();
646 		int sHeight = source->getHeight();
647 		int sDepth  = source->getDepth();
648 		int dWidth  = dest->getWidth();
649 		int dHeight = dest->getHeight();
650 		int dDepth  = dest->getDepth();
651 
652 		if((sWidth == 0) || (sHeight == 0) || (sDepth == 0) ||
653 		   (dWidth == 0) || (dHeight == 0) || (dDepth == 0))
654 		{
655 			return true; // no work to do
656 		}
657 
658 		bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);
659 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
660 		bool alpha0xFF = false;
661 
662 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
663 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
664 		{
665 			equalFormats = true;
666 			alpha0xFF = true;
667 		}
668 
669 		if(!scaling && equalFormats)
670 		{
671 			unsigned int sourcePitch = source->getInternalPitchB();
672 			unsigned int destPitch = dest->getInternalPitchB();
673 			unsigned int bytes = dWidth * Surface::bytes(source->getInternalFormat());
674 
675 			for(int z = 0; z < dDepth; z++)
676 			{
677 				unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);
678 				unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);
679 
680 				for(int y = 0; y < dHeight; y++)
681 				{
682 					memcpy(destBytes, sourceBytes, bytes);
683 
684 					if(alpha0xFF)
685 					{
686 						for(int x = 0; x < dWidth; x++)
687 						{
688 							destBytes[4 * x + 3] = 0xFF;
689 						}
690 					}
691 
692 					sourceBytes += sourcePitch;
693 					destBytes += destPitch;
694 				}
695 
696 				source->unlockInternal();
697 				dest->unlockInternal();
698 			}
699 		}
700 		else
701 		{
702 			blit3D(source, dest);
703 		}
704 
705 		return true;
706 	}
707 
bindResources()708 	bool Device::bindResources()
709 	{
710 		if(!bindViewport())
711 		{
712 			return false;   // Zero-area target region
713 		}
714 
715 		bindShaderConstants();
716 
717 		return true;
718 	}
719 
bindShaderConstants()720 	void Device::bindShaderConstants()
721 	{
722 		if(pixelShaderDirty)
723 		{
724 			if(pixelShader)
725 			{
726 				if(pixelShaderConstantsFDirty)
727 				{
728 					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
729 				}
730 
731 				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF
732 				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
733 			}
734 			else
735 			{
736 				setPixelShader(0);
737 			}
738 
739 			pixelShaderDirty = false;
740 		}
741 
742 		if(vertexShaderDirty)
743 		{
744 			if(vertexShader)
745 			{
746 				if(vertexShaderConstantsFDirty)
747 				{
748 					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
749 				}
750 
751 				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF
752 				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
753 			}
754 			else
755 			{
756 				setVertexShader(0);
757 			}
758 
759 			vertexShaderDirty = false;
760 		}
761 	}
762 
bindViewport()763 	bool Device::bindViewport()
764 	{
765 		if(viewport.width <= 0 || viewport.height <= 0)
766 		{
767 			return false;
768 		}
769 
770 		if(scissorEnable)
771 		{
772 			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
773 			{
774 				return false;
775 			}
776 
777 			sw::Rect scissor;
778 			scissor.x0 = scissorRect.x0;
779 			scissor.x1 = scissorRect.x1;
780 			scissor.y0 = scissorRect.y0;
781 			scissor.y1 = scissorRect.y1;
782 
783 			setScissor(scissor);
784 		}
785 		else
786 		{
787 			sw::Rect scissor;
788 			scissor.x0 = viewport.x0;
789 			scissor.x1 = viewport.x0 + viewport.width;
790 			scissor.y0 = viewport.y0;
791 			scissor.y1 = viewport.y0 + viewport.height;
792 
793 			for(int i = 0; i < RENDERTARGETS; ++i)
794 			{
795 				if(renderTarget[i])
796 				{
797 					scissor.x0 = max(scissor.x0, 0);
798 					scissor.x1 = min(scissor.x1, renderTarget[i]->getWidth());
799 					scissor.y0 = max(scissor.y0, 0);
800 					scissor.y1 = min(scissor.y1, renderTarget[i]->getHeight());
801 				}
802 			}
803 
804 			if(depthBuffer)
805 			{
806 				scissor.x0 = max(scissor.x0, 0);
807 				scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
808 				scissor.y0 = max(scissor.y0, 0);
809 				scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
810 			}
811 
812 			if(stencilBuffer)
813 			{
814 				scissor.x0 = max(scissor.x0, 0);
815 				scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
816 				scissor.y0 = max(scissor.y0, 0);
817 				scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
818 			}
819 
820 			setScissor(scissor);
821 		}
822 
823 		sw::Viewport view;
824 		view.x0 = (float)viewport.x0;
825 		view.y0 = (float)viewport.y0;
826 		view.width = (float)viewport.width;
827 		view.height = (float)viewport.height;
828 		view.minZ = viewport.minZ;
829 		view.maxZ = viewport.maxZ;
830 
831 		Renderer::setViewport(view);
832 
833 		return true;
834 	}
835 
validRectangle(const sw::Rect * rect,sw::Surface * surface)836 	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
837 	{
838 		if(!rect)
839 		{
840 			return true;
841 		}
842 
843 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
844 		{
845 			return false;
846 		}
847 
848 		if(rect->x0 < 0 || rect->y0 < 0)
849 		{
850 			return false;
851 		}
852 
853 		if(rect->x1 >(int)surface->getWidth() || rect->y1 >(int)surface->getHeight())
854 		{
855 			return false;
856 		}
857 
858 		return true;
859 	}
860 
validRectangle(const sw::RectF * rect,sw::Surface * surface)861 	bool Device::validRectangle(const sw::RectF *rect, sw::Surface *surface)
862 	{
863 		if(!rect)
864 		{
865 			return true;
866 		}
867 
868 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
869 		{
870 			return false;
871 		}
872 
873 		return true;
874 	}
875 
ClipDstRect(sw::RectF & srcRect,sw::Rect & dstRect,sw::Rect & clipRect,bool flipX,bool flipY)876 	void Device::ClipDstRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
877 	{
878 		if(dstRect.x0 < clipRect.x0)
879 		{
880 			float offset = (static_cast<float>(clipRect.x0 - dstRect.x0) / static_cast<float>(dstRect.width())) * srcRect.width();
881 			if(flipX)
882 			{
883 				srcRect.x1 -= offset;
884 			}
885 			else
886 			{
887 				srcRect.x0 += offset;
888 			}
889 			dstRect.x0 = clipRect.x0;
890 		}
891 		if(dstRect.x1 > clipRect.x1)
892 		{
893 			float offset = (static_cast<float>(dstRect.x1 - clipRect.x1) / static_cast<float>(dstRect.width())) * srcRect.width();
894 			if(flipX)
895 			{
896 				srcRect.x0 += offset;
897 			}
898 			else
899 			{
900 				srcRect.x1 -= offset;
901 			}
902 			dstRect.x1 = clipRect.x1;
903 		}
904 		if(dstRect.y0 < clipRect.y0)
905 		{
906 			float offset = (static_cast<float>(clipRect.y0 - dstRect.y0) / static_cast<float>(dstRect.height())) * srcRect.height();
907 			if(flipY)
908 			{
909 				srcRect.y1 -= offset;
910 			}
911 			else
912 			{
913 				srcRect.y0 += offset;
914 			}
915 			dstRect.y0 = clipRect.y0;
916 		}
917 		if(dstRect.y1 > clipRect.y1)
918 		{
919 			float offset = (static_cast<float>(dstRect.y1 - clipRect.y1) / static_cast<float>(dstRect.height())) * srcRect.height();
920 			if(flipY)
921 			{
922 				srcRect.y0 += offset;
923 			}
924 			else
925 			{
926 				srcRect.y1 -= offset;
927 			}
928 			dstRect.y1 = clipRect.y1;
929 		}
930 	}
931 
ClipSrcRect(sw::RectF & srcRect,sw::Rect & dstRect,sw::Rect & clipRect,bool flipX,bool flipY)932 	void Device::ClipSrcRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
933 	{
934 		if(srcRect.x0 < static_cast<float>(clipRect.x0))
935 		{
936 			float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
937 			float offsetf = roundf((static_cast<float>(clipRect.x0) - srcRect.x0) * ratio);
938 			int offset = static_cast<int>(offsetf);
939 			if(flipX)
940 			{
941 				dstRect.x1 -= offset;
942 			}
943 			else
944 			{
945 				dstRect.x0 += offset;
946 			}
947 			srcRect.x0 += offsetf / ratio;
948 		}
949 		if(srcRect.x1 > static_cast<float>(clipRect.x1))
950 		{
951 			float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
952 			float offsetf = roundf((srcRect.x1 - static_cast<float>(clipRect.x1)) * ratio);
953 			int offset = static_cast<int>(offsetf);
954 			if(flipX)
955 			{
956 				dstRect.x0 += offset;
957 			}
958 			else
959 			{
960 				dstRect.x1 -= offset;
961 			}
962 			srcRect.x1 -= offsetf / ratio;
963 		}
964 		if(srcRect.y0 < static_cast<float>(clipRect.y0))
965 		{
966 			float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
967 			float offsetf = roundf((static_cast<float>(clipRect.y0) - srcRect.y0) * ratio);
968 			int offset = static_cast<int>(offsetf);
969 			if(flipY)
970 			{
971 				dstRect.y1 -= offset;
972 			}
973 			else
974 			{
975 				dstRect.y0 += offset;
976 			}
977 			srcRect.y0 += offsetf / ratio;
978 		}
979 		if(srcRect.y1 > static_cast<float>(clipRect.y1))
980 		{
981 			float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
982 			float offsetf = roundf((srcRect.y1 - static_cast<float>(clipRect.y1)) * ratio);
983 			int offset = static_cast<int>(offsetf);
984 			if(flipY)
985 			{
986 				dstRect.y0 += offset;
987 			}
988 			else
989 			{
990 				dstRect.y1 -= offset;
991 			}
992 			srcRect.y1 -= offsetf / ratio;
993 		}
994 	}
995 
finish()996 	void Device::finish()
997 	{
998 		synchronize();
999 	}
1000 }
1001