Device.cpp revision 426cb5e11112c9a9c3a7f145474a29e5e81463ca
1// Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "Device.hpp" 16 17#include "common/Image.hpp" 18#include "Texture.h" 19 20#include "Renderer/Renderer.hpp" 21#include "Renderer/Clipper.hpp" 22#include "Shader/PixelShader.hpp" 23#include "Shader/VertexShader.hpp" 24#include "Main/Config.hpp" 25#include "Main/FrameBuffer.hpp" 26#include "Common/Math.hpp" 27#include "Common/Configurator.hpp" 28#include "Common/Memory.hpp" 29#include "Common/Timer.hpp" 30#include "../common/debug.h" 31 32namespace es1 33{ 34 using namespace sw; 35 36 Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) 37 { 38 renderTarget = nullptr; 39 depthBuffer = nullptr; 40 stencilBuffer = nullptr; 41 42 setDepthBufferEnable(true); 43 setFillMode(FILL_SOLID); 44 setShadingMode(SHADING_GOURAUD); 45 setDepthWriteEnable(true); 46 setAlphaTestEnable(false); 47 setSourceBlendFactor(BLEND_ONE); 48 setDestBlendFactor(BLEND_ZERO); 49 setCullMode(CULL_COUNTERCLOCKWISE); 50 setDepthCompare(DEPTH_LESSEQUAL); 51 setAlphaReference(0.0f); 52 setAlphaCompare(ALPHA_ALWAYS); 53 setAlphaBlendEnable(false); 54 setFogEnable(false); 55 setSpecularEnable(true); 56 setLocalViewer(false); 57 setFogColor(0); 58 setPixelFogMode(FOG_NONE); 59 setFogStart(0.0f); 60 setFogEnd(1.0f); 61 setFogDensity(1.0f); 62 setRangeFogEnable(false); 63 setStencilEnable(false); 64 setStencilFailOperation(OPERATION_KEEP); 65 setStencilZFailOperation(OPERATION_KEEP); 66 setStencilPassOperation(OPERATION_KEEP); 67 setStencilCompare(STENCIL_ALWAYS); 68 setStencilReference(0); 69 setStencilMask(0xFFFFFFFF); 70 setStencilWriteMask(0xFFFFFFFF); 71 setVertexFogMode(FOG_NONE); 72 setClipFlags(0); 73 setPointSize(1.0f); 74 setPointSizeMin(0.125f); 75 setPointSizeMax(8192.0f); 76 setColorWriteMask(0, 0x0000000F); 77 setBlendOperation(BLENDOP_ADD); 78 scissorEnable = false; 79 setSlopeDepthBias(0.0f); 80 setTwoSidedStencil(false); 81 setStencilFailOperationCCW(OPERATION_KEEP); 82 setStencilZFailOperationCCW(OPERATION_KEEP); 83 setStencilPassOperationCCW(OPERATION_KEEP); 84 setStencilCompareCCW(STENCIL_ALWAYS); 85 setColorWriteMask(1, 0x0000000F); 86 setColorWriteMask(2, 0x0000000F); 87 setColorWriteMask(3, 0x0000000F); 88 setBlendConstant(0xFFFFFFFF); 89 setWriteSRGB(false); 90 setDepthBias(0.0f); 91 setSeparateAlphaBlendEnable(false); 92 setSourceBlendFactorAlpha(BLEND_ONE); 93 setDestBlendFactorAlpha(BLEND_ZERO); 94 setBlendOperationAlpha(BLENDOP_ADD); 95 setPointSpriteEnable(true); 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 127 Device::~Device() 128 { 129 if(renderTarget) 130 { 131 renderTarget->release(); 132 renderTarget = nullptr; 133 } 134 135 if(depthBuffer) 136 { 137 depthBuffer->release(); 138 depthBuffer = nullptr; 139 } 140 141 if(stencilBuffer) 142 { 143 stencilBuffer->release(); 144 stencilBuffer = nullptr; 145 } 146 147 delete context; 148 } 149 150 // This object has to be mem aligned 151 void* Device::operator new(size_t size) 152 { 153 ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class 154 return sw::allocate(sizeof(Device), 16); 155 } 156 157 void Device::operator delete(void * mem) 158 { 159 sw::deallocate(mem); 160 } 161 162 void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask) 163 { 164 if(!renderTarget || !rgbaMask) 165 { 166 return; 167 } 168 169 float rgba[4]; 170 rgba[0] = red; 171 rgba[1] = green; 172 rgba[2] = blue; 173 rgba[3] = alpha; 174 175 sw::Rect clearRect = renderTarget->getRect(); 176 177 if(scissorEnable) 178 { 179 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 180 } 181 182 clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask); 183 } 184 185 void Device::clearDepth(float z) 186 { 187 if(!depthBuffer) 188 { 189 return; 190 } 191 192 z = clamp01(z); 193 sw::Rect clearRect = depthBuffer->getRect(); 194 195 if(scissorEnable) 196 { 197 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 198 } 199 200 depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 201 } 202 203 void Device::clearStencil(unsigned int stencil, unsigned int mask) 204 { 205 if(!stencilBuffer) 206 { 207 return; 208 } 209 210 sw::Rect clearRect = stencilBuffer->getRect(); 211 212 if(scissorEnable) 213 { 214 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 215 } 216 217 stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 218 } 219 220 egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) 221 { 222 if(height > OUTLINE_RESOLUTION) 223 { 224 ERR("Invalid parameters: %dx%d", width, height); 225 return nullptr; 226 } 227 228 bool lockable = true; 229 230 switch(format) 231 { 232 // case FORMAT_D15S1: 233 case FORMAT_D24S8: 234 case FORMAT_D24X8: 235 // case FORMAT_D24X4S4: 236 case FORMAT_D24FS8: 237 case FORMAT_D32: 238 case FORMAT_D16: 239 lockable = false; 240 break; 241 // case FORMAT_S8_LOCKABLE: 242 // case FORMAT_D16_LOCKABLE: 243 case FORMAT_D32F_LOCKABLE: 244 // case FORMAT_D32_LOCKABLE: 245 case FORMAT_DF24S8: 246 case FORMAT_DF16S8: 247 lockable = true; 248 break; 249 default: 250 UNREACHABLE(format); 251 } 252 253 egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable); 254 255 if(!surface) 256 { 257 ERR("Out of memory"); 258 return nullptr; 259 } 260 261 return surface; 262 } 263 264 egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable) 265 { 266 if(height > OUTLINE_RESOLUTION) 267 { 268 ERR("Invalid parameters: %dx%d", width, height); 269 return nullptr; 270 } 271 272 egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable); 273 274 if(!surface) 275 { 276 ERR("Out of memory"); 277 return nullptr; 278 } 279 280 return surface; 281 } 282 283 void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount) 284 { 285 if(!bindResources() || !primitiveCount) 286 { 287 return; 288 } 289 290 draw(type, indexOffset, primitiveCount); 291 } 292 293 void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount) 294 { 295 if(!bindResources() || !primitiveCount) 296 { 297 return; 298 } 299 300 setIndexBuffer(nullptr); 301 302 draw(type, 0, primitiveCount); 303 } 304 305 void Device::setScissorEnable(bool enable) 306 { 307 scissorEnable = enable; 308 } 309 310 void Device::setRenderTarget(int index, egl::Image *renderTarget) 311 { 312 if(renderTarget) 313 { 314 renderTarget->addRef(); 315 } 316 317 if(this->renderTarget) 318 { 319 this->renderTarget->release(); 320 } 321 322 this->renderTarget = renderTarget; 323 324 Renderer::setRenderTarget(index, renderTarget); 325 } 326 327 void Device::setDepthBuffer(egl::Image *depthBuffer) 328 { 329 if(this->depthBuffer == depthBuffer) 330 { 331 return; 332 } 333 334 if(depthBuffer) 335 { 336 depthBuffer->addRef(); 337 } 338 339 if(this->depthBuffer) 340 { 341 this->depthBuffer->release(); 342 } 343 344 this->depthBuffer = depthBuffer; 345 346 Renderer::setDepthBuffer(depthBuffer); 347 } 348 349 void Device::setStencilBuffer(egl::Image *stencilBuffer) 350 { 351 if(this->stencilBuffer == stencilBuffer) 352 { 353 return; 354 } 355 356 if(stencilBuffer) 357 { 358 stencilBuffer->addRef(); 359 } 360 361 if(this->stencilBuffer) 362 { 363 this->stencilBuffer->release(); 364 } 365 366 this->stencilBuffer = stencilBuffer; 367 368 Renderer::setStencilBuffer(stencilBuffer); 369 } 370 371 void Device::setScissorRect(const sw::Rect &rect) 372 { 373 scissorRect = rect; 374 } 375 376 void Device::setViewport(const Viewport &viewport) 377 { 378 this->viewport = viewport; 379 } 380 381 bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter) 382 { 383 if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest)) 384 { 385 ERR("Invalid parameters"); 386 return false; 387 } 388 389 int sWidth = source->getWidth(); 390 int sHeight = source->getHeight(); 391 int dWidth = dest->getWidth(); 392 int dHeight = dest->getHeight(); 393 394 SliceRect sRect; 395 SliceRect dRect; 396 397 if(sourceRect) 398 { 399 sRect = *sourceRect; 400 } 401 else 402 { 403 sRect.y0 = 0; 404 sRect.x0 = 0; 405 sRect.y1 = sHeight; 406 sRect.x1 = sWidth; 407 } 408 409 if(destRect) 410 { 411 dRect = *destRect; 412 } 413 else 414 { 415 dRect.y0 = 0; 416 dRect.x0 = 0; 417 dRect.y1 = dHeight; 418 dRect.x1 = dWidth; 419 } 420 421 bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); 422 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 423 bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()); 424 bool alpha0xFF = false; 425 426 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 427 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 428 { 429 equalFormats = true; 430 alpha0xFF = true; 431 } 432 433 if(depthStencil) // Copy entirely, internally // FIXME: Check 434 { 435 if(source->hasDepth()) 436 { 437 sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC); 438 sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC); 439 440 unsigned int width = source->getWidth(); 441 unsigned int height = source->getHeight(); 442 unsigned int pitch = source->getInternalPitchB(); 443 444 for(unsigned int y = 0; y < height; y++) 445 { 446 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes 447 448 sourceBuffer += pitch; 449 destBuffer += pitch; 450 } 451 452 source->unlockInternal(); 453 dest->unlockInternal(); 454 } 455 456 if(source->hasStencil()) 457 { 458 sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC); 459 sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC); 460 461 unsigned int width = source->getWidth(); 462 unsigned int height = source->getHeight(); 463 unsigned int pitch = source->getStencilPitchB(); 464 465 for(unsigned int y = 0; y < height; y++) 466 { 467 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes 468 469 sourceBuffer += pitch; 470 destBuffer += pitch; 471 } 472 473 source->unlockStencil(); 474 dest->unlockStencil(); 475 } 476 } 477 else if(!scaling && equalFormats) 478 { 479 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC); 480 unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC); 481 unsigned int sourcePitch = source->getInternalPitchB(); 482 unsigned int destPitch = dest->getInternalPitchB(); 483 484 unsigned int width = dRect.x1 - dRect.x0; 485 unsigned int height = dRect.y1 - dRect.y0; 486 unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat()); 487 488 for(unsigned int y = 0; y < height; y++) 489 { 490 memcpy(destBytes, sourceBytes, bytes); 491 492 if(alpha0xFF) 493 { 494 for(unsigned int x = 0; x < width; x++) 495 { 496 destBytes[4 * x + 3] = 0xFF; 497 } 498 } 499 500 sourceBytes += sourcePitch; 501 destBytes += destPitch; 502 } 503 504 source->unlockInternal(); 505 dest->unlockInternal(); 506 } 507 else 508 { 509 blit(source, sRect, dest, dRect, scaling && filter); 510 } 511 512 return true; 513 } 514 515 bool Device::bindResources() 516 { 517 if(!bindViewport()) 518 { 519 return false; // Zero-area target region 520 } 521 522 return true; 523 } 524 525 bool Device::bindViewport() 526 { 527 if(viewport.width <= 0 || viewport.height <= 0) 528 { 529 return false; 530 } 531 532 if(scissorEnable) 533 { 534 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1) 535 { 536 return false; 537 } 538 539 sw::Rect scissor; 540 scissor.x0 = scissorRect.x0; 541 scissor.x1 = scissorRect.x1; 542 scissor.y0 = scissorRect.y0; 543 scissor.y1 = scissorRect.y1; 544 545 setScissor(scissor); 546 } 547 else 548 { 549 sw::Rect scissor; 550 scissor.x0 = viewport.x0; 551 scissor.x1 = viewport.x0 + viewport.width; 552 scissor.y0 = viewport.y0; 553 scissor.y1 = viewport.y0 + viewport.height; 554 555 if(renderTarget) 556 { 557 scissor.x0 = max(scissor.x0, 0); 558 scissor.x1 = min(scissor.x1, renderTarget->getWidth()); 559 scissor.y0 = max(scissor.y0, 0); 560 scissor.y1 = min(scissor.y1, renderTarget->getHeight()); 561 } 562 563 if(depthBuffer) 564 { 565 scissor.x0 = max(scissor.x0, 0); 566 scissor.x1 = min(scissor.x1, depthBuffer->getWidth()); 567 scissor.y0 = max(scissor.y0, 0); 568 scissor.y1 = min(scissor.y1, depthBuffer->getHeight()); 569 } 570 571 if(stencilBuffer) 572 { 573 scissor.x0 = max(scissor.x0, 0); 574 scissor.x1 = min(scissor.x1, stencilBuffer->getWidth()); 575 scissor.y0 = max(scissor.y0, 0); 576 scissor.y1 = min(scissor.y1, stencilBuffer->getHeight()); 577 } 578 579 setScissor(scissor); 580 } 581 582 sw::Viewport view; 583 view.x0 = (float)viewport.x0; 584 view.y0 = (float)viewport.y0; 585 view.width = (float)viewport.width; 586 view.height = (float)viewport.height; 587 view.minZ = viewport.minZ; 588 view.maxZ = viewport.maxZ; 589 590 Renderer::setViewport(view); 591 592 return true; 593 } 594 595 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) 596 { 597 if(!rect) 598 { 599 return true; 600 } 601 602 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) 603 { 604 return false; 605 } 606 607 if(rect->x0 < 0 || rect->y0 < 0) 608 { 609 return false; 610 } 611 612 if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight()) 613 { 614 return false; 615 } 616 617 return true; 618 } 619 620 void Device::finish() 621 { 622 synchronize(); 623 } 624} 625