• 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 "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 gl
32 {
33 	using namespace sw;
34 
Device(Context * context)35 	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
36 	{
37 		depthStencil = 0;
38 		renderTarget = 0;
39 
40 		setDepthBufferEnable(true);
41 		setFillMode(FILL_SOLID);
42 		setShadingMode(SHADING_GOURAUD);
43 		setDepthWriteEnable(true);
44 		setAlphaTestEnable(false);
45 		setSourceBlendFactor(BLEND_ONE);
46 		setDestBlendFactor(BLEND_ZERO);
47 		setCullMode(CULL_COUNTERCLOCKWISE);
48 		setDepthCompare(DEPTH_LESSEQUAL);
49 		setAlphaReference(0.0f);
50 		setAlphaCompare(ALPHA_ALWAYS);
51 		setAlphaBlendEnable(false);
52 		setFogEnable(false);
53 		setSpecularEnable(false);
54 		setFogColor(0);
55 		setPixelFogMode(FOG_NONE);
56 		setFogStart(0.0f);
57 		setFogEnd(1.0f);
58 		setFogDensity(1.0f);
59 		setRangeFogEnable(false);
60 		setStencilEnable(false);
61 		setStencilFailOperation(OPERATION_KEEP);
62 		setStencilZFailOperation(OPERATION_KEEP);
63 		setStencilPassOperation(OPERATION_KEEP);
64 		setStencilCompare(STENCIL_ALWAYS);
65 		setStencilReference(0);
66 		setStencilMask(0xFFFFFFFF);
67 		setStencilWriteMask(0xFFFFFFFF);
68 		setVertexFogMode(FOG_NONE);
69 		setClipFlags(0);
70 		setPointSize(1.0f);
71 		setPointSizeMin(0.125f);
72 		setPointSizeMax(8192.0f);
73 		setColorWriteMask(0, 0x0000000F);
74 		setBlendOperation(BLENDOP_ADD);
75 		scissorEnable = false;
76 		setSlopeDepthBias(0.0f);
77 		setTwoSidedStencil(false);
78 		setStencilFailOperationCCW(OPERATION_KEEP);
79 		setStencilZFailOperationCCW(OPERATION_KEEP);
80 		setStencilPassOperationCCW(OPERATION_KEEP);
81 		setStencilCompareCCW(STENCIL_ALWAYS);
82 		setColorWriteMask(1, 0x0000000F);
83 		setColorWriteMask(2, 0x0000000F);
84 		setColorWriteMask(3, 0x0000000F);
85 		setBlendConstant(0xFFFFFFFF);
86 		setWriteSRGB(false);
87 		setDepthBias(0.0f);
88 		setSeparateAlphaBlendEnable(false);
89 		setSourceBlendFactorAlpha(BLEND_ONE);
90 		setDestBlendFactorAlpha(BLEND_ZERO);
91 		setBlendOperationAlpha(BLENDOP_ADD);
92 		setPointSpriteEnable(true);
93 		setColorLogicOpEnabled(false);
94 		setLogicalOperation(LOGICALOP_COPY);
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 		pixelShader = 0;
126 		vertexShader = 0;
127 
128 		pixelShaderDirty = true;
129 		pixelShaderConstantsFDirty = 0;
130 		vertexShaderDirty = true;
131 		vertexShaderConstantsFDirty = 0;
132 
133 		for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++)
134 		{
135 			float zero[4] = {0, 0, 0, 0};
136 
137 			setPixelShaderConstantF(i, zero, 1);
138 		}
139 
140 		for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++)
141 		{
142 			float zero[4] = {0, 0, 0, 0};
143 
144 			setVertexShaderConstantF(i, zero, 1);
145 		}
146 
147 		setLightingEnable(false);
148 
149 		setGlobalAmbient(sw::Color<float>(0.2f, 0.2f, 0.2f, 1.0f));
150 		setMaterialAmbient(sw::Color<float>(0.2f, 0.2f, 0.2f, 1.0f));
151 		setMaterialDiffuse(sw::Color<float>(0.8f, 0.8f, 0.8f, 1.0f));
152 		setMaterialSpecular(sw::Color<float>(0.0f, 0.0f, 0.0f, 1.0f));
153 		setMaterialEmission(sw::Color<float>(0.0f, 0.0f, 0.0f, 1.0f));
154 
155 		for(int i = 0; i < 8; i++)
156 		{
157 			setLightEnable(i, false);
158 			setLightAttenuation(i, 1.0f, 0.0f, 0.0f);
159 		}
160 
161 		setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
162 		setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
163 		setAmbientMaterialSource(sw::MATERIAL_COLOR1);
164 		setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
165 	}
166 
~Device()167 	Device::~Device()
168 	{
169 		if(depthStencil)
170 		{
171 			depthStencil->release();
172 			depthStencil = 0;
173 		}
174 
175 		if(renderTarget)
176 		{
177 			renderTarget->release();
178 			renderTarget = 0;
179 		}
180 
181 		delete context;
182 	}
183 
clearColor(float red,float green,float blue,float alpha,unsigned int rgbaMask)184 	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
185 	{
186 		if(!renderTarget || !rgbaMask)
187 		{
188 			return;
189 		}
190 
191 		sw::SliceRect clearRect = renderTarget->getRect();
192 
193 		if(scissorEnable)
194 		{
195 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
196 		}
197 
198 		float rgba[4];
199 		rgba[0] = red;
200 		rgba[1] = green;
201 		rgba[2] = blue;
202 		rgba[3] = alpha;
203 
204 		clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
205 	}
206 
clearDepth(float z)207 	void Device::clearDepth(float z)
208 	{
209 		if(!depthStencil)
210 		{
211 			return;
212 		}
213 
214 		z = clamp01(z);
215 		sw::SliceRect clearRect = depthStencil->getRect();
216 
217 		if(scissorEnable)
218 		{
219 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
220 		}
221 
222 		depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
223 	}
224 
clearStencil(unsigned int stencil,unsigned int mask)225 	void Device::clearStencil(unsigned int stencil, unsigned int mask)
226 	{
227 		if(!depthStencil)
228 		{
229 			return;
230 		}
231 
232 		sw::SliceRect clearRect = depthStencil->getRect();
233 
234 		if(scissorEnable)
235 		{
236 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
237 		}
238 
239 		depthStencil->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
240 	}
241 
createDepthStencilSurface(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool discard)242 	Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
243 	{
244 		if(height > OUTLINE_RESOLUTION)
245 		{
246 			ERR("Invalid parameters: %dx%d", width, height);
247 			return 0;
248 		}
249 
250 		bool lockable = true;
251 
252 		switch(format)
253 		{
254 	//	case FORMAT_D15S1:
255 		case FORMAT_D24S8:
256 		case FORMAT_D24X8:
257 	//	case FORMAT_D24X4S4:
258 		case FORMAT_D24FS8:
259 		case FORMAT_D32:
260 		case FORMAT_D16:
261 			lockable = false;
262 			break;
263 	//	case FORMAT_S8_LOCKABLE:
264 	//	case FORMAT_D16_LOCKABLE:
265 		case FORMAT_D32F_LOCKABLE:
266 	//	case FORMAT_D32_LOCKABLE:
267 		case FORMAT_DF24S8:
268 		case FORMAT_DF16S8:
269 			lockable = true;
270 			break;
271 		default:
272 			UNREACHABLE(format);
273 		}
274 
275 		Image *surface = new Image(0, width, height, format, multiSampleDepth, lockable, true);
276 
277 		if(!surface)
278 		{
279 			ERR("Out of memory");
280 			return 0;
281 		}
282 
283 		return surface;
284 	}
285 
createRenderTarget(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool lockable)286 	Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
287 	{
288 		if(height > OUTLINE_RESOLUTION)
289 		{
290 			ERR("Invalid parameters: %dx%d", width, height);
291 			return 0;
292 		}
293 
294 		Image *surface = new Image(0, width, height, format, multiSampleDepth, lockable, true);
295 
296 		if(!surface)
297 		{
298 			ERR("Out of memory");
299 			return 0;
300 		}
301 
302 		return surface;
303 	}
304 
drawIndexedPrimitive(PrimitiveType type,unsigned int indexOffset,unsigned int primitiveCount,int indexSize)305 	void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)
306 	{
307 		if(!bindResources() || !primitiveCount)
308 		{
309 			return;
310 		}
311 
312 		DrawType drawType;
313 
314 		if(indexSize == 4)
315 		{
316 			switch(type)
317 			{
318 			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
319 			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
320 			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
321 			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP32;      break;
322 			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
323 			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
324 			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;	  break;
325 			default: UNREACHABLE(type);
326 			}
327 		}
328 		else if(indexSize == 2)
329 		{
330 			switch(type)
331 			{
332 			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
333 			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
334 			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
335 			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP16;      break;
336 			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
337 			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
338 			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
339 			default: UNREACHABLE(type);
340 			}
341 		}
342 		else if(indexSize == 1)
343 		{
344 			switch(type)
345 			{
346 			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST8;     break;
347 			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST8;      break;
348 			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP8;     break;
349 			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP8;      break;
350 			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST8;  break;
351 			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP8; break;
352 			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN8;   break;
353 			default: UNREACHABLE(type);
354 			}
355 		}
356 		else UNREACHABLE(indexSize);
357 
358 		draw(drawType, indexOffset, primitiveCount);
359 	}
360 
drawPrimitive(PrimitiveType primitiveType,unsigned int primitiveCount)361 	void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)
362 	{
363 		if(!bindResources() || !primitiveCount)
364 		{
365 			return;
366 		}
367 
368 		setIndexBuffer(0);
369 
370 		DrawType drawType;
371 
372 		switch(primitiveType)
373 		{
374 		case DRAW_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
375 		case DRAW_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
376 		case DRAW_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
377 		case DRAW_LINELOOP:      drawType = sw::DRAW_LINELOOP;      break;
378 		case DRAW_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
379 		case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
380 		case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
381 		case DRAW_QUADLIST:      drawType = sw::DRAW_QUADLIST;      break;
382 		default: UNREACHABLE(primitiveType);
383 		}
384 
385 		draw(drawType, 0, primitiveCount);
386 	}
387 
setDepthStencilSurface(Image * depthStencil)388 	void Device::setDepthStencilSurface(Image *depthStencil)
389 	{
390 		if(this->depthStencil == depthStencil)
391 		{
392 			return;
393 		}
394 
395 		if(depthStencil)
396 		{
397 			depthStencil->addRef();
398 		}
399 
400 		if(this->depthStencil)
401 		{
402 			this->depthStencil->release();
403 		}
404 
405 		this->depthStencil = depthStencil;
406 
407 		setDepthBuffer(depthStencil);
408 		setStencilBuffer(depthStencil);
409 	}
410 
setPixelShader(PixelShader * pixelShader)411 	void Device::setPixelShader(PixelShader *pixelShader)
412 	{
413 		this->pixelShader = pixelShader;
414 		pixelShaderDirty = true;
415 	}
416 
setPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)417 	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
418 	{
419 		for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++)
420 		{
421 			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
422 			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
423 			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
424 			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
425 		}
426 
427 		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
428 		pixelShaderDirty = true;   // Reload DEF constants
429 	}
430 
setScissorEnable(bool enable)431 	void Device::setScissorEnable(bool enable)
432 	{
433 		scissorEnable = enable;
434 	}
435 
setRenderTarget(int index,Image * renderTarget)436 	void Device::setRenderTarget(int index, Image *renderTarget)
437 	{
438 		if(renderTarget)
439 		{
440 			renderTarget->addRef();
441 		}
442 
443 		if(this->renderTarget)
444 		{
445 			this->renderTarget->release();
446 		}
447 
448 		this->renderTarget = renderTarget;
449 
450 		Renderer::setRenderTarget(index, renderTarget);
451 	}
452 
setScissorRect(const sw::Rect & rect)453 	void Device::setScissorRect(const sw::Rect &rect)
454 	{
455 		scissorRect = rect;
456 	}
457 
setVertexShader(VertexShader * vertexShader)458 	void Device::setVertexShader(VertexShader *vertexShader)
459 	{
460 		this->vertexShader = vertexShader;
461 		vertexShaderDirty = true;
462 	}
463 
setVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)464 	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
465 	{
466 		for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++)
467 		{
468 			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
469 			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
470 			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
471 			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
472 		}
473 
474 		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
475 		vertexShaderDirty = true;   // Reload DEF constants
476 	}
477 
setViewport(const Viewport & viewport)478 	void Device::setViewport(const Viewport &viewport)
479 	{
480 		this->viewport = viewport;
481 	}
482 
stretchRect(Image * source,const sw::SliceRect * sourceRect,Image * dest,const sw::SliceRect * destRect,bool filter)483 	bool Device::stretchRect(Image *source, const sw::SliceRect *sourceRect, Image *dest, const sw::SliceRect *destRect, bool filter)
484 	{
485 		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
486 		{
487 			ERR("Invalid parameters");
488 			return false;
489 		}
490 
491 		int sWidth = source->getWidth();
492 		int sHeight = source->getHeight();
493 		int dWidth = dest->getWidth();
494 		int dHeight = dest->getHeight();
495 
496 		SliceRect sRect;
497 		SliceRect dRect;
498 
499 		if(sourceRect)
500 		{
501 			sRect = *sourceRect;
502 		}
503 		else
504 		{
505 			sRect.y0 = 0;
506 			sRect.x0 = 0;
507 			sRect.y1 = sHeight;
508 			sRect.x1 = sWidth;
509 		}
510 
511 		if(destRect)
512 		{
513 			dRect = *destRect;
514 		}
515 		else
516 		{
517 			dRect.y0 = 0;
518 			dRect.x0 = 0;
519 			dRect.y1 = dHeight;
520 			dRect.x1 = dWidth;
521 		}
522 
523 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
524 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
525 		bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());
526 		bool alpha0xFF = false;
527 
528 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
529 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
530 		{
531 			equalFormats = true;
532 			alpha0xFF = true;
533 		}
534 
535 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
536 		{
537 			if(source->hasDepth())
538 			{
539 				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
540 				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
541 
542 				unsigned int width = source->getWidth();
543 				unsigned int height = source->getHeight();
544 				unsigned int pitch = source->getInternalPitchB();
545 
546 				for(unsigned int y = 0; y < height; y++)
547 				{
548 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
549 
550 					sourceBuffer += pitch;
551 					destBuffer += pitch;
552 				}
553 
554 				source->unlockInternal();
555 				dest->unlockInternal();
556 			}
557 
558 			if(source->hasStencil())
559 			{
560 				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
561 				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
562 
563 				unsigned int width = source->getWidth();
564 				unsigned int height = source->getHeight();
565 				unsigned int pitch = source->getStencilPitchB();
566 
567 				for(unsigned int y = 0; y < height; y++)
568 				{
569 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
570 
571 					sourceBuffer += pitch;
572 					destBuffer += pitch;
573 				}
574 
575 				source->unlockStencil();
576 				dest->unlockStencil();
577 			}
578 		}
579 		else if(!scaling && equalFormats)
580 		{
581 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
582 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
583 			unsigned int sourcePitch = source->getInternalPitchB();
584 			unsigned int destPitch = dest->getInternalPitchB();
585 
586 			unsigned int width = dRect.x1 - dRect.x0;
587 			unsigned int height = dRect.y1 - dRect.y0;
588 			unsigned int bytes = width * Image::bytes(source->getInternalFormat());
589 
590 			for(unsigned int y = 0; y < height; y++)
591 			{
592 				memcpy(destBytes, sourceBytes, bytes);
593 
594 				if(alpha0xFF)
595 				{
596 					for(unsigned int x = 0; x < width; x++)
597 					{
598 						destBytes[4 * x + 3] = 0xFF;
599 					}
600 				}
601 
602 				sourceBytes += sourcePitch;
603 				destBytes += destPitch;
604 			}
605 
606 			source->unlockInternal();
607 			dest->unlockInternal();
608 		}
609 		else
610 		{
611 			blit(source, sRect, dest, dRect, scaling && filter);
612 		}
613 
614 		return true;
615 	}
616 
bindResources()617 	bool Device::bindResources()
618 	{
619 		if(!bindViewport())
620 		{
621 			return false;   // Zero-area target region
622 		}
623 
624 		bindShaderConstants();
625 
626 		return true;
627 	}
628 
bindShaderConstants()629 	void Device::bindShaderConstants()
630 	{
631 		if(pixelShaderDirty)
632 		{
633 			if(pixelShader)
634 			{
635 				if(pixelShaderConstantsFDirty)
636 				{
637 					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
638 				}
639 
640 				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF
641 				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
642 			}
643 			else
644 			{
645 				setPixelShader(0);
646 			}
647 
648 			pixelShaderDirty = false;
649 		}
650 
651 		if(vertexShaderDirty)
652 		{
653 			if(vertexShader)
654 			{
655 				if(vertexShaderConstantsFDirty)
656 				{
657 					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
658 				}
659 
660 				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF
661 				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
662 			}
663 			else
664 			{
665 				setVertexShader(0);
666 			}
667 
668 			vertexShaderDirty = false;
669 		}
670 	}
671 
bindViewport()672 	bool Device::bindViewport()
673 	{
674 		if(viewport.width <= 0 || viewport.height <= 0)
675 		{
676 			return false;
677 		}
678 
679 		if(scissorEnable)
680 		{
681 			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
682 			{
683 				return false;
684 			}
685 
686 			sw::Rect scissor;
687 			scissor.x0 = scissorRect.x0;
688 			scissor.x1 = scissorRect.x1;
689 			scissor.y0 = scissorRect.y0;
690 			scissor.y1 = scissorRect.y1;
691 
692 			setScissor(scissor);
693 		}
694 		else
695 		{
696 			sw::Rect scissor;
697 			scissor.x0 = viewport.x0;
698 			scissor.x1 = viewport.x0 + viewport.width;
699 			scissor.y0 = viewport.y0;
700 			scissor.y1 = viewport.y0 + viewport.height;
701 
702 			if(renderTarget)
703 			{
704 				scissor.x0 = max(scissor.x0, 0);
705 				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
706 				scissor.y0 = max(scissor.y0, 0);
707 				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
708 			}
709 
710 			if(depthStencil)
711 			{
712 				scissor.x0 = max(scissor.x0, 0);
713 				scissor.x1 = min(scissor.x1, depthStencil->getWidth());
714 				scissor.y0 = max(scissor.y0, 0);
715 				scissor.y1 = min(scissor.y1, depthStencil->getHeight());
716 			}
717 
718 			setScissor(scissor);
719 		}
720 
721 		sw::Viewport view;
722 		view.x0 = (float)viewport.x0;
723 		view.y0 = (float)viewport.y0;
724 		view.width = (float)viewport.width;
725 		view.height = (float)viewport.height;
726 		view.minZ = viewport.minZ;
727 		view.maxZ = viewport.maxZ;
728 
729 		Renderer::setViewport(view);
730 
731 		return true;
732 	}
733 
validRectangle(const sw::Rect * rect,Image * surface)734 	bool Device::validRectangle(const sw::Rect *rect, Image *surface)
735 	{
736 		if(!rect)
737 		{
738 			return true;
739 		}
740 
741 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
742 		{
743 			return false;
744 		}
745 
746 		if(rect->x0 < 0 || rect->y0 < 0)
747 		{
748 			return false;
749 		}
750 
751 		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
752 		{
753 			return false;
754 		}
755 
756 		return true;
757 	}
758 
finish()759 	void Device::finish()
760 	{
761 		synchronize();
762 	}
763 }
764