Device.cpp revision d9762743d768d943003a980005b8c689d94d7cc9
1// SwiftShader Software Renderer 2// 3// Copyright(c) 2005-2013 TransGaming Inc. 4// 5// All rights reserved. No part of this software may be copied, distributed, transmitted, 6// transcribed, stored in a retrieval system, translated into any human or computer 7// language by any means, or disclosed to third parties without the explicit written 8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express 9// or implied, including but not limited to any patent rights, are granted to you. 10// 11 12#include "Device.hpp" 13 14#include "common/Image.hpp" 15#include "Texture.h" 16 17#include "Renderer/Renderer.hpp" 18#include "Renderer/Clipper.hpp" 19#include "Shader/PixelShader.hpp" 20#include "Shader/VertexShader.hpp" 21#include "Main/Config.hpp" 22#include "Main/FrameBuffer.hpp" 23#include "Common/Math.hpp" 24#include "Common/Configurator.hpp" 25#include "Common/Timer.hpp" 26#include "../common/debug.h" 27 28namespace es1 29{ 30 using namespace sw; 31 32 Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) 33 { 34 depthStencil = 0; 35 renderTarget = 0; 36 37 setDepthBufferEnable(true); 38 setFillMode(FILL_SOLID); 39 setShadingMode(SHADING_GOURAUD); 40 setDepthWriteEnable(true); 41 setAlphaTestEnable(false); 42 setSourceBlendFactor(BLEND_ONE); 43 setDestBlendFactor(BLEND_ZERO); 44 setCullMode(CULL_COUNTERCLOCKWISE); 45 setDepthCompare(DEPTH_LESSEQUAL); 46 setAlphaReference(0.0f); 47 setAlphaCompare(ALPHA_ALWAYS); 48 setAlphaBlendEnable(false); 49 setFogEnable(false); 50 setSpecularEnable(false); 51 setFogColor(0); 52 setPixelFogMode(FOG_NONE); 53 setFogStart(0.0f); 54 setFogEnd(1.0f); 55 setFogDensity(1.0f); 56 setRangeFogEnable(false); 57 setStencilEnable(false); 58 setStencilFailOperation(OPERATION_KEEP); 59 setStencilZFailOperation(OPERATION_KEEP); 60 setStencilPassOperation(OPERATION_KEEP); 61 setStencilCompare(STENCIL_ALWAYS); 62 setStencilReference(0); 63 setStencilMask(0xFFFFFFFF); 64 setStencilWriteMask(0xFFFFFFFF); 65 setVertexFogMode(FOG_NONE); 66 setClipFlags(0); 67 setPointSize(1.0f); 68 setPointSizeMin(0.125f); 69 setPointSizeMax(8192.0f); 70 setColorWriteMask(0, 0x0000000F); 71 setBlendOperation(BLENDOP_ADD); 72 scissorEnable = false; 73 setSlopeDepthBias(0.0f); 74 setTwoSidedStencil(false); 75 setStencilFailOperationCCW(OPERATION_KEEP); 76 setStencilZFailOperationCCW(OPERATION_KEEP); 77 setStencilPassOperationCCW(OPERATION_KEEP); 78 setStencilCompareCCW(STENCIL_ALWAYS); 79 setColorWriteMask(1, 0x0000000F); 80 setColorWriteMask(2, 0x0000000F); 81 setColorWriteMask(3, 0x0000000F); 82 setBlendConstant(0xFFFFFFFF); 83 setWriteSRGB(false); 84 setDepthBias(0.0f); 85 setSeparateAlphaBlendEnable(false); 86 setSourceBlendFactorAlpha(BLEND_ONE); 87 setDestBlendFactorAlpha(BLEND_ZERO); 88 setBlendOperationAlpha(BLENDOP_ADD); 89 setPointSpriteEnable(true); 90 setColorLogicOpEnabled(false); 91 setLogicalOperation(LOGICALOP_COPY); 92 93 for(int i = 0; i < 16; i++) 94 { 95 setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 96 setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 97 setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 98 setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000); 99 setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT); 100 setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE); 101 setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f); 102 } 103 104 for(int i = 0; i < 4; i++) 105 { 106 setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 107 setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 108 setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 109 setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000); 110 setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT); 111 setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE); 112 setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f); 113 } 114 115 for(int i = 0; i < 6; i++) 116 { 117 float plane[4] = {0, 0, 0, 0}; 118 119 setClipPlane(i, plane); 120 } 121 } 122 123 Device::~Device() 124 { 125 if(depthStencil) 126 { 127 depthStencil->release(); 128 depthStencil = 0; 129 } 130 131 if(renderTarget) 132 { 133 renderTarget->release(); 134 renderTarget = 0; 135 } 136 137 delete context; 138 } 139 140 void Device::clearColor(unsigned int color, unsigned int rgbaMask) 141 { 142 if(!renderTarget) 143 { 144 return; 145 } 146 147 int x0 = 0; 148 int y0 = 0; 149 int width = renderTarget->getWidth(); 150 int height = renderTarget->getHeight(); 151 152 if(scissorEnable) // Clamp against scissor rectangle 153 { 154 if(x0 < scissorRect.x0) x0 = scissorRect.x0; 155 if(y0 < scissorRect.y0) y0 = scissorRect.y0; 156 if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0; 157 if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0; 158 } 159 160 renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height); 161 } 162 163 void Device::clearDepth(float z) 164 { 165 if(!depthStencil) 166 { 167 return; 168 } 169 170 if(z > 1) z = 1; 171 if(z < 0) z = 0; 172 173 int x0 = 0; 174 int y0 = 0; 175 int width = depthStencil->getWidth(); 176 int height = depthStencil->getHeight(); 177 178 if(scissorEnable) // Clamp against scissor rectangle 179 { 180 if(x0 < scissorRect.x0) x0 = scissorRect.x0; 181 if(y0 < scissorRect.y0) y0 = scissorRect.y0; 182 if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0; 183 if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0; 184 } 185 186 depthStencil->clearDepthBuffer(z, x0, y0, width, height); 187 } 188 189 void Device::clearStencil(unsigned int stencil, unsigned int mask) 190 { 191 if(!depthStencil) 192 { 193 return; 194 } 195 196 int x0 = 0; 197 int y0 = 0; 198 int width = depthStencil->getWidth(); 199 int height = depthStencil->getHeight(); 200 201 if(scissorEnable) // Clamp against scissor rectangle 202 { 203 if(x0 < scissorRect.x0) x0 = scissorRect.x0; 204 if(y0 < scissorRect.y0) y0 = scissorRect.y0; 205 if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0; 206 if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0; 207 } 208 209 depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height); 210 } 211 212 egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) 213 { 214 if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION) 215 { 216 ERR("Invalid parameters"); 217 return 0; 218 } 219 220 bool lockable = true; 221 222 switch(format) 223 { 224 // case FORMAT_D15S1: 225 case FORMAT_D24S8: 226 case FORMAT_D24X8: 227 // case FORMAT_D24X4S4: 228 case FORMAT_D24FS8: 229 case FORMAT_D32: 230 case FORMAT_D16: 231 lockable = false; 232 break; 233 // case FORMAT_S8_LOCKABLE: 234 // case FORMAT_D16_LOCKABLE: 235 case FORMAT_D32F_LOCKABLE: 236 // case FORMAT_D32_LOCKABLE: 237 case FORMAT_DF24S8: 238 case FORMAT_DF16S8: 239 lockable = true; 240 break; 241 default: 242 UNREACHABLE(format); 243 } 244 245 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable, true); 246 247 if(!surface) 248 { 249 ERR("Out of memory"); 250 return 0; 251 } 252 253 return surface; 254 } 255 256 egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable) 257 { 258 if(height > OUTLINE_RESOLUTION) 259 { 260 ERR("Invalid parameters"); 261 return 0; 262 } 263 264 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable, true); 265 266 if(!surface) 267 { 268 ERR("Out of memory"); 269 return 0; 270 } 271 272 return surface; 273 } 274 275 void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize) 276 { 277 if(!bindResources() || !primitiveCount) 278 { 279 return; 280 } 281 282 DrawType drawType; 283 284 if(indexSize == 4) 285 { 286 switch(type) 287 { 288 case DRAW_POINTLIST: drawType = sw::DRAW_INDEXEDPOINTLIST32; break; 289 case DRAW_LINELIST: drawType = sw::DRAW_INDEXEDLINELIST32; break; 290 case DRAW_LINESTRIP: drawType = sw::DRAW_INDEXEDLINESTRIP32; break; 291 case DRAW_LINELOOP: drawType = sw::DRAW_INDEXEDLINELOOP32; break; 292 case DRAW_TRIANGLELIST: drawType = sw::DRAW_INDEXEDTRIANGLELIST32; break; 293 case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break; 294 case DRAW_TRIANGLEFAN: drawType = sw::DRAW_INDEXEDTRIANGLEFAN32; break; 295 default: UNREACHABLE(type); 296 } 297 } 298 else if(indexSize == 2) 299 { 300 switch(type) 301 { 302 case DRAW_POINTLIST: drawType = sw::DRAW_INDEXEDPOINTLIST16; break; 303 case DRAW_LINELIST: drawType = sw::DRAW_INDEXEDLINELIST16; break; 304 case DRAW_LINESTRIP: drawType = sw::DRAW_INDEXEDLINESTRIP16; break; 305 case DRAW_LINELOOP: drawType = sw::DRAW_INDEXEDLINELOOP16; break; 306 case DRAW_TRIANGLELIST: drawType = sw::DRAW_INDEXEDTRIANGLELIST16; break; 307 case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break; 308 case DRAW_TRIANGLEFAN: drawType = sw::DRAW_INDEXEDTRIANGLEFAN16; break; 309 default: UNREACHABLE(type); 310 } 311 } 312 else if(indexSize == 1) 313 { 314 switch(type) 315 { 316 case DRAW_POINTLIST: drawType = sw::DRAW_INDEXEDPOINTLIST8; break; 317 case DRAW_LINELIST: drawType = sw::DRAW_INDEXEDLINELIST8; break; 318 case DRAW_LINESTRIP: drawType = sw::DRAW_INDEXEDLINESTRIP8; break; 319 case DRAW_LINELOOP: drawType = sw::DRAW_INDEXEDLINELOOP8; break; 320 case DRAW_TRIANGLELIST: drawType = sw::DRAW_INDEXEDTRIANGLELIST8; break; 321 case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP8; break; 322 case DRAW_TRIANGLEFAN: drawType = sw::DRAW_INDEXEDTRIANGLEFAN8; break; 323 default: UNREACHABLE(type); 324 } 325 } 326 else UNREACHABLE(indexSize); 327 328 draw(drawType, indexOffset, primitiveCount); 329 } 330 331 void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount) 332 { 333 if(!bindResources() || !primitiveCount) 334 { 335 return; 336 } 337 338 setIndexBuffer(0); 339 340 DrawType drawType; 341 342 switch(primitiveType) 343 { 344 case DRAW_POINTLIST: drawType = sw::DRAW_POINTLIST; break; 345 case DRAW_LINELIST: drawType = sw::DRAW_LINELIST; break; 346 case DRAW_LINESTRIP: drawType = sw::DRAW_LINESTRIP; break; 347 case DRAW_LINELOOP: drawType = sw::DRAW_LINELOOP; break; 348 case DRAW_TRIANGLELIST: drawType = sw::DRAW_TRIANGLELIST; break; 349 case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break; 350 case DRAW_TRIANGLEFAN: drawType = sw::DRAW_TRIANGLEFAN; break; 351 default: UNREACHABLE(primitiveType); 352 } 353 354 draw(drawType, 0, primitiveCount); 355 } 356 357 void Device::setDepthStencilSurface(egl::Image *depthStencil) 358 { 359 if(this->depthStencil == depthStencil) 360 { 361 return; 362 } 363 364 if(depthStencil) 365 { 366 depthStencil->addRef(); 367 } 368 369 if(this->depthStencil) 370 { 371 this->depthStencil->release(); 372 } 373 374 this->depthStencil = depthStencil; 375 376 setDepthStencil(depthStencil); 377 } 378 379 void Device::setScissorEnable(bool enable) 380 { 381 scissorEnable = enable; 382 } 383 384 void Device::setRenderTarget(egl::Image *renderTarget) 385 { 386 if(renderTarget) 387 { 388 renderTarget->addRef(); 389 } 390 391 if(this->renderTarget) 392 { 393 this->renderTarget->release(); 394 } 395 396 this->renderTarget = renderTarget; 397 398 Renderer::setRenderTarget(0, renderTarget); 399 } 400 401 void Device::setScissorRect(const sw::Rect &rect) 402 { 403 scissorRect = rect; 404 } 405 406 void Device::setViewport(const Viewport &viewport) 407 { 408 this->viewport = viewport; 409 } 410 411 bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter) 412 { 413 if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest)) 414 { 415 ERR("Invalid parameters"); 416 return false; 417 } 418 419 int sWidth = source->getWidth(); 420 int sHeight = source->getHeight(); 421 int dWidth = dest->getWidth(); 422 int dHeight = dest->getHeight(); 423 424 SliceRect sRect; 425 SliceRect dRect; 426 427 if(sourceRect) 428 { 429 sRect = *sourceRect; 430 } 431 else 432 { 433 sRect.y0 = 0; 434 sRect.x0 = 0; 435 sRect.y1 = sHeight; 436 sRect.x1 = sWidth; 437 } 438 439 if(destRect) 440 { 441 dRect = *destRect; 442 } 443 else 444 { 445 dRect.y0 = 0; 446 dRect.x0 = 0; 447 dRect.y1 = dHeight; 448 dRect.x1 = dWidth; 449 } 450 451 bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); 452 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 453 bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()); 454 bool alpha0xFF = false; 455 456 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 457 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 458 { 459 equalFormats = true; 460 alpha0xFF = true; 461 } 462 463 if(depthStencil) // Copy entirely, internally // FIXME: Check 464 { 465 if(source->hasDepth()) 466 { 467 sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC); 468 sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC); 469 470 unsigned int width = source->getWidth(); 471 unsigned int height = source->getHeight(); 472 unsigned int pitch = source->getInternalPitchB(); 473 474 for(unsigned int y = 0; y < height; y++) 475 { 476 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes 477 478 sourceBuffer += pitch; 479 destBuffer += pitch; 480 } 481 482 source->unlockInternal(); 483 dest->unlockInternal(); 484 } 485 486 if(source->hasStencil()) 487 { 488 sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC); 489 sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC); 490 491 unsigned int width = source->getWidth(); 492 unsigned int height = source->getHeight(); 493 unsigned int pitch = source->getStencilPitchB(); 494 495 for(unsigned int y = 0; y < height; y++) 496 { 497 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes 498 499 sourceBuffer += pitch; 500 destBuffer += pitch; 501 } 502 503 source->unlockStencil(); 504 dest->unlockStencil(); 505 } 506 } 507 else if(!scaling && equalFormats) 508 { 509 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC); 510 unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC); 511 unsigned int sourcePitch = source->getInternalPitchB(); 512 unsigned int destPitch = dest->getInternalPitchB(); 513 514 unsigned int width = dRect.x1 - dRect.x0; 515 unsigned int height = dRect.y1 - dRect.y0; 516 unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat()); 517 518 for(unsigned int y = 0; y < height; y++) 519 { 520 memcpy(destBytes, sourceBytes, bytes); 521 522 if(alpha0xFF) 523 { 524 for(unsigned int x = 0; x < width; x++) 525 { 526 destBytes[4 * x + 3] = 0xFF; 527 } 528 } 529 530 sourceBytes += sourcePitch; 531 destBytes += destPitch; 532 } 533 534 source->unlockInternal(); 535 dest->unlockInternal(); 536 } 537 else 538 { 539 blit(source, sRect, dest, dRect, scaling && filter); 540 } 541 542 return true; 543 } 544 545 bool Device::bindResources() 546 { 547 if(!bindViewport()) 548 { 549 return false; // Zero-area target region 550 } 551 552 return true; 553 } 554 555 bool Device::bindViewport() 556 { 557 if(viewport.width <= 0 || viewport.height <= 0) 558 { 559 return false; 560 } 561 562 if(scissorEnable) 563 { 564 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1) 565 { 566 return false; 567 } 568 569 sw::Rect scissor; 570 scissor.x0 = scissorRect.x0; 571 scissor.x1 = scissorRect.x1; 572 scissor.y0 = scissorRect.y0; 573 scissor.y1 = scissorRect.y1; 574 575 setScissor(scissor); 576 } 577 else 578 { 579 sw::Rect scissor; 580 scissor.x0 = viewport.x0; 581 scissor.x1 = viewport.x0 + viewport.width; 582 scissor.y0 = viewport.y0; 583 scissor.y1 = viewport.y0 + viewport.height; 584 585 if(renderTarget) 586 { 587 scissor.x0 = max(scissor.x0, 0); 588 scissor.x1 = min(scissor.x1, renderTarget->getWidth()); 589 scissor.y0 = max(scissor.y0, 0); 590 scissor.y1 = min(scissor.y1, renderTarget->getHeight()); 591 } 592 593 if(depthStencil) 594 { 595 scissor.x0 = max(scissor.x0, 0); 596 scissor.x1 = min(scissor.x1, depthStencil->getWidth()); 597 scissor.y0 = max(scissor.y0, 0); 598 scissor.y1 = min(scissor.y1, depthStencil->getHeight()); 599 } 600 601 setScissor(scissor); 602 } 603 604 sw::Viewport view; 605 view.x0 = (float)viewport.x0; 606 view.y0 = (float)viewport.y0; 607 view.width = (float)viewport.width; 608 view.height = (float)viewport.height; 609 view.minZ = viewport.minZ; 610 view.maxZ = viewport.maxZ; 611 612 Renderer::setViewport(view); 613 614 return true; 615 } 616 617 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) 618 { 619 if(!rect) 620 { 621 return true; 622 } 623 624 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) 625 { 626 return false; 627 } 628 629 if(rect->x0 < 0 || rect->y0 < 0) 630 { 631 return false; 632 } 633 634 if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight()) 635 { 636 return false; 637 } 638 639 return true; 640 } 641 642 void Device::finish() 643 { 644 synchronize(); 645 } 646} 647