blob: 359588f1d8e9063e904060d4de2f9e477b166dec [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman19bac1e2014-05-06 15:23:49 -04003// Copyright(c) 2005-2012 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "Device.hpp"
13
14#include "Image.hpp"
15#include "Texture.h"
16
17#include "Renderer/Renderer.hpp"
18#include "Renderer/Clipper.hpp"
19#include "Shader/PixelShader.hpp"
20#include "Shader/VertexShader.hpp"
21#include "Main/Config.hpp"
22#include "Main/FrameBuffer.hpp"
23#include "Common/Math.hpp"
24#include "Common/Configurator.hpp"
25#include "Common/Timer.hpp"
26#include "../common/debug.h"
27
John Bauman19bac1e2014-05-06 15:23:49 -040028bool localShaderConstants = false;
John Bauman89401822014-05-06 15:04:28 -040029
30namespace gl
31{
32 using namespace sw;
33
John Bauman19bac1e2014-05-06 15:23:49 -040034 Device::Device(Context *context) : Renderer(context, true, true, true, true, true), context(context)
John Bauman89401822014-05-06 15:04:28 -040035 {
36 depthStencil = 0;
37 renderTarget = 0;
38
39 setDepthBufferEnable(true);
40 setFillMode(Context::FILL_SOLID);
41 setShadingMode(Context::SHADING_GOURAUD);
42 setDepthWriteEnable(true);
43 setAlphaTestEnable(false);
44 setSourceBlendFactor(Context::BLEND_ONE);
45 setDestBlendFactor(Context::BLEND_ZERO);
46 setCullMode(Context::CULL_COUNTERCLOCKWISE);
47 setDepthCompare(Context::DEPTH_LESSEQUAL);
48 setAlphaReference(0);
49 setAlphaCompare(Context::ALPHA_ALWAYS);
50 setAlphaBlendEnable(false);
51 setFogEnable(false);
52 setSpecularEnable(false);
53 setFogColor(0);
54 setPixelFogMode(Context::FOG_NONE);
55 setFogStart(0.0f);
56 setFogEnd(1.0f);
57 setFogDensity(1.0f);
58 setRangeFogEnable(false);
59 setStencilEnable(false);
60 setStencilFailOperation(Context::OPERATION_KEEP);
61 setStencilZFailOperation(Context::OPERATION_KEEP);
62 setStencilPassOperation(Context::OPERATION_KEEP);
63 setStencilCompare(Context::STENCIL_ALWAYS);
64 setStencilReference(0);
65 setStencilMask(0xFFFFFFFF);
66 setStencilWriteMask(0xFFFFFFFF);
67 setVertexFogMode(Context::FOG_NONE);
68 setClipFlags(0);
69 setPointSize(1.0f);
John Bauman19bac1e2014-05-06 15:23:49 -040070 setPointSizeMin(0.125f);
John Bauman89401822014-05-06 15:04:28 -040071 setPointSpriteEnable(false);
John Bauman19bac1e2014-05-06 15:23:49 -040072 setPointSizeMax(8192.0f);
John Bauman89401822014-05-06 15:04:28 -040073 setColorWriteMask(0, 0x0000000F);
74 setBlendOperation(Context::BLENDOP_ADD);
75 scissorEnable = false;
76 setSlopeDepthBias(0.0f);
77 setTwoSidedStencil(false);
78 setStencilFailOperationCCW(Context::OPERATION_KEEP);
79 setStencilZFailOperationCCW(Context::OPERATION_KEEP);
80 setStencilPassOperationCCW(Context::OPERATION_KEEP);
81 setStencilCompareCCW(Context::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(Context::BLEND_ONE);
90 setDestBlendFactorAlpha(Context::BLEND_ZERO);
91 setBlendOperationAlpha(Context::BLENDOP_ADD);
92
93 for(int i = 0; i < 16; i++)
94 {
95 setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
96 setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
97 setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
98 setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
99 setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
100 setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
101 setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
102 }
103
104 for(int i = 0; i < 4; i++)
105 {
106 setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
107 setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
108 setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
109 setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
110 setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
111 setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
112 setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
113 }
114
115 for(int i = 0; i < 6; i++)
116 {
117 float plane[4] = {0, 0, 0, 0};
118
119 setClipPlane(i, plane);
120 }
121
122 pixelShader = 0;
123 vertexShader = 0;
124
125 pixelShaderDirty = true;
126 pixelShaderConstantsFDirty = 0;
127 vertexShaderDirty = true;
128 vertexShaderConstantsFDirty = 0;
129
130 for(int i = 0; i < 224; i++)
131 {
132 float zero[4] = {0, 0, 0, 0};
133
134 setPixelShaderConstantF(i, zero, 1);
135 }
136
137 for(int i = 0; i < 256; i++)
138 {
139 float zero[4] = {0, 0, 0, 0};
140
141 setVertexShaderConstantF(i, zero, 1);
142 }
143 }
144
145 Device::~Device()
146 {
147 if(depthStencil)
148 {
149 depthStencil->unbind();
150 depthStencil = 0;
151 }
152
153 if(renderTarget)
154 {
155 renderTarget->unbind();
156 renderTarget = 0;
157 }
158
159 delete context;
160 }
161
162 void Device::clearColor(unsigned int color, unsigned int rgbaMask)
163 {
164 TRACE("unsigned long color = 0x%0.8X", color);
165
John Bauman19bac1e2014-05-06 15:23:49 -0400166 int x0 = 0;
167 int y0 = 0;
168 int width = renderTarget->getExternalWidth();
169 int height = renderTarget->getExternalHeight();
John Bauman89401822014-05-06 15:04:28 -0400170
John Bauman19bac1e2014-05-06 15:23:49 -0400171 if(scissorEnable) // Clamp against scissor rectangle
John Bauman89401822014-05-06 15:04:28 -0400172 {
John Bauman19bac1e2014-05-06 15:23:49 -0400173 if(x0 < scissorRect.x0) x0 = scissorRect.x0;
174 if(y0 < scissorRect.y0) y0 = scissorRect.y0;
175 if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
176 if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400177 }
178
John Bauman19bac1e2014-05-06 15:23:49 -0400179 renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
John Bauman89401822014-05-06 15:04:28 -0400180 }
181
182 void Device::clearDepth(float z)
183 {
184 TRACE("float z = %f", z);
185
John Bauman19bac1e2014-05-06 15:23:49 -0400186 if(!depthStencil)
187 {
188 return;
189 }
190
John Bauman89401822014-05-06 15:04:28 -0400191 if(z > 1) z = 1;
192 if(z < 0) z = 0;
193
John Bauman19bac1e2014-05-06 15:23:49 -0400194 int x0 = 0;
195 int y0 = 0;
196 int width = depthStencil->getExternalWidth();
197 int height = depthStencil->getExternalHeight();
John Bauman89401822014-05-06 15:04:28 -0400198
John Bauman19bac1e2014-05-06 15:23:49 -0400199 if(scissorEnable) // Clamp against scissor rectangle
John Bauman89401822014-05-06 15:04:28 -0400200 {
John Bauman19bac1e2014-05-06 15:23:49 -0400201 if(x0 < scissorRect.x0) x0 = scissorRect.x0;
202 if(y0 < scissorRect.y0) y0 = scissorRect.y0;
203 if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
204 if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400205 }
John Bauman19bac1e2014-05-06 15:23:49 -0400206
207 depthStencil->clearDepthBuffer(z, x0, y0, width, height);
John Bauman89401822014-05-06 15:04:28 -0400208 }
209
210 void Device::clearStencil(unsigned int stencil, unsigned int mask)
211 {
212 TRACE("unsigned long stencil = %d", stencil);
213
John Bauman19bac1e2014-05-06 15:23:49 -0400214 if(!depthStencil)
John Bauman89401822014-05-06 15:04:28 -0400215 {
John Bauman19bac1e2014-05-06 15:23:49 -0400216 return;
John Bauman89401822014-05-06 15:04:28 -0400217 }
218
John Bauman19bac1e2014-05-06 15:23:49 -0400219 int x0 = 0;
220 int y0 = 0;
221 int width = renderTarget->getExternalWidth();
222 int height = renderTarget->getExternalHeight();
223
224 if(scissorEnable) // Clamp against scissor rectangle
John Bauman89401822014-05-06 15:04:28 -0400225 {
John Bauman19bac1e2014-05-06 15:23:49 -0400226 if(x0 < scissorRect.x0) x0 = scissorRect.x0;
227 if(y0 < scissorRect.y0) y0 = scissorRect.y0;
228 if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
229 if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400230 }
John Bauman19bac1e2014-05-06 15:23:49 -0400231
232 depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height);
John Bauman89401822014-05-06 15:04:28 -0400233 }
234
235 Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
236 {
237 TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d, int multiSampleDepth = %d, bool discard = %d", width, height, format, multiSampleDepth, discard);
238
239 if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)
240 {
241 ERR("Invalid parameters");
242 return 0;
243 }
244
245 bool lockable = true;
246
247 switch(format)
248 {
249 // case FORMAT_D15S1:
250 case FORMAT_D24S8:
251 case FORMAT_D24X8:
252 // case FORMAT_D24X4S4:
253 case FORMAT_D24FS8:
254 case FORMAT_D32:
255 case FORMAT_D16:
256 lockable = false;
257 break;
258 // case FORMAT_S8_LOCKABLE:
259 // case FORMAT_D16_LOCKABLE:
260 case FORMAT_D32F_LOCKABLE:
261 // case FORMAT_D32_LOCKABLE:
262 case FORMAT_DF24:
263 case FORMAT_DF16:
264 lockable = true;
265 break;
266 default:
267 UNREACHABLE();
268 }
269
270 Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, multiSampleDepth, lockable, true);
271
272 if(!surface)
273 {
274 ERR("Out of memory");
275 return 0;
276 }
277
278 surface->addRef();
279
280 return surface;
281 }
282
283 Image *Device::createOffscreenPlainSurface(unsigned int width, unsigned int height, sw::Format format)
284 {
285 TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d", width, height, format);
286
287 Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, 1, true, false);
288
289 if(!surface)
290 {
291 ERR("Out of memory");
292 return 0;
293 }
294
295 surface->addRef();
296
297 return surface;
298 }
299
300 Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
301 {
302 TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d, int multiSampleDepth = %d, bool lockable = %d", width, height, format, multiSampleDepth, lockable);
303
304 if(height > OUTLINE_RESOLUTION)
305 {
306 ERR("Invalid parameters");
307 return 0;
308 }
309
310 Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, multiSampleDepth, lockable != FALSE, true);
311
312 if(!surface)
313 {
314 ERR("Out of memory");
315 return 0;
316 }
317
318 surface->addRef();
319
320 return surface;
321 }
322
323 void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)
324 {
325 TRACE("");
326
327 if(!bindResources() || !primitiveCount)
328 {
329 return;
330 }
331
332 Context::DrawType drawType;
333
334 if(indexSize == 4)
335 {
336 switch(type)
337 {
338 case DRAW_POINTLIST: drawType = Context::DRAW_INDEXEDPOINTLIST32; break;
339 case DRAW_LINELIST: drawType = Context::DRAW_INDEXEDLINELIST32; break;
340 case DRAW_LINESTRIP: drawType = Context::DRAW_INDEXEDLINESTRIP32; break;
341 case DRAW_LINELOOP: drawType = Context::DRAW_INDEXEDLINELOOP32; break;
342 case DRAW_TRIANGLELIST: drawType = Context::DRAW_INDEXEDTRIANGLELIST32; break;
343 case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP32; break;
344 case DRAW_TRIANGLEFAN: drawType = Context::DRAW_INDEXEDTRIANGLEFAN32; break;
345 default: UNREACHABLE();
346 }
347 }
348 else if(indexSize == 2)
349 {
350 switch(type)
351 {
352 case DRAW_POINTLIST: drawType = Context::DRAW_INDEXEDPOINTLIST16; break;
353 case DRAW_LINELIST: drawType = Context::DRAW_INDEXEDLINELIST16; break;
354 case DRAW_LINESTRIP: drawType = Context::DRAW_INDEXEDLINESTRIP16; break;
355 case DRAW_LINELOOP: drawType = Context::DRAW_INDEXEDLINELOOP16; break;
356 case DRAW_TRIANGLELIST: drawType = Context::DRAW_INDEXEDTRIANGLELIST16; break;
357 case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP16; break;
358 case DRAW_TRIANGLEFAN: drawType = Context::DRAW_INDEXEDTRIANGLEFAN16; break;
359 default: UNREACHABLE();
360 }
361 }
362 else if(indexSize == 1)
363 {
364 switch(type)
365 {
366 case DRAW_POINTLIST: drawType = Context::DRAW_INDEXEDPOINTLIST8; break;
367 case DRAW_LINELIST: drawType = Context::DRAW_INDEXEDLINELIST8; break;
368 case DRAW_LINESTRIP: drawType = Context::DRAW_INDEXEDLINESTRIP8; break;
369 case DRAW_LINELOOP: drawType = Context::DRAW_INDEXEDLINELOOP8; break;
370 case DRAW_TRIANGLELIST: drawType = Context::DRAW_INDEXEDTRIANGLELIST8; break;
371 case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP8; break;
372 case DRAW_TRIANGLEFAN: drawType = Context::DRAW_INDEXEDTRIANGLEFAN8; break;
373 default: UNREACHABLE();
374 }
375 }
376 else UNREACHABLE();
377
378 draw(drawType, indexOffset, primitiveCount);
379 }
380
381 void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)
382 {
383 TRACE("");
384
385 if(!bindResources() || !primitiveCount)
386 {
387 return;
388 }
389
390 setIndexBuffer(0);
391
392 Context::DrawType drawType;
393
394 switch(primitiveType)
395 {
396 case DRAW_POINTLIST: drawType = Context::DRAW_POINTLIST; break;
397 case DRAW_LINELIST: drawType = Context::DRAW_LINELIST; break;
398 case DRAW_LINESTRIP: drawType = Context::DRAW_LINESTRIP; break;
399 case DRAW_LINELOOP: drawType = Context::DRAW_LINELOOP; break;
400 case DRAW_TRIANGLELIST: drawType = Context::DRAW_TRIANGLELIST; break;
401 case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_TRIANGLESTRIP; break;
402 case DRAW_TRIANGLEFAN: drawType = Context::DRAW_TRIANGLEFAN; break;
403 default: UNREACHABLE();
404 }
405
406 draw(drawType, 0, primitiveCount);
407 }
408
409 Image *Device::getDepthStencilSurface()
410 {
411 TRACE("void");
412
413 if(depthStencil)
414 {
415 depthStencil->addRef();
416 }
417
418 return depthStencil;
419 }
420
John Bauman89401822014-05-06 15:04:28 -0400421 void Device::setDepthStencilSurface(Image *depthStencil)
422 {
423 TRACE("Image *newDepthStencil = 0x%0.8p", depthStencil);
424
425 if(this->depthStencil == depthStencil)
426 {
427 return;
428 }
429
430 if(depthStencil)
431 {
432 depthStencil->bind();
433 }
434
435 if(this->depthStencil)
436 {
437 this->depthStencil->unbind();
438 }
439
440 this->depthStencil = depthStencil;
441
442 setDepthStencil(depthStencil);
443 }
444
445 void Device::setPixelShader(PixelShader *pixelShader)
446 {
447 TRACE("PixelShader *shader = 0x%0.8p", pixelShader);
448
449 this->pixelShader = pixelShader;
450 pixelShaderDirty = true;
451 }
452
453 void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
454 {
455 TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
456
457 for(unsigned int i = 0; i < count && startRegister + i < 224; i++)
458 {
459 pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
460 pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
461 pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
462 pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
463 }
464
465 pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
466 pixelShaderDirty = true; // Reload DEF constants
467 }
468
469 void Device::setScissorEnable(bool enable)
470 {
471 scissorEnable = enable;
472 }
473
474 void Device::setRenderTarget(Image *iRenderTarget)
475 {
476 TRACE("Image *newRenderTarget = 0x%0.8p", iRenderTarget);
477
478 Image *renderTarget = static_cast<Image*>(iRenderTarget);
479
480 if(renderTarget)
481 {
482 renderTarget->bind();
483 }
484
485 if(this->renderTarget)
486 {
487 this->renderTarget->unbind();
488 }
489
490 this->renderTarget = renderTarget;
491
John Bauman89401822014-05-06 15:04:28 -0400492 Renderer::setRenderTarget(0, renderTarget);
493 }
494
495 void Device::setScissorRect(const sw::Rect &rect)
496 {
497 TRACE("const sw::Rect *rect = 0x%0.8p", rect);
498
499 scissorRect = rect;
500 }
501
502 void Device::setVertexShader(VertexShader *vertexShader)
503 {
504 TRACE("VertexShader *shader = 0x%0.8p", vertexShader);
505
506 this->vertexShader = vertexShader;
507 vertexShaderDirty = true;
508 }
509
510 void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
511 {
512 TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
513
514 for(unsigned int i = 0; i < count && startRegister + i < 256; i++)
515 {
516 vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
517 vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
518 vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
519 vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
520 }
521
522 vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
523 vertexShaderDirty = true; // Reload DEF constants
524 }
525
526 void Device::setViewport(const Viewport &viewport)
527 {
528 TRACE("const Viewport *viewport = 0x%0.8p", viewport);
529
530 this->viewport = viewport;
531 }
532
533 bool Device::stretchRect(Image *sourceSurface, const sw::Rect *sourceRect, Image *destSurface, const sw::Rect *destRect, bool filter)
534 {
535 TRACE("Image *sourceSurface = 0x%0.8p, const sw::Rect *sourceRect = 0x%0.8p, Image *destSurface = 0x%0.8p, const sw::Rect *destRect = 0x%0.8p, bool filter = %d", sourceSurface, sourceRect, destSurface, destRect, filter);
536
537 if(!sourceSurface || !destSurface || !validRectangle(sourceRect, sourceSurface) || !validRectangle(destRect, destSurface))
538 {
539 ERR("Invalid parameters");
540 return false;
541 }
542
543 Image *source = static_cast<Image*>(sourceSurface);
544 Image *dest = static_cast<Image*>(destSurface);
545
546 int sWidth = source->getExternalWidth();
547 int sHeight = source->getExternalHeight();
548 int dWidth = dest->getExternalWidth();
549 int dHeight = dest->getExternalHeight();
550
551 Rect sRect;
552 Rect dRect;
553
554 if(sourceRect)
555 {
556 sRect = *sourceRect;
557 }
558 else
559 {
John Bauman19bac1e2014-05-06 15:23:49 -0400560 sRect.y0 = 0;
561 sRect.x0 = 0;
562 sRect.y1 = sHeight;
563 sRect.x1 = sWidth;
John Bauman89401822014-05-06 15:04:28 -0400564 }
565
566 if(destRect)
567 {
568 dRect = *destRect;
569 }
570 else
571 {
John Bauman19bac1e2014-05-06 15:23:49 -0400572 dRect.y0 = 0;
573 dRect.x0 = 0;
574 dRect.y1 = dHeight;
575 dRect.x1 = dWidth;
John Bauman89401822014-05-06 15:04:28 -0400576 }
577
John Bauman19bac1e2014-05-06 15:23:49 -0400578 bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
John Bauman89401822014-05-06 15:04:28 -0400579 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
580 bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());
581 bool alpha0xFF = false;
582
583 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
584 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
585 {
586 equalFormats = true;
587 alpha0xFF = true;
588 }
589
590 if(depthStencil) // Copy entirely, internally // FIXME: Check
591 {
592 if(source->hasDepth())
593 {
594 sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
595 sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
596
597 unsigned int width = source->getInternalWidth();
598 unsigned int height = source->getInternalHeight();
599 unsigned int pitch = source->getInternalPitchB();
600
601 for(unsigned int y = 0; y < height; y++)
602 {
603 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
604
605 sourceBuffer += pitch;
606 destBuffer += pitch;
607 }
608
609 source->unlockInternal();
610 dest->unlockInternal();
611 }
612
613 if(source->hasStencil())
614 {
615 sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
616 sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
617
618 unsigned int width = source->getInternalWidth();
619 unsigned int height = source->getInternalHeight();
620 unsigned int pitch = source->getStencilPitchB();
621
622 for(unsigned int y = 0; y < height; y++)
623 {
624 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
625
626 sourceBuffer += pitch;
627 destBuffer += pitch;
628 }
629
630 source->unlockStencil();
631 dest->unlockStencil();
632 }
633 }
634 else if(!scaling && equalFormats)
635 {
John Bauman19bac1e2014-05-06 15:23:49 -0400636 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, 0, LOCK_READONLY, PUBLIC);
637 unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, 0, LOCK_READWRITE, PUBLIC);
John Bauman89401822014-05-06 15:04:28 -0400638 unsigned int sourcePitch = source->getInternalPitchB();
639 unsigned int destPitch = dest->getInternalPitchB();
640
John Bauman19bac1e2014-05-06 15:23:49 -0400641 unsigned int width = dRect.x1 - dRect.x0;
642 unsigned int height = dRect.y1 - dRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400643 unsigned int bytes = width * Image::bytes(source->getInternalFormat());
644
645 for(unsigned int y = 0; y < height; y++)
646 {
647 memcpy(destBytes, sourceBytes, bytes);
648
649 if(alpha0xFF)
650 {
651 for(unsigned int x = 0; x < width; x++)
652 {
653 destBytes[4 * x + 3] = 0xFF;
654 }
655 }
656
657 sourceBytes += sourcePitch;
658 destBytes += destPitch;
659 }
660
661 source->unlockInternal();
662 dest->unlockInternal();
663 }
664 else
665 {
666 blit(source, sRect, dest, dRect, scaling && filter);
667 }
668
669 return true;
670 }
671
672 bool Device::updateSurface(Image *sourceSurface, const sw::Rect *sourceRect, Image *destinationSurface, const POINT *destPoint)
673 {
674 TRACE("Image *sourceSurface = 0x%0.8p, const sw::Rect *sourceRect = 0x%0.8p, Image *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint);
675
676 if(!sourceSurface || !destinationSurface)
677 {
678 ERR("Invalid parameters");
679 return false;
680 }
681
682 Rect sRect;
683 Rect dRect;
684
685 if(sourceRect)
686 {
John Bauman19bac1e2014-05-06 15:23:49 -0400687 sRect.x0 = sourceRect->x0;
688 sRect.y0 = sourceRect->y0;
689 sRect.x1 = sourceRect->x1;
690 sRect.y1 = sourceRect->y1;
John Bauman89401822014-05-06 15:04:28 -0400691 }
692 else
693 {
John Bauman19bac1e2014-05-06 15:23:49 -0400694 sRect.x0 = 0;
695 sRect.y0 = 0;
696 sRect.x1 = sourceSurface->getWidth();
697 sRect.y1 = sourceSurface->getHeight();
John Bauman89401822014-05-06 15:04:28 -0400698 }
699
700 if(destPoint)
701 {
John Bauman19bac1e2014-05-06 15:23:49 -0400702 dRect.x0 = destPoint->x;
703 dRect.y0 = destPoint->y;
704 dRect.x1 = destPoint->x + sRect.x1 - sRect.x0;
705 dRect.y1 = destPoint->y + sRect.y1 - sRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400706 }
707 else
708 {
John Bauman19bac1e2014-05-06 15:23:49 -0400709 dRect.x0 = 0;
710 dRect.y0 = 0;
711 dRect.x1 = sRect.x1 - sRect.x0;
712 dRect.y1 = sRect.y1 - sRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400713 }
714
715 if(!validRectangle(&sRect, sourceSurface) || !validRectangle(&dRect, destinationSurface))
716 {
717 ERR("Invalid parameters");
718 return false;
719 }
720
John Bauman19bac1e2014-05-06 15:23:49 -0400721 int sWidth = sRect.x1 - sRect.x0;
722 int sHeight = sRect.y1 - sRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400723
John Bauman19bac1e2014-05-06 15:23:49 -0400724 int dWidth = dRect.x1 - dRect.x0;
725 int dHeight = dRect.y1 - dRect.y0;
John Bauman89401822014-05-06 15:04:28 -0400726
727 if(sourceSurface->getMultiSampleDepth() > 1 ||
728 destinationSurface->getMultiSampleDepth() > 1 ||
729 sourceSurface->getInternalFormat() != destinationSurface->getInternalFormat())
730 {
731 ERR("Invalid parameters");
732 return false;
733 }
734
John Bauman19bac1e2014-05-06 15:23:49 -0400735 unsigned char *sourceBuffer = (unsigned char*)sourceSurface->lock(sRect.x0, sRect.y0, LOCK_READONLY);
736 unsigned char *destinationBuffer = (unsigned char*)destinationSurface->lock(dRect.x0, dRect.y0, LOCK_WRITEONLY);
John Bauman89401822014-05-06 15:04:28 -0400737
738 unsigned int width;
739 unsigned int height;
740 unsigned int bytes;
741
742 switch(sourceSurface->getInternalFormat())
743 {
744 #if S3TC_SUPPORT
745 case FORMAT_DXT1:
746 case FORMAT_ATI1:
747 width = (dWidth + 3) / 4;
748 height = (dHeight + 3) / 4;
749 bytes = width * 8; // 64 bit per 4x4 block
750 break;
751 // case FORMAT_DXT2:
752 case FORMAT_DXT3:
753 // case FORMAT_DXT4:
754 case FORMAT_DXT5:
755 case FORMAT_ATI2:
756 width = (dWidth + 3) / 4;
757 height = (dHeight + 3) / 4;
758 bytes = width * 16; // 128 bit per 4x4 block
759 break;
760 #endif
761 default:
762 width = dWidth;
763 height = dHeight;
764 bytes = width * Image::bytes(sourceSurface->getInternalFormat());
765 }
766
767 int sourcePitch = sourceSurface->getPitch();
768 int destinationPitch = destinationSurface->getPitch();
769
770 #if S3TC_SUPPORT
771 if(sourceSurface->getInternalFormat() == FORMAT_ATI1 || sourceSurface->getInternalFormat() == FORMAT_ATI2)
772 {
773 // Make the pitch correspond to 4 rows
774 sourcePitch *= 4;
775 destinationPitch *= 4;
776 }
777 #endif
778
779 for(unsigned int y = 0; y < height; y++)
780 {
781 memcpy(destinationBuffer, sourceBuffer, bytes);
782
783 sourceBuffer += sourcePitch;
784 destinationBuffer += destinationPitch;
785 }
786
787 sourceSurface->unlock();
788 destinationSurface->unlock();
789
790 return true;
791 }
792
793 bool Device::bindResources()
794 {
795 if(!bindViewport())
796 {
797 return false; // Zero-area target region
798 }
799
800 bindShaderConstants();
801
802 return true;
803 }
804
805 void Device::bindShaderConstants()
806 {
807 if(pixelShaderDirty)
808 {
809 if(pixelShader)
810 {
811 if(pixelShaderConstantsFDirty)
812 {
813 Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
814 }
815
816 Renderer::setPixelShader(pixelShader); // Loads shader constants set with DEF
817 pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF; // Shader DEF'ed constants are dirty
818 }
819 else
820 {
821 setPixelShader(0);
822 }
823
824 pixelShaderDirty = false;
825 }
826
827 if(vertexShaderDirty)
828 {
829 if(vertexShader)
830 {
831 if(vertexShaderConstantsFDirty)
832 {
833 Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
834 }
835
836 Renderer::setVertexShader(vertexShader); // Loads shader constants set with DEF
837 vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF; // Shader DEF'ed constants are dirty
838 }
839 else
840 {
841 setVertexShader(0);
842 }
843
844 vertexShaderDirty = false;
845 }
846 }
847
848 bool Device::bindViewport()
849 {
850 if(viewport.width <= 0 || viewport.height <= 0)
851 {
852 return false;
853 }
854
855 if(scissorEnable)
856 {
John Bauman19bac1e2014-05-06 15:23:49 -0400857 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
John Bauman89401822014-05-06 15:04:28 -0400858 {
859 return false;
860 }
861
John Bauman19bac1e2014-05-06 15:23:49 -0400862 sw::Rect scissor;
863 scissor.x0 = scissorRect.x0;
864 scissor.x1 = scissorRect.x1;
865 scissor.y0 = scissorRect.y0;
866 scissor.y1 = scissorRect.y1;
867
868 setScissor(scissor);
John Bauman89401822014-05-06 15:04:28 -0400869 }
870 else
871 {
John Bauman19bac1e2014-05-06 15:23:49 -0400872 sw::Rect scissor;
873 scissor.x0 = max(viewport.x0, 0);
874 scissor.x1 = min(viewport.x0 + viewport.width, renderTarget->getExternalWidth());
875 scissor.y0 = max(viewport.y0, 0);
876 scissor.y1 = min(viewport.y0 + viewport.height, renderTarget->getExternalHeight());
877
878 setScissor(scissor);
John Bauman89401822014-05-06 15:04:28 -0400879 }
880
John Bauman19bac1e2014-05-06 15:23:49 -0400881 sw::Viewport view;
882 view.x0 = (float)viewport.x0;
883 view.y0 = (float)viewport.y0;
884 view.width = (float)viewport.width;
885 view.height = (float)viewport.height;
886 view.minZ = viewport.minZ;
887 view.maxZ = viewport.maxZ;
888
889 Renderer::setViewport(view);
890
John Bauman89401822014-05-06 15:04:28 -0400891 return true;
892 }
893
894 bool Device::validRectangle(const sw::Rect *rect, Image *surface)
895 {
896 if(!rect)
897 {
898 return true;
899 }
900
John Bauman19bac1e2014-05-06 15:23:49 -0400901 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
John Bauman89401822014-05-06 15:04:28 -0400902 {
903 return false;
904 }
905
John Bauman19bac1e2014-05-06 15:23:49 -0400906 if(rect->x0 < 0 || rect->y0 < 0)
John Bauman89401822014-05-06 15:04:28 -0400907 {
908 return false;
909 }
910
John Bauman19bac1e2014-05-06 15:23:49 -0400911 if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
John Bauman89401822014-05-06 15:04:28 -0400912 {
913 return false;
914 }
915
916 return true;
917 }
918
919 void Device::finish()
920 {
John Bauman19bac1e2014-05-06 15:23:49 -0400921 synchronize();
John Bauman89401822014-05-06 15:04:28 -0400922 }
923}
924
925extern "C"
926{
927 gl::Device *createDevice()
928 {
929 sw::Context *context = new sw::Context();
930
931 if(context)
932 {
933 return new gl::Device(context);
934 }
935
936 return 0;
937 }
938}