1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "Device.hpp" 16 17 #include "common/Image.hpp" 18 #include "Texture.h" 19 20 #include "Renderer/Renderer.hpp" 21 #include "Renderer/Clipper.hpp" 22 #include "Shader/PixelShader.hpp" 23 #include "Shader/VertexShader.hpp" 24 #include "Main/Config.hpp" 25 #include "Main/FrameBuffer.hpp" 26 #include "Common/Math.hpp" 27 #include "Common/Configurator.hpp" 28 #include "Common/Memory.hpp" 29 #include "Common/Timer.hpp" 30 #include "../common/debug.h" 31 32 namespace es2 33 { 34 using namespace sw; 35 Device(Context * context)36 Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) 37 { 38 for(int i = 0; i < RENDERTARGETS; i++) 39 { 40 renderTarget[i] = nullptr; 41 } 42 43 depthBuffer = nullptr; 44 stencilBuffer = nullptr; 45 46 setDepthBufferEnable(true); 47 setFillMode(FILL_SOLID); 48 setShadingMode(SHADING_GOURAUD); 49 setDepthWriteEnable(true); 50 setAlphaTestEnable(false); 51 setSourceBlendFactor(BLEND_ONE); 52 setDestBlendFactor(BLEND_ZERO); 53 setCullMode(CULL_COUNTERCLOCKWISE, true); 54 setDepthCompare(DEPTH_LESSEQUAL); 55 setAlphaReference(127.5f); 56 setAlphaCompare(ALPHA_ALWAYS); 57 setAlphaBlendEnable(false); 58 setFogEnable(false); 59 setSpecularEnable(false); 60 setFogColor(0); 61 setPixelFogMode(FOG_NONE); 62 setFogStart(0.0f); 63 setFogEnd(1.0f); 64 setFogDensity(1.0f); 65 setRangeFogEnable(false); 66 setStencilEnable(false); 67 setStencilFailOperation(OPERATION_KEEP); 68 setStencilZFailOperation(OPERATION_KEEP); 69 setStencilPassOperation(OPERATION_KEEP); 70 setStencilCompare(STENCIL_ALWAYS); 71 setStencilReference(0); 72 setStencilMask(0xFFFFFFFF); 73 setStencilWriteMask(0xFFFFFFFF); 74 setVertexFogMode(FOG_NONE); 75 setClipFlags(0); 76 setPointSize(1.0f); 77 setPointSizeMin(0.125f); 78 setPointSizeMax(8192.0f); 79 setBlendOperation(BLENDOP_ADD); 80 scissorEnable = false; 81 setSlopeDepthBias(0.0f); 82 setTwoSidedStencil(false); 83 setStencilFailOperationCCW(OPERATION_KEEP); 84 setStencilZFailOperationCCW(OPERATION_KEEP); 85 setStencilPassOperationCCW(OPERATION_KEEP); 86 setStencilCompareCCW(STENCIL_ALWAYS); 87 setBlendConstant(0xFFFFFFFF); 88 setWriteSRGB(false); 89 setDepthBias(0.0f); 90 setSeparateAlphaBlendEnable(false); 91 setSourceBlendFactorAlpha(BLEND_ONE); 92 setDestBlendFactorAlpha(BLEND_ZERO); 93 setBlendOperationAlpha(BLENDOP_ADD); 94 setPointSpriteEnable(true); 95 setColorLogicOpEnabled(false); 96 setLogicalOperation(LOGICALOP_COPY); 97 98 for(int i = 0; i < 16; i++) 99 { 100 setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 101 setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 102 setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 103 setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000); 104 setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT); 105 setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE); 106 setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f); 107 } 108 109 for(int i = 0; i < 4; i++) 110 { 111 setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 112 setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 113 setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 114 setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000); 115 setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT); 116 setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE); 117 setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f); 118 } 119 120 for(int i = 0; i < 6; i++) 121 { 122 float plane[4] = {0, 0, 0, 0}; 123 124 setClipPlane(i, plane); 125 } 126 127 pixelShader = nullptr; 128 vertexShader = nullptr; 129 130 pixelShaderDirty = true; 131 pixelShaderConstantsFDirty = 0; 132 vertexShaderDirty = true; 133 vertexShaderConstantsFDirty = 0; 134 135 for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++) 136 { 137 float zero[4] = {0, 0, 0, 0}; 138 139 setPixelShaderConstantF(i, zero, 1); 140 } 141 142 for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++) 143 { 144 float zero[4] = {0, 0, 0, 0}; 145 146 setVertexShaderConstantF(i, zero, 1); 147 } 148 } 149 ~Device()150 Device::~Device() 151 { 152 for(int i = 0; i < RENDERTARGETS; i++) 153 { 154 if(renderTarget[i]) 155 { 156 renderTarget[i]->release(); 157 renderTarget[i] = nullptr; 158 } 159 } 160 161 if(depthBuffer) 162 { 163 depthBuffer->release(); 164 depthBuffer = nullptr; 165 } 166 167 if(stencilBuffer) 168 { 169 stencilBuffer->release(); 170 stencilBuffer = nullptr; 171 } 172 173 delete context; 174 } 175 176 // This object has to be mem aligned operator new(size_t size)177 void* Device::operator new(size_t size) 178 { 179 ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class 180 return sw::allocate(sizeof(Device), 16); 181 } 182 operator delete(void * mem)183 void Device::operator delete(void * mem) 184 { 185 sw::deallocate(mem); 186 } 187 clearColor(float red,float green,float blue,float alpha,unsigned int rgbaMask)188 void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask) 189 { 190 if(!rgbaMask) 191 { 192 return; 193 } 194 195 float rgba[4]; 196 rgba[0] = red; 197 rgba[1] = green; 198 rgba[2] = blue; 199 rgba[3] = alpha; 200 201 for(int i = 0; i < RENDERTARGETS; ++i) 202 { 203 if(renderTarget[i]) 204 { 205 sw::Rect clearRect = renderTarget[i]->getRect(); 206 207 if(scissorEnable) 208 { 209 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 210 } 211 212 clear(rgba, FORMAT_A32B32G32R32F, renderTarget[i], clearRect, rgbaMask); 213 } 214 } 215 } 216 clearDepth(float z)217 void Device::clearDepth(float z) 218 { 219 if(!depthBuffer) 220 { 221 return; 222 } 223 224 z = clamp01(z); 225 sw::Rect clearRect = depthBuffer->getRect(); 226 227 if(scissorEnable) 228 { 229 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 230 } 231 232 depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 233 } 234 clearStencil(unsigned int stencil,unsigned int mask)235 void Device::clearStencil(unsigned int stencil, unsigned int mask) 236 { 237 if(!stencilBuffer) 238 { 239 return; 240 } 241 242 sw::Rect clearRect = stencilBuffer->getRect(); 243 244 if(scissorEnable) 245 { 246 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 247 } 248 249 stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 250 } 251 drawIndexedPrimitive(sw::DrawType type,unsigned int indexOffset,unsigned int primitiveCount)252 void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount) 253 { 254 if(!bindResources() || !primitiveCount) 255 { 256 return; 257 } 258 259 draw(type, indexOffset, primitiveCount); 260 } 261 drawPrimitive(sw::DrawType type,unsigned int primitiveCount)262 void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount) 263 { 264 if(!bindResources() || !primitiveCount) 265 { 266 return; 267 } 268 269 setIndexBuffer(nullptr); 270 271 draw(type, 0, primitiveCount); 272 } 273 setPixelShader(const PixelShader * pixelShader)274 void Device::setPixelShader(const PixelShader *pixelShader) 275 { 276 this->pixelShader = pixelShader; 277 pixelShaderDirty = true; 278 } 279 setPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)280 void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) 281 { 282 for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++) 283 { 284 pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0]; 285 pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1]; 286 pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2]; 287 pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3]; 288 } 289 290 pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty); 291 pixelShaderDirty = true; // Reload DEF constants 292 } 293 setScissorEnable(bool enable)294 void Device::setScissorEnable(bool enable) 295 { 296 scissorEnable = enable; 297 } 298 setRenderTarget(int index,egl::Image * renderTarget,unsigned int layer)299 void Device::setRenderTarget(int index, egl::Image *renderTarget, unsigned int layer) 300 { 301 if(renderTarget) 302 { 303 renderTarget->addRef(); 304 } 305 306 if(this->renderTarget[index]) 307 { 308 this->renderTarget[index]->release(); 309 } 310 311 this->renderTarget[index] = renderTarget; 312 313 Renderer::setRenderTarget(index, renderTarget, layer); 314 } 315 setDepthBuffer(egl::Image * depthBuffer,unsigned int layer)316 void Device::setDepthBuffer(egl::Image *depthBuffer, unsigned int layer) 317 { 318 if(this->depthBuffer == depthBuffer) 319 { 320 return; 321 } 322 323 if(depthBuffer) 324 { 325 depthBuffer->addRef(); 326 } 327 328 if(this->depthBuffer) 329 { 330 this->depthBuffer->release(); 331 } 332 333 this->depthBuffer = depthBuffer; 334 335 Renderer::setDepthBuffer(depthBuffer, layer); 336 } 337 setStencilBuffer(egl::Image * stencilBuffer,unsigned int layer)338 void Device::setStencilBuffer(egl::Image *stencilBuffer, unsigned int layer) 339 { 340 if(this->stencilBuffer == stencilBuffer) 341 { 342 return; 343 } 344 345 if(stencilBuffer) 346 { 347 stencilBuffer->addRef(); 348 } 349 350 if(this->stencilBuffer) 351 { 352 this->stencilBuffer->release(); 353 } 354 355 this->stencilBuffer = stencilBuffer; 356 357 Renderer::setStencilBuffer(stencilBuffer, layer); 358 } 359 setScissorRect(const sw::Rect & rect)360 void Device::setScissorRect(const sw::Rect &rect) 361 { 362 scissorRect = rect; 363 } 364 setVertexShader(const VertexShader * vertexShader)365 void Device::setVertexShader(const VertexShader *vertexShader) 366 { 367 this->vertexShader = vertexShader; 368 vertexShaderDirty = true; 369 } 370 setVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)371 void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) 372 { 373 for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++) 374 { 375 vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0]; 376 vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1]; 377 vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2]; 378 vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3]; 379 } 380 381 vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty); 382 vertexShaderDirty = true; // Reload DEF constants 383 } 384 setViewport(const Viewport & viewport)385 void Device::setViewport(const Viewport &viewport) 386 { 387 this->viewport = viewport; 388 } 389 copyBuffer(byte * sourceBuffer,byte * destBuffer,unsigned int width,unsigned int height,unsigned int sourcePitch,unsigned int destPitch,unsigned int bytes,bool flipX,bool flipY)390 void Device::copyBuffer(byte *sourceBuffer, byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY) 391 { 392 if(flipX) 393 { 394 if(flipY) 395 { 396 sourceBuffer += (height - 1) * sourcePitch; 397 for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch) 398 { 399 byte *srcX = sourceBuffer + (width - 1) * bytes; 400 byte *dstX = destBuffer; 401 for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes) 402 { 403 memcpy(dstX, srcX, bytes); 404 } 405 } 406 } 407 else 408 { 409 for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch) 410 { 411 byte *srcX = sourceBuffer + (width - 1) * bytes; 412 byte *dstX = destBuffer; 413 for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes) 414 { 415 memcpy(dstX, srcX, bytes); 416 } 417 } 418 } 419 } 420 else 421 { 422 unsigned int widthB = width * bytes; 423 424 if(flipY) 425 { 426 sourceBuffer += (height - 1) * sourcePitch; 427 for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch) 428 { 429 memcpy(destBuffer, sourceBuffer, widthB); 430 } 431 } 432 else 433 { 434 for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch) 435 { 436 memcpy(destBuffer, sourceBuffer, widthB); 437 } 438 } 439 } 440 } 441 stretchRect(sw::Surface * source,const sw::SliceRectF * sourceRect,sw::Surface * dest,const sw::SliceRect * destRect,unsigned char flags)442 bool Device::stretchRect(sw::Surface *source, const sw::SliceRectF *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, unsigned char flags) 443 { 444 if(!source || !dest) 445 { 446 ERR("Invalid parameters"); 447 return false; 448 } 449 450 int sWidth = source->getWidth(); 451 int sHeight = source->getHeight(); 452 int dWidth = dest->getWidth(); 453 int dHeight = dest->getHeight(); 454 455 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) && (source->getBorder() == 0) && (dest->getBorder() == 0); 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 stretchCube(sw::Surface * source,sw::Surface * dest)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 bindResources()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 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 // 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 validRectangle(const sw::Rect * rect,sw::Surface * surface)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 validRectangle(const sw::RectF * rect,sw::Surface * surface)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 ClipDstRect(sw::RectF & srcRect,sw::Rect & dstRect,sw::Rect & clipRect,bool flipX,bool flipY)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 ClipSrcRect(sw::RectF & srcRect,sw::Rect & dstRect,sw::Rect & clipRect,bool flipX,bool flipY)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 finish()1057 void Device::finish() 1058 { 1059 synchronize(); 1060 } 1061 } 1062