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
32namespace es2
33{
34 using namespace sw;
35
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
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
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
183 void Device::operator delete(void * mem)
184 {
185 sw::deallocate(mem);
186 }
187
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
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
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
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
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
274 void Device::setPixelShader(const PixelShader *pixelShader)
275 {
276 this->pixelShader = pixelShader;
277 pixelShaderDirty = true;
278 }
279
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
294 void Device::setScissorEnable(bool enable)
295 {
296 scissorEnable = enable;
297 }
298
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
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
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
360 void Device::setScissorRect(const sw::Rect &rect)
361 {
362 scissorRect = rect;
363 }
364
365 void Device::setVertexShader(const VertexShader *vertexShader)
366 {
367 this->vertexShader = vertexShader;
368 vertexShaderDirty = true;
369 }
370
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
385 void Device::setViewport(const Viewport &viewport)
386 {
387 this->viewport = viewport;
388 }
389
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
442 bool Device::stretchRect(sw::Surface *source, const sw::SliceRectF *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, unsigned char flags)
443 {
444 if(!source || !dest)
445 {
446 ERR("Invalid parameters");
447 return false;
448 }
449
450 int sWidth = source->getWidth();
451 int sHeight = source->getHeight();
452 int dWidth = dest->getWidth();
453 int dHeight = dest->getHeight();
454
455 if(sourceRect && destRect &&
456 (sourceRect->width() == 0.0f || !std::isfinite(sourceRect->width()) ||
457 sourceRect->height() == 0.0f || !std::isfinite(sourceRect->height()) ||
458 destRect->width() == 0.0f || destRect->height() == 0.0f))
459 {
460 return true; // No work to do.
461 }
462
463 bool flipX = false;
464 bool flipY = false;
465 if(sourceRect && destRect)
466 {
467 flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1);
468 flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1);
469 }
470 else if(sourceRect)
471 {
472 flipX = (sourceRect->x0 > sourceRect->x1);
473 flipY = (sourceRect->y0 > sourceRect->y1);
474 }
475 else if(destRect)
476 {
477 flipX = (destRect->x0 > destRect->x1);
478 flipY = (destRect->y0 > destRect->y1);
479 }
480
481 SliceRectF sRect;
482 SliceRect dRect;
483
484 if(sourceRect)
485 {
486 sRect.x0 = sourceRect->x0;
487 sRect.x1 = sourceRect->x1;
488 sRect.y0 = sourceRect->y0;
489 sRect.y1 = sourceRect->y1;
490 sRect.slice = sourceRect->slice;
491
492 if(sRect.x0 > sRect.x1)
493 {
494 swap(sRect.x0, sRect.x1);
495 }
496
497 if(sRect.y0 > sRect.y1)
498 {
499 swap(sRect.y0, sRect.y1);
500 }
501 }
502 else
503 {
504 sRect.y0 = 0.0f;
505 sRect.x0 = 0.0f;
506 sRect.y1 = (float)sHeight;
507 sRect.x1 = (float)sWidth;
508 }
509
510 if(destRect)
511 {
512 dRect = *destRect;
513
514 if(dRect.x0 > dRect.x1)
515 {
516 swap(dRect.x0, dRect.x1);
517 }
518
519 if(dRect.y0 > dRect.y1)
520 {
521 swap(dRect.y0, dRect.y1);
522 }
523 }
524 else
525 {
526 dRect.y0 = 0;
527 dRect.x0 = 0;
528 dRect.y1 = dHeight;
529 dRect.x1 = dWidth;
530 }
531
532 sw::Rect srcClipRect(0, 0, sWidth, sHeight);
533 if (!ClipSrcRect(sRect, dRect, srcClipRect, flipX, flipY))
534 {
535 return true;
536 }
537
538 sw::Rect dstClipRect(0, 0, dWidth, dHeight);
539 if (!ClipDstRect(sRect, dRect, dstClipRect, flipX, flipY))
540 {
541 return true;
542 }
543
544 if((sRect.width() == 0) || (sRect.height() == 0) ||
545 (dRect.width() == 0) || (dRect.height() == 0) ||
546 !std::isfinite(sRect.width()) || !std::isfinite(sRect.height()))
547 {
548 return true; // no work to do
549 }
550
551 if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest))
552 {
553 ERR("Invalid parameters");
554 return false;
555 }
556
557 bool isDepth = (flags & Device::DEPTH_BUFFER) && Surface::isDepth(source->getInternalFormat());
558 bool isStencil = (flags & Device::STENCIL_BUFFER) && Surface::isStencil(source->getInternalFormat());
559 bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER;
560
561 if(!isColor && !isDepth && !isStencil)
562 {
563 return true;
564 }
565
566 int sourceSliceB = isStencil ? source->getStencilSliceB() : source->getInternalSliceB();
567 int destSliceB = isStencil ? dest->getStencilSliceB() : dest->getInternalSliceB();
568 int sourcePitchB = isStencil ? source->getStencilPitchB() : source->getInternalPitchB();
569 int destPitchB = isStencil ? dest->getStencilPitchB() : dest->getInternalPitchB();
570
571 bool isOutOfBounds = (sRect.x0 < 0.0f) || (sRect.y0 < 0.0f) || (sRect.x1 > (float)sWidth) || (sRect.y1 > (float)sHeight);
572 bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height());
573 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
574 bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat());
575 bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) &&
576 (sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y1 == dHeight);
577 bool alpha0xFF = false;
578 bool equalSlice = sourceSliceB == destSliceB;
579 bool smallMargin = sourcePitchB <= source->getWidth() * Surface::bytes(source->getInternalFormat()) + 16;
580
581 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
582 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
583 {
584 equalFormats = true;
585 alpha0xFF = true;
586 }
587
588 if(fullCopy && !scaling && !isOutOfBounds && equalFormats && !alpha0xFF && equalSlice && smallMargin && !flipX && !flipY)
589 {
590 byte *sourceBuffer = isStencil ? (byte*)source->lockStencil(0, 0, 0, PUBLIC) : (byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
591 byte *destBuffer = isStencil ? (byte*)dest->lockStencil(0, 0, 0, PUBLIC) : (byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
592
593 memcpy(destBuffer, sourceBuffer, sourceSliceB);
594
595 isStencil ? source->unlockStencil() : source->unlockInternal();
596 isStencil ? dest->unlockStencil() : dest->unlockInternal();
597 }
598 else if(isDepth && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
599 {
600 byte *sourceBuffer = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC);
601 byte *destBuffer = (byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
602
603 copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
604
605 source->unlockInternal();
606 dest->unlockInternal();
607 }
608 else if((flags & Device::COLOR_BUFFER) && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
609 {
610 byte *sourceBytes = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
611 byte *destBytes = (byte*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
612
613 unsigned int width = dRect.x1 - dRect.x0;
614 unsigned int height = dRect.y1 - dRect.y0;
615
616 copyBuffer(sourceBytes, destBytes, width, height, sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
617
618 if(alpha0xFF)
619 {
620 for(unsigned int y = 0; y < height; y++)
621 {
622 for(unsigned int x = 0; x < width; x++)
623 {
624 destBytes[4 * x + 3] = 0xFF;
625 }
626
627 destBytes += destPitchB;
628 }
629 }
630
631 source->unlockInternal();
632 dest->unlockInternal();
633 }
634 else if(isColor || isDepth || isStencil)
635 {
636 if(flipX)
637 {
638 swap(dRect.x0, dRect.x1);
639 }
640 if(flipY)
641 {
642 swap(dRect.y0, dRect.y1);
643 }
644
645 blit(source, sRect, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil);
646 }
647 else UNREACHABLE(false);
648
649 return true;
650 }
651
652 bool Device::stretchCube(sw::Surface *source, sw::Surface *dest)
653 {
654 if(!source || !dest || Surface::isDepth(source->getInternalFormat()) || Surface::isStencil(source->getInternalFormat()))
655 {
656 ERR("Invalid parameters");
657 return false;
658 }
659
660 int sWidth = source->getWidth();
661 int sHeight = source->getHeight();
662 int sDepth = source->getDepth();
663 int dWidth = dest->getWidth();
664 int dHeight = dest->getHeight();
665 int dDepth = dest->getDepth();
666
667 if((sWidth == 0) || (sHeight == 0) || (sDepth == 0) ||
668 (dWidth == 0) || (dHeight == 0) || (dDepth == 0))
669 {
670 return true; // no work to do
671 }
672
673 bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);
674 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
675 bool alpha0xFF = false;
676
677 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
678 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
679 {
680 equalFormats = true;
681 alpha0xFF = true;
682 }
683
684 if(!scaling && equalFormats)
685 {
686 unsigned int sourcePitch = source->getInternalPitchB();
687 unsigned int destPitch = dest->getInternalPitchB();
688 unsigned int bytes = dWidth * Surface::bytes(source->getInternalFormat());
689
690 for(int z = 0; z < dDepth; z++)
691 {
692 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);
693 unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);
694
695 for(int y = 0; y < dHeight; y++)
696 {
697 memcpy(destBytes, sourceBytes, bytes);
698
699 if(alpha0xFF)
700 {
701 for(int x = 0; x < dWidth; x++)
702 {
703 destBytes[4 * x + 3] = 0xFF;
704 }
705 }
706
707 sourceBytes += sourcePitch;
708 destBytes += destPitch;
709 }
710
711 source->unlockInternal();
712 dest->unlockInternal();
713 }
714 }
715 else
716 {
717 blit3D(source, dest);
718 }
719
720 return true;
721 }
722
723 bool Device::bindResources()
724 {
725 if(!bindViewport() && !context->transformFeedbackEnabled)
726 {
727 return false; // Zero-area target region
728 }
729
730 bindShaderConstants();
731
732 return true;
733 }
734
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
778 bool Device::bindViewport()
779 {
780 if(viewport.width <= 0 || viewport.height <= 0)
781 {
782 return false;
783 }
784
785 if(scissorEnable)
786 {
787 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
788 {
789 return false;
790 }
791
792 sw::Rect scissor;
793 scissor.x0 = scissorRect.x0;
794 scissor.x1 = scissorRect.x1;
795 scissor.y0 = scissorRect.y0;
796 scissor.y1 = scissorRect.y1;
797
798 setScissor(scissor);
799 }
800 else
801 {
802 sw::Rect scissor;
803 scissor.x0 = viewport.x0;
804 scissor.x1 = viewport.x0 + viewport.width;
805 scissor.y0 = viewport.y0;
806 scissor.y1 = viewport.y0 + viewport.height;
807
808 for(int i = 0; i < RENDERTARGETS; ++i)
809 {
810 if(renderTarget[i])
811 {
812 scissor.x0 = max(scissor.x0, 0);
813 scissor.x1 = min(scissor.x1, renderTarget[i]->getWidth());
814 scissor.y0 = max(scissor.y0, 0);
815 scissor.y1 = min(scissor.y1, renderTarget[i]->getHeight());
816 }
817 }
818
819 if(depthBuffer)
820 {
821 scissor.x0 = max(scissor.x0, 0);
822 scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
823 scissor.y0 = max(scissor.y0, 0);
824 scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
825 }
826
827 if(stencilBuffer)
828 {
829 scissor.x0 = max(scissor.x0, 0);
830 scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
831 scissor.y0 = max(scissor.y0, 0);
832 scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
833 }
834
835 // Ensure scissor range is positive
836 scissor.x0 = max(scissor.x0, 0);
837 scissor.x1 = max(scissor.x1, 0);
838 scissor.y0 = max(scissor.y0, 0);
839 scissor.y1 = max(scissor.y1, 0);
840
841 setScissor(scissor);
842 }
843
844 sw::Viewport view;
845 view.x0 = (float)viewport.x0;
846 view.y0 = (float)viewport.y0;
847 view.width = (float)viewport.width;
848 view.height = (float)viewport.height;
849 view.minZ = viewport.minZ;
850 view.maxZ = viewport.maxZ;
851
852 Renderer::setViewport(view);
853
854 return true;
855 }
856
857 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
858 {
859 if(!rect)
860 {
861 return true;
862 }
863
864 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
865 {
866 return false;
867 }
868
869 if(rect->x0 < 0 || rect->y0 < 0)
870 {
871 return false;
872 }
873
874 if(rect->x1 >(int)surface->getWidth() || rect->y1 >(int)surface->getHeight())
875 {
876 return false;
877 }
878
879 return true;
880 }
881
882 bool Device::validRectangle(const sw::RectF *rect, sw::Surface *surface)
883 {
884 if(!rect)
885 {
886 return true;
887 }
888
889 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
890 {
891 return false;
892 }
893
894 if (!std::isfinite(rect->x0) || !std::isfinite(rect->x1) ||
895 !std::isfinite(rect->y0) || !std::isfinite(rect->y1))
896 {
897 return false;
898 }
899
900 return true;
901 }
902
903 bool Device::ClipDstRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
904 {
905 if(dstRect.x0 < clipRect.x0)
906 {
907 float offset = (static_cast<float>(clipRect.x0 - dstRect.x0) / static_cast<float>(dstRect.width())) * srcRect.width();
908 if (!std::isfinite(offset))
909 {
910 return false;
911 }
912 if(flipX)
913 {
914 srcRect.x1 -= offset;
915 }
916 else
917 {
918 srcRect.x0 += offset;
919 }
920 dstRect.x0 = clipRect.x0;
921 }
922 if(dstRect.x1 > clipRect.x1)
923 {
924 float offset = (static_cast<float>(dstRect.x1 - clipRect.x1) / static_cast<float>(dstRect.width())) * srcRect.width();
925 if (!std::isfinite(offset))
926 {
927 return false;
928 }
929 if(flipX)
930 {
931 srcRect.x0 += offset;
932 }
933 else
934 {
935 srcRect.x1 -= offset;
936 }
937 dstRect.x1 = clipRect.x1;
938 }
939 if(dstRect.y0 < clipRect.y0)
940 {
941 float offset = (static_cast<float>(clipRect.y0 - dstRect.y0) / static_cast<float>(dstRect.height())) * srcRect.height();
942 if (!std::isfinite(offset))
943 {
944 return false;
945 }
946 if(flipY)
947 {
948 srcRect.y1 -= offset;
949 }
950 else
951 {
952 srcRect.y0 += offset;
953 }
954 dstRect.y0 = clipRect.y0;
955 }
956 if(dstRect.y1 > clipRect.y1)
957 {
958 float offset = (static_cast<float>(dstRect.y1 - clipRect.y1) / static_cast<float>(dstRect.height())) * srcRect.height();
959 if (!std::isfinite(offset))
960 {
961 return false;
962 }
963 if(flipY)
964 {
965 srcRect.y0 += offset;
966 }
967 else
968 {
969 srcRect.y1 -= offset;
970 }
971 dstRect.y1 = clipRect.y1;
972 }
973 return true;
974 }
975
976 bool Device::ClipSrcRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
977 {
978 if(srcRect.x0 < static_cast<float>(clipRect.x0))
979 {
980 float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
981 float offsetf = roundf((static_cast<float>(clipRect.x0) - srcRect.x0) * ratio);
982 if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
983 {
984 return false;
985 }
986 int offset = static_cast<int>(offsetf);
987 if(flipX)
988 {
989 dstRect.x1 -= offset;
990 }
991 else
992 {
993 dstRect.x0 += offset;
994 }
995 srcRect.x0 += offsetf / ratio;
996 }
997 if(srcRect.x1 > static_cast<float>(clipRect.x1))
998 {
999 float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
1000 float offsetf = roundf((srcRect.x1 - static_cast<float>(clipRect.x1)) * ratio);
1001 if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
1002 {
1003 return false;
1004 }
1005 int offset = static_cast<int>(offsetf);
1006 if(flipX)
1007 {
1008 dstRect.x0 += offset;
1009 }
1010 else
1011 {
1012 dstRect.x1 -= offset;
1013 }
1014 srcRect.x1 -= offsetf / ratio;
1015 }
1016 if(srcRect.y0 < static_cast<float>(clipRect.y0))
1017 {
1018 float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
1019 float offsetf = roundf((static_cast<float>(clipRect.y0) - srcRect.y0) * ratio);
1020 if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
1021 {
1022 return false;
1023 }
1024 int offset = static_cast<int>(offsetf);
1025 if(flipY)
1026 {
1027 dstRect.y1 -= offset;
1028 }
1029 else
1030 {
1031 dstRect.y0 += offset;
1032 }
1033 srcRect.y0 += offsetf / ratio;
1034 }
1035 if(srcRect.y1 > static_cast<float>(clipRect.y1))
1036 {
1037 float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
1038 float offsetf = roundf((srcRect.y1 - static_cast<float>(clipRect.y1)) * ratio);
1039 if (!FloatFitsInInt(offsetf) || !std::isfinite(ratio))
1040 {
1041 return false;
1042 }
1043 int offset = static_cast<int>(offsetf);
1044 if(flipY)
1045 {
1046 dstRect.y0 += offset;
1047 }
1048 else
1049 {
1050 dstRect.y1 -= offset;
1051 }
1052 srcRect.y1 -= offsetf / ratio;
1053 }
1054 return true;
1055 }
1056
1057 void Device::finish()
1058 {
1059 synchronize();
1060 }
1061}
1062