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 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 bool flipX = false; 456 bool flipY = false; 457 if(sourceRect && destRect) 458 { 459 flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1); 460 flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1); 461 } 462 else if(sourceRect) 463 { 464 flipX = (sourceRect->x0 > sourceRect->x1); 465 flipY = (sourceRect->y0 > sourceRect->y1); 466 } 467 else if(destRect) 468 { 469 flipX = (destRect->x0 > destRect->x1); 470 flipY = (destRect->y0 > destRect->y1); 471 } 472 473 SliceRectF sRect; 474 SliceRect dRect; 475 476 if(sourceRect) 477 { 478 sRect.x0 = sourceRect->x0; 479 sRect.x1 = sourceRect->x1; 480 sRect.y0 = sourceRect->y0; 481 sRect.y1 = sourceRect->y1; 482 sRect.slice = sourceRect->slice; 483 484 if(sRect.x0 > sRect.x1) 485 { 486 swap(sRect.x0, sRect.x1); 487 } 488 489 if(sRect.y0 > sRect.y1) 490 { 491 swap(sRect.y0, sRect.y1); 492 } 493 } 494 else 495 { 496 sRect.y0 = 0.0f; 497 sRect.x0 = 0.0f; 498 sRect.y1 = (float)sHeight; 499 sRect.x1 = (float)sWidth; 500 } 501 502 if(destRect) 503 { 504 dRect = *destRect; 505 506 if(dRect.x0 > dRect.x1) 507 { 508 swap(dRect.x0, dRect.x1); 509 } 510 511 if(dRect.y0 > dRect.y1) 512 { 513 swap(dRect.y0, dRect.y1); 514 } 515 } 516 else 517 { 518 dRect.y0 = 0; 519 dRect.x0 = 0; 520 dRect.y1 = dHeight; 521 dRect.x1 = dWidth; 522 } 523 524 sw::Rect srcClipRect(0, 0, sWidth, sHeight); 525 ClipSrcRect(sRect, dRect, srcClipRect, flipX, flipY); 526 527 sw::Rect dstClipRect(0, 0, dWidth, dHeight); 528 ClipDstRect(sRect, dRect, dstClipRect, flipX, flipY); 529 530 if((sRect.width() == 0) || (sRect.height() == 0) || 531 (dRect.width() == 0) || (dRect.height() == 0)) 532 { 533 return true; // no work to do 534 } 535 536 if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest)) 537 { 538 ERR("Invalid parameters"); 539 return false; 540 } 541 542 bool isDepth = (flags & Device::DEPTH_BUFFER) && Surface::isDepth(source->getInternalFormat()); 543 bool isStencil = (flags & Device::STENCIL_BUFFER) && Surface::isStencil(source->getInternalFormat()); 544 bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER; 545 546 if(!isColor && !isDepth && !isStencil) 547 { 548 return true; 549 } 550 551 int sourceSliceB = isStencil ? source->getStencilSliceB() : source->getInternalSliceB(); 552 int destSliceB = isStencil ? dest->getStencilSliceB() : dest->getInternalSliceB(); 553 int sourcePitchB = isStencil ? source->getStencilPitchB() : source->getInternalPitchB(); 554 int destPitchB = isStencil ? dest->getStencilPitchB() : dest->getInternalPitchB(); 555 556 bool isOutOfBounds = (sRect.x0 < 0.0f) || (sRect.y0 < 0.0f) || (sRect.x1 > (float)sWidth) || (sRect.y1 > (float)sHeight); 557 bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height()); 558 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 559 bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat()); 560 bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) && 561 (sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y1 == dHeight); 562 bool alpha0xFF = false; 563 bool equalSlice = sourceSliceB == destSliceB; 564 bool smallMargin = sourcePitchB <= source->getWidth() * Surface::bytes(source->getInternalFormat()) + 16; 565 566 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 567 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 568 { 569 equalFormats = true; 570 alpha0xFF = true; 571 } 572 573 if(fullCopy && !scaling && !isOutOfBounds && equalFormats && !alpha0xFF && equalSlice && smallMargin && !flipX && !flipY) 574 { 575 byte *sourceBuffer = isStencil ? (byte*)source->lockStencil(0, 0, 0, PUBLIC) : (byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC); 576 byte *destBuffer = isStencil ? (byte*)dest->lockStencil(0, 0, 0, PUBLIC) : (byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC); 577 578 memcpy(destBuffer, sourceBuffer, sourceSliceB); 579 580 isStencil ? source->unlockStencil() : source->unlockInternal(); 581 isStencil ? dest->unlockStencil() : dest->unlockInternal(); 582 } 583 else if(isDepth && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout) 584 { 585 byte *sourceBuffer = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC); 586 byte *destBuffer = (byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC); 587 588 copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY); 589 590 source->unlockInternal(); 591 dest->unlockInternal(); 592 } 593 else if((flags & Device::COLOR_BUFFER) && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout) 594 { 595 byte *sourceBytes = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC); 596 byte *destBytes = (byte*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC); 597 598 unsigned int width = dRect.x1 - dRect.x0; 599 unsigned int height = dRect.y1 - dRect.y0; 600 601 copyBuffer(sourceBytes, destBytes, width, height, sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY); 602 603 if(alpha0xFF) 604 { 605 for(unsigned int y = 0; y < height; y++) 606 { 607 for(unsigned int x = 0; x < width; x++) 608 { 609 destBytes[4 * x + 3] = 0xFF; 610 } 611 612 destBytes += destPitchB; 613 } 614 } 615 616 source->unlockInternal(); 617 dest->unlockInternal(); 618 } 619 else if(isColor || isDepth || isStencil) 620 { 621 if(flipX) 622 { 623 swap(dRect.x0, dRect.x1); 624 } 625 if(flipY) 626 { 627 swap(dRect.y0, dRect.y1); 628 } 629 630 blit(source, sRect, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil); 631 } 632 else UNREACHABLE(false); 633 634 return true; 635 } 636 637 bool Device::stretchCube(sw::Surface *source, sw::Surface *dest) 638 { 639 if(!source || !dest || Surface::isDepth(source->getInternalFormat()) || Surface::isStencil(source->getInternalFormat())) 640 { 641 ERR("Invalid parameters"); 642 return false; 643 } 644 645 int sWidth = source->getWidth(); 646 int sHeight = source->getHeight(); 647 int sDepth = source->getDepth(); 648 int dWidth = dest->getWidth(); 649 int dHeight = dest->getHeight(); 650 int dDepth = dest->getDepth(); 651 652 if((sWidth == 0) || (sHeight == 0) || (sDepth == 0) || 653 (dWidth == 0) || (dHeight == 0) || (dDepth == 0)) 654 { 655 return true; // no work to do 656 } 657 658 bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth); 659 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 660 bool alpha0xFF = false; 661 662 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 663 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 664 { 665 equalFormats = true; 666 alpha0xFF = true; 667 } 668 669 if(!scaling && equalFormats) 670 { 671 unsigned int sourcePitch = source->getInternalPitchB(); 672 unsigned int destPitch = dest->getInternalPitchB(); 673 unsigned int bytes = dWidth * Surface::bytes(source->getInternalFormat()); 674 675 for(int z = 0; z < dDepth; z++) 676 { 677 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC); 678 unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC); 679 680 for(int y = 0; y < dHeight; y++) 681 { 682 memcpy(destBytes, sourceBytes, bytes); 683 684 if(alpha0xFF) 685 { 686 for(int x = 0; x < dWidth; x++) 687 { 688 destBytes[4 * x + 3] = 0xFF; 689 } 690 } 691 692 sourceBytes += sourcePitch; 693 destBytes += destPitch; 694 } 695 696 source->unlockInternal(); 697 dest->unlockInternal(); 698 } 699 } 700 else 701 { 702 blit3D(source, dest); 703 } 704 705 return true; 706 } 707 708 bool Device::bindResources() 709 { 710 if(!bindViewport()) 711 { 712 return false; // Zero-area target region 713 } 714 715 bindShaderConstants(); 716 717 return true; 718 } 719 720 void Device::bindShaderConstants() 721 { 722 if(pixelShaderDirty) 723 { 724 if(pixelShader) 725 { 726 if(pixelShaderConstantsFDirty) 727 { 728 Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty); 729 } 730 731 Renderer::setPixelShader(pixelShader); // Loads shader constants set with DEF 732 pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF; // Shader DEF'ed constants are dirty 733 } 734 else 735 { 736 setPixelShader(0); 737 } 738 739 pixelShaderDirty = false; 740 } 741 742 if(vertexShaderDirty) 743 { 744 if(vertexShader) 745 { 746 if(vertexShaderConstantsFDirty) 747 { 748 Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty); 749 } 750 751 Renderer::setVertexShader(vertexShader); // Loads shader constants set with DEF 752 vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF; // Shader DEF'ed constants are dirty 753 } 754 else 755 { 756 setVertexShader(0); 757 } 758 759 vertexShaderDirty = false; 760 } 761 } 762 763 bool Device::bindViewport() 764 { 765 if(viewport.width <= 0 || viewport.height <= 0) 766 { 767 return false; 768 } 769 770 if(scissorEnable) 771 { 772 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1) 773 { 774 return false; 775 } 776 777 sw::Rect scissor; 778 scissor.x0 = scissorRect.x0; 779 scissor.x1 = scissorRect.x1; 780 scissor.y0 = scissorRect.y0; 781 scissor.y1 = scissorRect.y1; 782 783 setScissor(scissor); 784 } 785 else 786 { 787 sw::Rect scissor; 788 scissor.x0 = viewport.x0; 789 scissor.x1 = viewport.x0 + viewport.width; 790 scissor.y0 = viewport.y0; 791 scissor.y1 = viewport.y0 + viewport.height; 792 793 for(int i = 0; i < RENDERTARGETS; ++i) 794 { 795 if(renderTarget[i]) 796 { 797 scissor.x0 = max(scissor.x0, 0); 798 scissor.x1 = min(scissor.x1, renderTarget[i]->getWidth()); 799 scissor.y0 = max(scissor.y0, 0); 800 scissor.y1 = min(scissor.y1, renderTarget[i]->getHeight()); 801 } 802 } 803 804 if(depthBuffer) 805 { 806 scissor.x0 = max(scissor.x0, 0); 807 scissor.x1 = min(scissor.x1, depthBuffer->getWidth()); 808 scissor.y0 = max(scissor.y0, 0); 809 scissor.y1 = min(scissor.y1, depthBuffer->getHeight()); 810 } 811 812 if(stencilBuffer) 813 { 814 scissor.x0 = max(scissor.x0, 0); 815 scissor.x1 = min(scissor.x1, stencilBuffer->getWidth()); 816 scissor.y0 = max(scissor.y0, 0); 817 scissor.y1 = min(scissor.y1, stencilBuffer->getHeight()); 818 } 819 820 setScissor(scissor); 821 } 822 823 sw::Viewport view; 824 view.x0 = (float)viewport.x0; 825 view.y0 = (float)viewport.y0; 826 view.width = (float)viewport.width; 827 view.height = (float)viewport.height; 828 view.minZ = viewport.minZ; 829 view.maxZ = viewport.maxZ; 830 831 Renderer::setViewport(view); 832 833 return true; 834 } 835 836 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) 837 { 838 if(!rect) 839 { 840 return true; 841 } 842 843 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) 844 { 845 return false; 846 } 847 848 if(rect->x0 < 0 || rect->y0 < 0) 849 { 850 return false; 851 } 852 853 if(rect->x1 >(int)surface->getWidth() || rect->y1 >(int)surface->getHeight()) 854 { 855 return false; 856 } 857 858 return true; 859 } 860 861 bool Device::validRectangle(const sw::RectF *rect, sw::Surface *surface) 862 { 863 if(!rect) 864 { 865 return true; 866 } 867 868 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) 869 { 870 return false; 871 } 872 873 return true; 874 } 875 876 void Device::ClipDstRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY) 877 { 878 if(dstRect.x0 < clipRect.x0) 879 { 880 float offset = (static_cast<float>(clipRect.x0 - dstRect.x0) / static_cast<float>(dstRect.width())) * srcRect.width(); 881 if(flipX) 882 { 883 srcRect.x1 -= offset; 884 } 885 else 886 { 887 srcRect.x0 += offset; 888 } 889 dstRect.x0 = clipRect.x0; 890 } 891 if(dstRect.x1 > clipRect.x1) 892 { 893 float offset = (static_cast<float>(dstRect.x1 - clipRect.x1) / static_cast<float>(dstRect.width())) * srcRect.width(); 894 if(flipX) 895 { 896 srcRect.x0 += offset; 897 } 898 else 899 { 900 srcRect.x1 -= offset; 901 } 902 dstRect.x1 = clipRect.x1; 903 } 904 if(dstRect.y0 < clipRect.y0) 905 { 906 float offset = (static_cast<float>(clipRect.y0 - dstRect.y0) / static_cast<float>(dstRect.height())) * srcRect.height(); 907 if(flipY) 908 { 909 srcRect.y1 -= offset; 910 } 911 else 912 { 913 srcRect.y0 += offset; 914 } 915 dstRect.y0 = clipRect.y0; 916 } 917 if(dstRect.y1 > clipRect.y1) 918 { 919 float offset = (static_cast<float>(dstRect.y1 - clipRect.y1) / static_cast<float>(dstRect.height())) * srcRect.height(); 920 if(flipY) 921 { 922 srcRect.y0 += offset; 923 } 924 else 925 { 926 srcRect.y1 -= offset; 927 } 928 dstRect.y1 = clipRect.y1; 929 } 930 } 931 932 void Device::ClipSrcRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY) 933 { 934 if(srcRect.x0 < static_cast<float>(clipRect.x0)) 935 { 936 float ratio = static_cast<float>(dstRect.width()) / srcRect.width(); 937 float offsetf = roundf((static_cast<float>(clipRect.x0) - srcRect.x0) * ratio); 938 int offset = static_cast<int>(offsetf); 939 if(flipX) 940 { 941 dstRect.x1 -= offset; 942 } 943 else 944 { 945 dstRect.x0 += offset; 946 } 947 srcRect.x0 += offsetf / ratio; 948 } 949 if(srcRect.x1 > static_cast<float>(clipRect.x1)) 950 { 951 float ratio = static_cast<float>(dstRect.width()) / srcRect.width(); 952 float offsetf = roundf((srcRect.x1 - static_cast<float>(clipRect.x1)) * ratio); 953 int offset = static_cast<int>(offsetf); 954 if(flipX) 955 { 956 dstRect.x0 += offset; 957 } 958 else 959 { 960 dstRect.x1 -= offset; 961 } 962 srcRect.x1 -= offsetf / ratio; 963 } 964 if(srcRect.y0 < static_cast<float>(clipRect.y0)) 965 { 966 float ratio = static_cast<float>(dstRect.height()) / srcRect.height(); 967 float offsetf = roundf((static_cast<float>(clipRect.y0) - srcRect.y0) * ratio); 968 int offset = static_cast<int>(offsetf); 969 if(flipY) 970 { 971 dstRect.y1 -= offset; 972 } 973 else 974 { 975 dstRect.y0 += offset; 976 } 977 srcRect.y0 += offsetf / ratio; 978 } 979 if(srcRect.y1 > static_cast<float>(clipRect.y1)) 980 { 981 float ratio = static_cast<float>(dstRect.height()) / srcRect.height(); 982 float offsetf = roundf((srcRect.y1 - static_cast<float>(clipRect.y1)) * ratio); 983 int offset = static_cast<int>(offsetf); 984 if(flipY) 985 { 986 dstRect.y0 += offset; 987 } 988 else 989 { 990 dstRect.y1 -= offset; 991 } 992 srcRect.y1 -= offsetf / ratio; 993 } 994 } 995 996 void Device::finish() 997 { 998 synchronize(); 999 } 1000 } 1001