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 es2
32 {
33 	using namespace sw;
34 
Device(Context * context)35 	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
36 	{
37 		for(int i = 0; i < RENDERTARGETS; i++)
38 		{
39 			renderTarget[i] = nullptr;
40 		}
41 
42 		depthBuffer = nullptr;
43 		stencilBuffer = nullptr;
44 
45 		setDepthBufferEnable(true);
46 		setFillMode(FILL_SOLID);
47 		setShadingMode(SHADING_GOURAUD);
48 		setDepthWriteEnable(true);
49 		setAlphaTestEnable(false);
50 		setSourceBlendFactor(BLEND_ONE);
51 		setDestBlendFactor(BLEND_ZERO);
52 		setCullMode(CULL_COUNTERCLOCKWISE);
53 		setDepthCompare(DEPTH_LESSEQUAL);
54 		setAlphaReference(0.0f);
55 		setAlphaCompare(ALPHA_ALWAYS);
56 		setAlphaBlendEnable(false);
57 		setFogEnable(false);
58 		setSpecularEnable(false);
59 		setFogColor(0);
60 		setPixelFogMode(FOG_NONE);
61 		setFogStart(0.0f);
62 		setFogEnd(1.0f);
63 		setFogDensity(1.0f);
64 		setRangeFogEnable(false);
65 		setStencilEnable(false);
66 		setStencilFailOperation(OPERATION_KEEP);
67 		setStencilZFailOperation(OPERATION_KEEP);
68 		setStencilPassOperation(OPERATION_KEEP);
69 		setStencilCompare(STENCIL_ALWAYS);
70 		setStencilReference(0);
71 		setStencilMask(0xFFFFFFFF);
72 		setStencilWriteMask(0xFFFFFFFF);
73 		setVertexFogMode(FOG_NONE);
74 		setClipFlags(0);
75 		setPointSize(1.0f);
76 		setPointSizeMin(0.125f);
77         setPointSizeMax(8192.0f);
78 		setBlendOperation(BLENDOP_ADD);
79 		scissorEnable = false;
80 		setSlopeDepthBias(0.0f);
81 		setTwoSidedStencil(false);
82 		setStencilFailOperationCCW(OPERATION_KEEP);
83 		setStencilZFailOperationCCW(OPERATION_KEEP);
84 		setStencilPassOperationCCW(OPERATION_KEEP);
85 		setStencilCompareCCW(STENCIL_ALWAYS);
86 		setBlendConstant(0xFFFFFFFF);
87 		setWriteSRGB(false);
88 		setDepthBias(0.0f);
89 		setSeparateAlphaBlendEnable(false);
90 		setSourceBlendFactorAlpha(BLEND_ONE);
91 		setDestBlendFactorAlpha(BLEND_ZERO);
92 		setBlendOperationAlpha(BLENDOP_ADD);
93 		setPointSpriteEnable(true);
94 		setColorLogicOpEnabled(false);
95 		setLogicalOperation(LOGICALOP_COPY);
96 
97 		for(int i = 0; i < 16; i++)
98 		{
99 			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
100 			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
101 			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
102 			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
103 			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
104 			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
105 			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
106 		}
107 
108 		for(int i = 0; i < 4; i++)
109 		{
110 			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
111 			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
112 			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
113 			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
114 			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
115 			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
116 			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
117 		}
118 
119 		for(int i = 0; i < 6; i++)
120 		{
121 			float plane[4] = {0, 0, 0, 0};
122 
123 			setClipPlane(i, plane);
124 		}
125 
126 		pixelShader = nullptr;
127 		vertexShader = nullptr;
128 
129 		pixelShaderDirty = true;
130 		pixelShaderConstantsFDirty = 0;
131 		vertexShaderDirty = true;
132 		vertexShaderConstantsFDirty = 0;
133 
134 		for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++)
135 		{
136 			float zero[4] = {0, 0, 0, 0};
137 
138 			setPixelShaderConstantF(i, zero, 1);
139 		}
140 
141 		for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++)
142 		{
143 			float zero[4] = {0, 0, 0, 0};
144 
145 			setVertexShaderConstantF(i, zero, 1);
146 		}
147 	}
148 
~Device()149 	Device::~Device()
150 	{
151 		for(int i = 0; i < RENDERTARGETS; i++)
152 		{
153 			if(renderTarget[i])
154 			{
155 				renderTarget[i]->release();
156 				renderTarget[i] = nullptr;
157 			}
158 		}
159 
160 		if(depthBuffer)
161 		{
162 			depthBuffer->release();
163 			depthBuffer = nullptr;
164 		}
165 
166 		if(stencilBuffer)
167 		{
168 			stencilBuffer->release();
169 			stencilBuffer = nullptr;
170 		}
171 
172 		delete context;
173 	}
174 
clearColor(float red,float green,float blue,float alpha,unsigned int rgbaMask)175 	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
176 	{
177 		if(!rgbaMask)
178 		{
179 			return;
180 		}
181 
182 		float rgba[4];
183 		rgba[0] = red;
184 		rgba[1] = green;
185 		rgba[2] = blue;
186 		rgba[3] = alpha;
187 
188 		for(int i = 0; i < RENDERTARGETS; ++i)
189 		{
190 			if(renderTarget[i])
191 			{
192 				sw::SliceRect clearRect = renderTarget[i]->getRect();
193 
194 				if(scissorEnable)
195 				{
196 					clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
197 				}
198 
199 				int depth = sw::max(renderTarget[i]->getDepth(), 1);
200 				for(clearRect.slice = 0; clearRect.slice < depth; clearRect.slice++)
201 				{
202 					clear(rgba, FORMAT_A32B32G32R32F, renderTarget[i], clearRect, rgbaMask);
203 				}
204 			}
205 		}
206 	}
207 
clearDepth(float z)208 	void Device::clearDepth(float z)
209 	{
210 		if(!depthBuffer)
211 		{
212 			return;
213 		}
214 
215 		z = clamp01(z);
216 		sw::SliceRect clearRect = depthBuffer->getRect();
217 
218 		if(scissorEnable)
219 		{
220 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
221 		}
222 
223 		depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
224 	}
225 
clearStencil(unsigned int stencil,unsigned int mask)226 	void Device::clearStencil(unsigned int stencil, unsigned int mask)
227 	{
228 		if(!stencilBuffer)
229 		{
230 			return;
231 		}
232 
233 		sw::SliceRect clearRect = stencilBuffer->getRect();
234 
235 		if(scissorEnable)
236 		{
237 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
238 		}
239 
240 		stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
241 	}
242 
createDepthStencilSurface(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool discard)243 	egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
244 	{
245 		if(height > OUTLINE_RESOLUTION)
246 		{
247 			ERR("Invalid parameters: %dx%d", width, height);
248 			return nullptr;
249 		}
250 
251 		bool lockable = true;
252 
253 		switch(format)
254 		{
255 	//	case FORMAT_D15S1:
256 		case FORMAT_D24S8:
257 		case FORMAT_D24X8:
258 	//	case FORMAT_D24X4S4:
259 		case FORMAT_D24FS8:
260 		case FORMAT_D32:
261 		case FORMAT_D16:
262 		case FORMAT_D32F:
263 		case FORMAT_D32F_COMPLEMENTARY:
264 			lockable = false;
265 			break;
266 	//	case FORMAT_S8_LOCKABLE:
267 	//	case FORMAT_D16_LOCKABLE:
268 		case FORMAT_D32F_LOCKABLE:
269 	//	case FORMAT_D32_LOCKABLE:
270 		case FORMAT_DF24S8:
271 		case FORMAT_DF16S8:
272 		case FORMAT_D32FS8_TEXTURE:
273 		case FORMAT_D32FS8_SHADOW:
274 			lockable = true;
275 			break;
276 		default:
277 			UNREACHABLE(format);
278 		}
279 
280 		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
281 
282 		if(!surface)
283 		{
284 			ERR("Out of memory");
285 			return nullptr;
286 		}
287 
288 		return surface;
289 	}
290 
createRenderTarget(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool lockable)291 	egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
292 	{
293 		if(height > OUTLINE_RESOLUTION)
294 		{
295 			ERR("Invalid parameters: %dx%d", width, height);
296 			return nullptr;
297 		}
298 
299 		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
300 
301 		if(!surface)
302 		{
303 			ERR("Out of memory");
304 			return nullptr;
305 		}
306 
307 		return surface;
308 	}
309 
drawIndexedPrimitive(sw::DrawType type,unsigned int indexOffset,unsigned int primitiveCount)310 	void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
311 	{
312 		if(!bindResources() || !primitiveCount)
313 		{
314 			return;
315 		}
316 
317 		draw(type, indexOffset, primitiveCount);
318 	}
319 
drawPrimitive(sw::DrawType type,unsigned int primitiveCount)320 	void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
321 	{
322 		if(!bindResources() || !primitiveCount)
323 		{
324 			return;
325 		}
326 
327 		setIndexBuffer(nullptr);
328 
329 		draw(type, 0, primitiveCount);
330 	}
331 
setPixelShader(PixelShader * pixelShader)332 	void Device::setPixelShader(PixelShader *pixelShader)
333 	{
334 		this->pixelShader = pixelShader;
335 		pixelShaderDirty = true;
336 	}
337 
setPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)338 	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
339 	{
340 		for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++)
341 		{
342 			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
343 			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
344 			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
345 			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
346 		}
347 
348 		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
349 		pixelShaderDirty = true;   // Reload DEF constants
350 	}
351 
setScissorEnable(bool enable)352 	void Device::setScissorEnable(bool enable)
353 	{
354 		scissorEnable = enable;
355 	}
356 
setRenderTarget(int index,egl::Image * renderTarget)357 	void Device::setRenderTarget(int index, egl::Image *renderTarget)
358 	{
359 		if(renderTarget)
360 		{
361 			renderTarget->addRef();
362 		}
363 
364 		if(this->renderTarget[index])
365 		{
366 			this->renderTarget[index]->release();
367 		}
368 
369 		this->renderTarget[index] = renderTarget;
370 
371 		Renderer::setRenderTarget(index, renderTarget);
372 	}
373 
setDepthBuffer(egl::Image * depthBuffer)374 	void Device::setDepthBuffer(egl::Image *depthBuffer)
375 	{
376 		if(this->depthBuffer == depthBuffer)
377 		{
378 			return;
379 		}
380 
381 		if(depthBuffer)
382 		{
383 			depthBuffer->addRef();
384 		}
385 
386 		if(this->depthBuffer)
387 		{
388 			this->depthBuffer->release();
389 		}
390 
391 		this->depthBuffer = depthBuffer;
392 
393 		Renderer::setDepthBuffer(depthBuffer);
394 	}
395 
setStencilBuffer(egl::Image * stencilBuffer)396 	void Device::setStencilBuffer(egl::Image *stencilBuffer)
397 	{
398 		if(this->stencilBuffer == stencilBuffer)
399 		{
400 			return;
401 		}
402 
403 		if(stencilBuffer)
404 		{
405 			stencilBuffer->addRef();
406 		}
407 
408 		if(this->stencilBuffer)
409 		{
410 			this->stencilBuffer->release();
411 		}
412 
413 		this->stencilBuffer = stencilBuffer;
414 
415 		Renderer::setStencilBuffer(stencilBuffer);
416 	}
417 
setScissorRect(const sw::Rect & rect)418 	void Device::setScissorRect(const sw::Rect &rect)
419 	{
420 		scissorRect = rect;
421 	}
422 
setVertexShader(VertexShader * vertexShader)423 	void Device::setVertexShader(VertexShader *vertexShader)
424 	{
425 		this->vertexShader = vertexShader;
426 		vertexShaderDirty = true;
427 	}
428 
setVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)429 	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
430 	{
431 		for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++)
432 		{
433 			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
434 			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
435 			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
436 			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
437 		}
438 
439 		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
440 		vertexShaderDirty = true;   // Reload DEF constants
441 	}
442 
setViewport(const Viewport & viewport)443 	void Device::setViewport(const Viewport &viewport)
444 	{
445 		this->viewport = viewport;
446 	}
447 
copyBuffer(sw::byte * sourceBuffer,sw::byte * destBuffer,unsigned int width,unsigned int height,unsigned int sourcePitch,unsigned int destPitch,unsigned int bytes,bool flipX,bool flipY)448 	void Device::copyBuffer(sw::byte *sourceBuffer, sw::byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY)
449 	{
450 		unsigned int widthB = width * bytes;
451 		unsigned int widthMaxB = widthB - 1;
452 
453 		if(flipX)
454 		{
455 			if(flipY)
456 			{
457 				sourceBuffer += (height - 1) * sourcePitch;
458 				for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
459 				{
460 					for(unsigned int x = 0; x < widthB; ++x)
461 					{
462 						destBuffer[x] = sourceBuffer[widthMaxB - x];
463 					}
464 				}
465 			}
466 			else
467 			{
468 				for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
469 				{
470 					for(unsigned int x = 0; x < widthB; ++x)
471 					{
472 						destBuffer[x] = sourceBuffer[widthMaxB - x];
473 					}
474 				}
475 			}
476 		}
477 		else
478 		{
479 			if(flipY)
480 			{
481 				sourceBuffer += (height - 1) * sourcePitch;
482 				for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
483 				{
484 					memcpy(destBuffer, sourceBuffer, widthB);
485 				}
486 			}
487 			else
488 			{
489 				for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
490 				{
491 					memcpy(destBuffer, sourceBuffer, widthB);
492 				}
493 			}
494 		}
495 	}
496 
stretchRect(sw::Surface * source,const sw::SliceRect * sourceRect,sw::Surface * dest,const sw::SliceRect * destRect,bool filter)497 	bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
498 	{
499 		if(!source || !dest)
500 		{
501 			ERR("Invalid parameters");
502 			return false;
503 		}
504 
505 		int sWidth = source->getWidth();
506 		int sHeight = source->getHeight();
507 		int dWidth = dest->getWidth();
508 		int dHeight = dest->getHeight();
509 
510 		bool flipX = false;
511 		bool flipY = false;
512 		if(sourceRect && destRect)
513 		{
514 			flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1);
515 			flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1);
516 		}
517 		else if(sourceRect)
518 		{
519 			flipX = (sourceRect->x0 > sourceRect->x1);
520 			flipY = (sourceRect->y0 > sourceRect->y1);
521 		}
522 		else if(destRect)
523 		{
524 			flipX = (destRect->x0 > destRect->x1);
525 			flipY = (destRect->y0 > destRect->y1);
526 		}
527 
528 		SliceRect sRect;
529 		SliceRect dRect;
530 
531 		if(sourceRect)
532 		{
533 			sRect = *sourceRect;
534 
535 			if(sRect.x0 > sRect.x1)
536 			{
537 				swap(sRect.x0, sRect.x1);
538 			}
539 
540 			if(sRect.y0 > sRect.y1)
541 			{
542 				swap(sRect.y0, sRect.y1);
543 			}
544 		}
545 		else
546 		{
547 			sRect.y0 = 0;
548 			sRect.x0 = 0;
549 			sRect.y1 = sHeight;
550 			sRect.x1 = sWidth;
551 		}
552 
553 		if(destRect)
554 		{
555 			dRect = *destRect;
556 
557 			if(dRect.x0 > dRect.x1)
558 			{
559 				swap(dRect.x0, dRect.x1);
560 			}
561 
562 			if(dRect.y0 > dRect.y1)
563 			{
564 				swap(dRect.y0, dRect.y1);
565 			}
566 		}
567 		else
568 		{
569 			dRect.y0 = 0;
570 			dRect.x0 = 0;
571 			dRect.y1 = dHeight;
572 			dRect.x1 = dWidth;
573 		}
574 
575 		if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest))
576 		{
577 			ERR("Invalid parameters");
578 			return false;
579 		}
580 
581 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
582 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
583 		bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
584 		bool alpha0xFF = false;
585 
586 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
587 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
588 		{
589 			equalFormats = true;
590 			alpha0xFF = true;
591 		}
592 
593 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
594 		{
595 			if(source->hasDepth())
596 			{
597 				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sourceRect->slice, LOCK_READONLY, PUBLIC);
598 				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, destRect->slice, LOCK_DISCARD, PUBLIC);
599 
600 				copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY);
601 
602 				source->unlockInternal();
603 				dest->unlockInternal();
604 			}
605 
606 			if(source->hasStencil())
607 			{
608 				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
609 				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
610 
611 				copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY);
612 
613 				source->unlockStencil();
614 				dest->unlockStencil();
615 			}
616 		}
617 		else if(!scaling && equalFormats)
618 		{
619 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
620 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, LOCK_READWRITE, PUBLIC);
621 			unsigned int sourcePitch = source->getInternalPitchB();
622 			unsigned int destPitch = dest->getInternalPitchB();
623 
624 			unsigned int width = dRect.x1 - dRect.x0;
625 			unsigned int height = dRect.y1 - dRect.y0;
626 
627 			copyBuffer(sourceBytes, destBytes, width, height, sourcePitch, destPitch, egl::Image::bytes(source->getInternalFormat()), flipX, flipY);
628 
629 			if(alpha0xFF)
630 			{
631 				for(unsigned int y = 0; y < height; ++y, destBytes += destPitch)
632 				{
633 					for(unsigned int x = 0; x < width; ++x)
634 					{
635 						destBytes[4 * x + 3] = 0xFF;
636 					}
637 				}
638 			}
639 
640 			source->unlockInternal();
641 			dest->unlockInternal();
642 		}
643 		else
644 		{
645 			if(flipX)
646 			{
647 				swap(dRect.x0, dRect.x1);
648 			}
649 			if(flipY)
650 			{
651 				swap(dRect.y0, dRect.y1);
652 			}
653 			blit(source, sRect, dest, dRect, scaling && filter);
654 		}
655 
656 		return true;
657 	}
658 
stretchCube(sw::Surface * source,sw::Surface * dest)659 	bool Device::stretchCube(sw::Surface *source, sw::Surface *dest)
660 	{
661 		if(!source || !dest || egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()))
662 		{
663 			ERR("Invalid parameters");
664 			return false;
665 		}
666 
667 		int sWidth  = source->getWidth();
668 		int sHeight = source->getHeight();
669 		int sDepth  = source->getDepth();
670 		int dWidth  = dest->getWidth();
671 		int dHeight = dest->getHeight();
672 		int dDepth  = dest->getDepth();
673 
674 		bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);
675 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
676 		bool alpha0xFF = false;
677 
678 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
679 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
680 		{
681 			equalFormats = true;
682 			alpha0xFF = true;
683 		}
684 
685 		if(!scaling && equalFormats)
686 		{
687 			unsigned int sourcePitch = source->getInternalPitchB();
688 			unsigned int destPitch = dest->getInternalPitchB();
689 			unsigned int bytes = dWidth * egl::Image::bytes(source->getInternalFormat());
690 
691 			for(int z = 0; z < dDepth; ++z)
692 			{
693 				unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);
694 				unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);
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 
712 			source->unlockInternal();
713 			dest->unlockInternal();
714 		}
715 		else
716 		{
717 			blit3D(source, dest);
718 		}
719 
720 		return true;
721 	}
722 
bindResources()723 	bool Device::bindResources()
724 	{
725 		if(!bindViewport())
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 			setScissor(scissor);
836 		}
837 
838 		sw::Viewport view;
839 		view.x0 = (float)viewport.x0;
840 		view.y0 = (float)viewport.y0;
841 		view.width = (float)viewport.width;
842 		view.height = (float)viewport.height;
843 		view.minZ = viewport.minZ;
844 		view.maxZ = viewport.maxZ;
845 
846 		Renderer::setViewport(view);
847 
848 		return true;
849 	}
850 
validRectangle(const sw::Rect * rect,sw::Surface * surface)851 	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
852 	{
853 		if(!rect)
854 		{
855 			return true;
856 		}
857 
858 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
859 		{
860 			return false;
861 		}
862 
863 		if(rect->x0 < 0 || rect->y0 < 0)
864 		{
865 			return false;
866 		}
867 
868 		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
869 		{
870 			return false;
871 		}
872 
873 		return true;
874 	}
875 
finish()876 	void Device::finish()
877 	{
878 		synchronize();
879 	}
880 }
881