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/Timer.hpp" 29 #include "../common/debug.h" 30 31 namespace es2 32 { 33 using namespace sw; 34 Device(Context * context)35 Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) 36 { 37 for(int i = 0; i < RENDERTARGETS; i++) 38 { 39 renderTarget[i] = nullptr; 40 } 41 42 depthBuffer = nullptr; 43 stencilBuffer = nullptr; 44 45 setDepthBufferEnable(true); 46 setFillMode(FILL_SOLID); 47 setShadingMode(SHADING_GOURAUD); 48 setDepthWriteEnable(true); 49 setAlphaTestEnable(false); 50 setSourceBlendFactor(BLEND_ONE); 51 setDestBlendFactor(BLEND_ZERO); 52 setCullMode(CULL_COUNTERCLOCKWISE); 53 setDepthCompare(DEPTH_LESSEQUAL); 54 setAlphaReference(0.0f); 55 setAlphaCompare(ALPHA_ALWAYS); 56 setAlphaBlendEnable(false); 57 setFogEnable(false); 58 setSpecularEnable(false); 59 setFogColor(0); 60 setPixelFogMode(FOG_NONE); 61 setFogStart(0.0f); 62 setFogEnd(1.0f); 63 setFogDensity(1.0f); 64 setRangeFogEnable(false); 65 setStencilEnable(false); 66 setStencilFailOperation(OPERATION_KEEP); 67 setStencilZFailOperation(OPERATION_KEEP); 68 setStencilPassOperation(OPERATION_KEEP); 69 setStencilCompare(STENCIL_ALWAYS); 70 setStencilReference(0); 71 setStencilMask(0xFFFFFFFF); 72 setStencilWriteMask(0xFFFFFFFF); 73 setVertexFogMode(FOG_NONE); 74 setClipFlags(0); 75 setPointSize(1.0f); 76 setPointSizeMin(0.125f); 77 setPointSizeMax(8192.0f); 78 setBlendOperation(BLENDOP_ADD); 79 scissorEnable = false; 80 setSlopeDepthBias(0.0f); 81 setTwoSidedStencil(false); 82 setStencilFailOperationCCW(OPERATION_KEEP); 83 setStencilZFailOperationCCW(OPERATION_KEEP); 84 setStencilPassOperationCCW(OPERATION_KEEP); 85 setStencilCompareCCW(STENCIL_ALWAYS); 86 setBlendConstant(0xFFFFFFFF); 87 setWriteSRGB(false); 88 setDepthBias(0.0f); 89 setSeparateAlphaBlendEnable(false); 90 setSourceBlendFactorAlpha(BLEND_ONE); 91 setDestBlendFactorAlpha(BLEND_ZERO); 92 setBlendOperationAlpha(BLENDOP_ADD); 93 setPointSpriteEnable(true); 94 setColorLogicOpEnabled(false); 95 setLogicalOperation(LOGICALOP_COPY); 96 97 for(int i = 0; i < 16; i++) 98 { 99 setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 100 setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 101 setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 102 setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000); 103 setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT); 104 setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE); 105 setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f); 106 } 107 108 for(int i = 0; i < 4; i++) 109 { 110 setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 111 setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 112 setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 113 setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000); 114 setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT); 115 setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE); 116 setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f); 117 } 118 119 for(int i = 0; i < 6; i++) 120 { 121 float plane[4] = {0, 0, 0, 0}; 122 123 setClipPlane(i, plane); 124 } 125 126 pixelShader = nullptr; 127 vertexShader = nullptr; 128 129 pixelShaderDirty = true; 130 pixelShaderConstantsFDirty = 0; 131 vertexShaderDirty = true; 132 vertexShaderConstantsFDirty = 0; 133 134 for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++) 135 { 136 float zero[4] = {0, 0, 0, 0}; 137 138 setPixelShaderConstantF(i, zero, 1); 139 } 140 141 for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++) 142 { 143 float zero[4] = {0, 0, 0, 0}; 144 145 setVertexShaderConstantF(i, zero, 1); 146 } 147 } 148 ~Device()149 Device::~Device() 150 { 151 for(int i = 0; i < RENDERTARGETS; i++) 152 { 153 if(renderTarget[i]) 154 { 155 renderTarget[i]->release(); 156 renderTarget[i] = nullptr; 157 } 158 } 159 160 if(depthBuffer) 161 { 162 depthBuffer->release(); 163 depthBuffer = nullptr; 164 } 165 166 if(stencilBuffer) 167 { 168 stencilBuffer->release(); 169 stencilBuffer = nullptr; 170 } 171 172 delete context; 173 } 174 clearColor(float red,float green,float blue,float alpha,unsigned int rgbaMask)175 void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask) 176 { 177 if(!rgbaMask) 178 { 179 return; 180 } 181 182 float rgba[4]; 183 rgba[0] = red; 184 rgba[1] = green; 185 rgba[2] = blue; 186 rgba[3] = alpha; 187 188 for(int i = 0; i < RENDERTARGETS; ++i) 189 { 190 if(renderTarget[i]) 191 { 192 sw::SliceRect clearRect = renderTarget[i]->getRect(); 193 194 if(scissorEnable) 195 { 196 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 197 } 198 199 int depth = sw::max(renderTarget[i]->getDepth(), 1); 200 for(clearRect.slice = 0; clearRect.slice < depth; clearRect.slice++) 201 { 202 clear(rgba, FORMAT_A32B32G32R32F, renderTarget[i], clearRect, rgbaMask); 203 } 204 } 205 } 206 } 207 clearDepth(float z)208 void Device::clearDepth(float z) 209 { 210 if(!depthBuffer) 211 { 212 return; 213 } 214 215 z = clamp01(z); 216 sw::SliceRect clearRect = depthBuffer->getRect(); 217 218 if(scissorEnable) 219 { 220 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 221 } 222 223 depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 224 } 225 clearStencil(unsigned int stencil,unsigned int mask)226 void Device::clearStencil(unsigned int stencil, unsigned int mask) 227 { 228 if(!stencilBuffer) 229 { 230 return; 231 } 232 233 sw::SliceRect clearRect = stencilBuffer->getRect(); 234 235 if(scissorEnable) 236 { 237 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 238 } 239 240 stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 241 } 242 createDepthStencilSurface(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool discard)243 egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) 244 { 245 if(height > OUTLINE_RESOLUTION) 246 { 247 ERR("Invalid parameters: %dx%d", width, height); 248 return nullptr; 249 } 250 251 bool lockable = true; 252 253 switch(format) 254 { 255 // case FORMAT_D15S1: 256 case FORMAT_D24S8: 257 case FORMAT_D24X8: 258 // case FORMAT_D24X4S4: 259 case FORMAT_D24FS8: 260 case FORMAT_D32: 261 case FORMAT_D16: 262 case FORMAT_D32F: 263 case FORMAT_D32F_COMPLEMENTARY: 264 lockable = false; 265 break; 266 // case FORMAT_S8_LOCKABLE: 267 // case FORMAT_D16_LOCKABLE: 268 case FORMAT_D32F_LOCKABLE: 269 // case FORMAT_D32_LOCKABLE: 270 case FORMAT_DF24S8: 271 case FORMAT_DF16S8: 272 case FORMAT_D32FS8_TEXTURE: 273 case FORMAT_D32FS8_SHADOW: 274 lockable = true; 275 break; 276 default: 277 UNREACHABLE(format); 278 } 279 280 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); 281 282 if(!surface) 283 { 284 ERR("Out of memory"); 285 return nullptr; 286 } 287 288 return surface; 289 } 290 createRenderTarget(unsigned int width,unsigned int height,sw::Format format,int multiSampleDepth,bool lockable)291 egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable) 292 { 293 if(height > OUTLINE_RESOLUTION) 294 { 295 ERR("Invalid parameters: %dx%d", width, height); 296 return nullptr; 297 } 298 299 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); 300 301 if(!surface) 302 { 303 ERR("Out of memory"); 304 return nullptr; 305 } 306 307 return surface; 308 } 309 drawIndexedPrimitive(sw::DrawType type,unsigned int indexOffset,unsigned int primitiveCount)310 void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount) 311 { 312 if(!bindResources() || !primitiveCount) 313 { 314 return; 315 } 316 317 draw(type, indexOffset, primitiveCount); 318 } 319 drawPrimitive(sw::DrawType type,unsigned int primitiveCount)320 void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount) 321 { 322 if(!bindResources() || !primitiveCount) 323 { 324 return; 325 } 326 327 setIndexBuffer(nullptr); 328 329 draw(type, 0, primitiveCount); 330 } 331 setPixelShader(PixelShader * pixelShader)332 void Device::setPixelShader(PixelShader *pixelShader) 333 { 334 this->pixelShader = pixelShader; 335 pixelShaderDirty = true; 336 } 337 setPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)338 void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) 339 { 340 for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++) 341 { 342 pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0]; 343 pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1]; 344 pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2]; 345 pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3]; 346 } 347 348 pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty); 349 pixelShaderDirty = true; // Reload DEF constants 350 } 351 setScissorEnable(bool enable)352 void Device::setScissorEnable(bool enable) 353 { 354 scissorEnable = enable; 355 } 356 setRenderTarget(int index,egl::Image * renderTarget)357 void Device::setRenderTarget(int index, egl::Image *renderTarget) 358 { 359 if(renderTarget) 360 { 361 renderTarget->addRef(); 362 } 363 364 if(this->renderTarget[index]) 365 { 366 this->renderTarget[index]->release(); 367 } 368 369 this->renderTarget[index] = renderTarget; 370 371 Renderer::setRenderTarget(index, renderTarget); 372 } 373 setDepthBuffer(egl::Image * depthBuffer)374 void Device::setDepthBuffer(egl::Image *depthBuffer) 375 { 376 if(this->depthBuffer == depthBuffer) 377 { 378 return; 379 } 380 381 if(depthBuffer) 382 { 383 depthBuffer->addRef(); 384 } 385 386 if(this->depthBuffer) 387 { 388 this->depthBuffer->release(); 389 } 390 391 this->depthBuffer = depthBuffer; 392 393 Renderer::setDepthBuffer(depthBuffer); 394 } 395 setStencilBuffer(egl::Image * stencilBuffer)396 void Device::setStencilBuffer(egl::Image *stencilBuffer) 397 { 398 if(this->stencilBuffer == stencilBuffer) 399 { 400 return; 401 } 402 403 if(stencilBuffer) 404 { 405 stencilBuffer->addRef(); 406 } 407 408 if(this->stencilBuffer) 409 { 410 this->stencilBuffer->release(); 411 } 412 413 this->stencilBuffer = stencilBuffer; 414 415 Renderer::setStencilBuffer(stencilBuffer); 416 } 417 setScissorRect(const sw::Rect & rect)418 void Device::setScissorRect(const sw::Rect &rect) 419 { 420 scissorRect = rect; 421 } 422 setVertexShader(VertexShader * vertexShader)423 void Device::setVertexShader(VertexShader *vertexShader) 424 { 425 this->vertexShader = vertexShader; 426 vertexShaderDirty = true; 427 } 428 setVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)429 void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) 430 { 431 for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++) 432 { 433 vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0]; 434 vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1]; 435 vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2]; 436 vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3]; 437 } 438 439 vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty); 440 vertexShaderDirty = true; // Reload DEF constants 441 } 442 setViewport(const Viewport & viewport)443 void Device::setViewport(const Viewport &viewport) 444 { 445 this->viewport = viewport; 446 } 447 copyBuffer(sw::byte * sourceBuffer,sw::byte * destBuffer,unsigned int width,unsigned int height,unsigned int sourcePitch,unsigned int destPitch,unsigned int bytes,bool flipX,bool flipY)448 void Device::copyBuffer(sw::byte *sourceBuffer, sw::byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY) 449 { 450 unsigned int widthB = width * bytes; 451 unsigned int widthMaxB = widthB - 1; 452 453 if(flipX) 454 { 455 if(flipY) 456 { 457 sourceBuffer += (height - 1) * sourcePitch; 458 for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch) 459 { 460 for(unsigned int x = 0; x < widthB; ++x) 461 { 462 destBuffer[x] = sourceBuffer[widthMaxB - x]; 463 } 464 } 465 } 466 else 467 { 468 for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch) 469 { 470 for(unsigned int x = 0; x < widthB; ++x) 471 { 472 destBuffer[x] = sourceBuffer[widthMaxB - x]; 473 } 474 } 475 } 476 } 477 else 478 { 479 if(flipY) 480 { 481 sourceBuffer += (height - 1) * sourcePitch; 482 for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch) 483 { 484 memcpy(destBuffer, sourceBuffer, widthB); 485 } 486 } 487 else 488 { 489 for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch) 490 { 491 memcpy(destBuffer, sourceBuffer, widthB); 492 } 493 } 494 } 495 } 496 stretchRect(sw::Surface * source,const sw::SliceRect * sourceRect,sw::Surface * dest,const sw::SliceRect * destRect,bool filter)497 bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter) 498 { 499 if(!source || !dest) 500 { 501 ERR("Invalid parameters"); 502 return false; 503 } 504 505 int sWidth = source->getWidth(); 506 int sHeight = source->getHeight(); 507 int dWidth = dest->getWidth(); 508 int dHeight = dest->getHeight(); 509 510 bool flipX = false; 511 bool flipY = false; 512 if(sourceRect && destRect) 513 { 514 flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1); 515 flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1); 516 } 517 else if(sourceRect) 518 { 519 flipX = (sourceRect->x0 > sourceRect->x1); 520 flipY = (sourceRect->y0 > sourceRect->y1); 521 } 522 else if(destRect) 523 { 524 flipX = (destRect->x0 > destRect->x1); 525 flipY = (destRect->y0 > destRect->y1); 526 } 527 528 SliceRect sRect; 529 SliceRect dRect; 530 531 if(sourceRect) 532 { 533 sRect = *sourceRect; 534 535 if(sRect.x0 > sRect.x1) 536 { 537 swap(sRect.x0, sRect.x1); 538 } 539 540 if(sRect.y0 > sRect.y1) 541 { 542 swap(sRect.y0, sRect.y1); 543 } 544 } 545 else 546 { 547 sRect.y0 = 0; 548 sRect.x0 = 0; 549 sRect.y1 = sHeight; 550 sRect.x1 = sWidth; 551 } 552 553 if(destRect) 554 { 555 dRect = *destRect; 556 557 if(dRect.x0 > dRect.x1) 558 { 559 swap(dRect.x0, dRect.x1); 560 } 561 562 if(dRect.y0 > dRect.y1) 563 { 564 swap(dRect.y0, dRect.y1); 565 } 566 } 567 else 568 { 569 dRect.y0 = 0; 570 dRect.x0 = 0; 571 dRect.y1 = dHeight; 572 dRect.x1 = dWidth; 573 } 574 575 if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest)) 576 { 577 ERR("Invalid parameters"); 578 return false; 579 } 580 581 bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); 582 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 583 bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()); 584 bool alpha0xFF = false; 585 586 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 587 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 588 { 589 equalFormats = true; 590 alpha0xFF = true; 591 } 592 593 if(depthStencil) // Copy entirely, internally // FIXME: Check 594 { 595 if(source->hasDepth()) 596 { 597 sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sourceRect->slice, LOCK_READONLY, PUBLIC); 598 sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, destRect->slice, LOCK_DISCARD, PUBLIC); 599 600 copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY); 601 602 source->unlockInternal(); 603 dest->unlockInternal(); 604 } 605 606 if(source->hasStencil()) 607 { 608 sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC); 609 sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC); 610 611 copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY); 612 613 source->unlockStencil(); 614 dest->unlockStencil(); 615 } 616 } 617 else if(!scaling && equalFormats) 618 { 619 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC); 620 unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, LOCK_READWRITE, PUBLIC); 621 unsigned int sourcePitch = source->getInternalPitchB(); 622 unsigned int destPitch = dest->getInternalPitchB(); 623 624 unsigned int width = dRect.x1 - dRect.x0; 625 unsigned int height = dRect.y1 - dRect.y0; 626 627 copyBuffer(sourceBytes, destBytes, width, height, sourcePitch, destPitch, egl::Image::bytes(source->getInternalFormat()), flipX, flipY); 628 629 if(alpha0xFF) 630 { 631 for(unsigned int y = 0; y < height; ++y, destBytes += destPitch) 632 { 633 for(unsigned int x = 0; x < width; ++x) 634 { 635 destBytes[4 * x + 3] = 0xFF; 636 } 637 } 638 } 639 640 source->unlockInternal(); 641 dest->unlockInternal(); 642 } 643 else 644 { 645 if(flipX) 646 { 647 swap(dRect.x0, dRect.x1); 648 } 649 if(flipY) 650 { 651 swap(dRect.y0, dRect.y1); 652 } 653 blit(source, sRect, dest, dRect, scaling && filter); 654 } 655 656 return true; 657 } 658 stretchCube(sw::Surface * source,sw::Surface * dest)659 bool Device::stretchCube(sw::Surface *source, sw::Surface *dest) 660 { 661 if(!source || !dest || egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat())) 662 { 663 ERR("Invalid parameters"); 664 return false; 665 } 666 667 int sWidth = source->getWidth(); 668 int sHeight = source->getHeight(); 669 int sDepth = source->getDepth(); 670 int dWidth = dest->getWidth(); 671 int dHeight = dest->getHeight(); 672 int dDepth = dest->getDepth(); 673 674 bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth); 675 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 676 bool alpha0xFF = false; 677 678 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 679 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 680 { 681 equalFormats = true; 682 alpha0xFF = true; 683 } 684 685 if(!scaling && equalFormats) 686 { 687 unsigned int sourcePitch = source->getInternalPitchB(); 688 unsigned int destPitch = dest->getInternalPitchB(); 689 unsigned int bytes = dWidth * egl::Image::bytes(source->getInternalFormat()); 690 691 for(int z = 0; z < dDepth; ++z) 692 { 693 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC); 694 unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC); 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 712 source->unlockInternal(); 713 dest->unlockInternal(); 714 } 715 else 716 { 717 blit3D(source, dest); 718 } 719 720 return true; 721 } 722 bindResources()723 bool Device::bindResources() 724 { 725 if(!bindViewport()) 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 setScissor(scissor); 836 } 837 838 sw::Viewport view; 839 view.x0 = (float)viewport.x0; 840 view.y0 = (float)viewport.y0; 841 view.width = (float)viewport.width; 842 view.height = (float)viewport.height; 843 view.minZ = viewport.minZ; 844 view.maxZ = viewport.maxZ; 845 846 Renderer::setViewport(view); 847 848 return true; 849 } 850 validRectangle(const sw::Rect * rect,sw::Surface * surface)851 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) 852 { 853 if(!rect) 854 { 855 return true; 856 } 857 858 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) 859 { 860 return false; 861 } 862 863 if(rect->x0 < 0 || rect->y0 < 0) 864 { 865 return false; 866 } 867 868 if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight()) 869 { 870 return false; 871 } 872 873 return true; 874 } 875 finish()876 void Device::finish() 877 { 878 synchronize(); 879 } 880 } 881