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 31namespace es1 32{ 33 using namespace sw; 34 35 Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) 36 { 37 renderTarget = nullptr; 38 depthBuffer = nullptr; 39 stencilBuffer = nullptr; 40 41 setDepthBufferEnable(true); 42 setFillMode(FILL_SOLID); 43 setShadingMode(SHADING_GOURAUD); 44 setDepthWriteEnable(true); 45 setAlphaTestEnable(false); 46 setSourceBlendFactor(BLEND_ONE); 47 setDestBlendFactor(BLEND_ZERO); 48 setCullMode(CULL_COUNTERCLOCKWISE); 49 setDepthCompare(DEPTH_LESSEQUAL); 50 setAlphaReference(0.0f); 51 setAlphaCompare(ALPHA_ALWAYS); 52 setAlphaBlendEnable(false); 53 setFogEnable(false); 54 setSpecularEnable(true); 55 setLocalViewer(false); 56 setFogColor(0); 57 setPixelFogMode(FOG_NONE); 58 setFogStart(0.0f); 59 setFogEnd(1.0f); 60 setFogDensity(1.0f); 61 setRangeFogEnable(false); 62 setStencilEnable(false); 63 setStencilFailOperation(OPERATION_KEEP); 64 setStencilZFailOperation(OPERATION_KEEP); 65 setStencilPassOperation(OPERATION_KEEP); 66 setStencilCompare(STENCIL_ALWAYS); 67 setStencilReference(0); 68 setStencilMask(0xFFFFFFFF); 69 setStencilWriteMask(0xFFFFFFFF); 70 setVertexFogMode(FOG_NONE); 71 setClipFlags(0); 72 setPointSize(1.0f); 73 setPointSizeMin(0.125f); 74 setPointSizeMax(8192.0f); 75 setColorWriteMask(0, 0x0000000F); 76 setBlendOperation(BLENDOP_ADD); 77 scissorEnable = false; 78 setSlopeDepthBias(0.0f); 79 setTwoSidedStencil(false); 80 setStencilFailOperationCCW(OPERATION_KEEP); 81 setStencilZFailOperationCCW(OPERATION_KEEP); 82 setStencilPassOperationCCW(OPERATION_KEEP); 83 setStencilCompareCCW(STENCIL_ALWAYS); 84 setColorWriteMask(1, 0x0000000F); 85 setColorWriteMask(2, 0x0000000F); 86 setColorWriteMask(3, 0x0000000F); 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 96 for(int i = 0; i < 16; i++) 97 { 98 setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 99 setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 100 setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); 101 setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000); 102 setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT); 103 setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE); 104 setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f); 105 } 106 107 for(int i = 0; i < 4; i++) 108 { 109 setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 110 setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 111 setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); 112 setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000); 113 setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT); 114 setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE); 115 setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f); 116 } 117 118 for(int i = 0; i < 6; i++) 119 { 120 float plane[4] = {0, 0, 0, 0}; 121 122 setClipPlane(i, plane); 123 } 124 } 125 126 Device::~Device() 127 { 128 if(renderTarget) 129 { 130 renderTarget->release(); 131 renderTarget = nullptr; 132 } 133 134 if(depthBuffer) 135 { 136 depthBuffer->release(); 137 depthBuffer = nullptr; 138 } 139 140 if(stencilBuffer) 141 { 142 stencilBuffer->release(); 143 stencilBuffer = nullptr; 144 } 145 146 delete context; 147 } 148 149 void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask) 150 { 151 if(!renderTarget || !rgbaMask) 152 { 153 return; 154 } 155 156 float rgba[4]; 157 rgba[0] = red; 158 rgba[1] = green; 159 rgba[2] = blue; 160 rgba[3] = alpha; 161 162 sw::SliceRect clearRect = renderTarget->getRect(); 163 164 if(scissorEnable) 165 { 166 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 167 } 168 169 clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask); 170 } 171 172 void Device::clearDepth(float z) 173 { 174 if(!depthBuffer) 175 { 176 return; 177 } 178 179 z = clamp01(z); 180 sw::SliceRect clearRect = depthBuffer->getRect(); 181 182 if(scissorEnable) 183 { 184 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 185 } 186 187 depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 188 } 189 190 void Device::clearStencil(unsigned int stencil, unsigned int mask) 191 { 192 if(!stencilBuffer) 193 { 194 return; 195 } 196 197 sw::SliceRect clearRect = stencilBuffer->getRect(); 198 199 if(scissorEnable) 200 { 201 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); 202 } 203 204 stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); 205 } 206 207 egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) 208 { 209 if(height > OUTLINE_RESOLUTION) 210 { 211 ERR("Invalid parameters: %dx%d", width, height); 212 return nullptr; 213 } 214 215 bool lockable = true; 216 217 switch(format) 218 { 219 // case FORMAT_D15S1: 220 case FORMAT_D24S8: 221 case FORMAT_D24X8: 222 // case FORMAT_D24X4S4: 223 case FORMAT_D24FS8: 224 case FORMAT_D32: 225 case FORMAT_D16: 226 lockable = false; 227 break; 228 // case FORMAT_S8_LOCKABLE: 229 // case FORMAT_D16_LOCKABLE: 230 case FORMAT_D32F_LOCKABLE: 231 // case FORMAT_D32_LOCKABLE: 232 case FORMAT_DF24S8: 233 case FORMAT_DF16S8: 234 lockable = true; 235 break; 236 default: 237 UNREACHABLE(format); 238 } 239 240 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); 241 242 if(!surface) 243 { 244 ERR("Out of memory"); 245 return nullptr; 246 } 247 248 return surface; 249 } 250 251 egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable) 252 { 253 if(height > OUTLINE_RESOLUTION) 254 { 255 ERR("Invalid parameters: %dx%d", width, height); 256 return nullptr; 257 } 258 259 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); 260 261 if(!surface) 262 { 263 ERR("Out of memory"); 264 return nullptr; 265 } 266 267 return surface; 268 } 269 270 void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount) 271 { 272 if(!bindResources() || !primitiveCount) 273 { 274 return; 275 } 276 277 draw(type, indexOffset, primitiveCount); 278 } 279 280 void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount) 281 { 282 if(!bindResources() || !primitiveCount) 283 { 284 return; 285 } 286 287 setIndexBuffer(nullptr); 288 289 draw(type, 0, primitiveCount); 290 } 291 292 void Device::setScissorEnable(bool enable) 293 { 294 scissorEnable = enable; 295 } 296 297 void Device::setRenderTarget(int index, egl::Image *renderTarget) 298 { 299 if(renderTarget) 300 { 301 renderTarget->addRef(); 302 } 303 304 if(this->renderTarget) 305 { 306 this->renderTarget->release(); 307 } 308 309 this->renderTarget = renderTarget; 310 311 Renderer::setRenderTarget(index, renderTarget); 312 } 313 314 void Device::setDepthBuffer(egl::Image *depthBuffer) 315 { 316 if(this->depthBuffer == depthBuffer) 317 { 318 return; 319 } 320 321 if(depthBuffer) 322 { 323 depthBuffer->addRef(); 324 } 325 326 if(this->depthBuffer) 327 { 328 this->depthBuffer->release(); 329 } 330 331 this->depthBuffer = depthBuffer; 332 333 Renderer::setDepthBuffer(depthBuffer); 334 } 335 336 void Device::setStencilBuffer(egl::Image *stencilBuffer) 337 { 338 if(this->stencilBuffer == stencilBuffer) 339 { 340 return; 341 } 342 343 if(stencilBuffer) 344 { 345 stencilBuffer->addRef(); 346 } 347 348 if(this->stencilBuffer) 349 { 350 this->stencilBuffer->release(); 351 } 352 353 this->stencilBuffer = stencilBuffer; 354 355 Renderer::setStencilBuffer(stencilBuffer); 356 } 357 358 void Device::setScissorRect(const sw::Rect &rect) 359 { 360 scissorRect = rect; 361 } 362 363 void Device::setViewport(const Viewport &viewport) 364 { 365 this->viewport = viewport; 366 } 367 368 bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter) 369 { 370 if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest)) 371 { 372 ERR("Invalid parameters"); 373 return false; 374 } 375 376 int sWidth = source->getWidth(); 377 int sHeight = source->getHeight(); 378 int dWidth = dest->getWidth(); 379 int dHeight = dest->getHeight(); 380 381 SliceRect sRect; 382 SliceRect dRect; 383 384 if(sourceRect) 385 { 386 sRect = *sourceRect; 387 } 388 else 389 { 390 sRect.y0 = 0; 391 sRect.x0 = 0; 392 sRect.y1 = sHeight; 393 sRect.x1 = sWidth; 394 } 395 396 if(destRect) 397 { 398 dRect = *destRect; 399 } 400 else 401 { 402 dRect.y0 = 0; 403 dRect.x0 = 0; 404 dRect.y1 = dHeight; 405 dRect.x1 = dWidth; 406 } 407 408 bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); 409 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); 410 bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()); 411 bool alpha0xFF = false; 412 413 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || 414 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) 415 { 416 equalFormats = true; 417 alpha0xFF = true; 418 } 419 420 if(depthStencil) // Copy entirely, internally // FIXME: Check 421 { 422 if(source->hasDepth()) 423 { 424 sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC); 425 sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC); 426 427 unsigned int width = source->getWidth(); 428 unsigned int height = source->getHeight(); 429 unsigned int pitch = source->getInternalPitchB(); 430 431 for(unsigned int y = 0; y < height; y++) 432 { 433 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes 434 435 sourceBuffer += pitch; 436 destBuffer += pitch; 437 } 438 439 source->unlockInternal(); 440 dest->unlockInternal(); 441 } 442 443 if(source->hasStencil()) 444 { 445 sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC); 446 sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC); 447 448 unsigned int width = source->getWidth(); 449 unsigned int height = source->getHeight(); 450 unsigned int pitch = source->getStencilPitchB(); 451 452 for(unsigned int y = 0; y < height; y++) 453 { 454 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes 455 456 sourceBuffer += pitch; 457 destBuffer += pitch; 458 } 459 460 source->unlockStencil(); 461 dest->unlockStencil(); 462 } 463 } 464 else if(!scaling && equalFormats) 465 { 466 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC); 467 unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC); 468 unsigned int sourcePitch = source->getInternalPitchB(); 469 unsigned int destPitch = dest->getInternalPitchB(); 470 471 unsigned int width = dRect.x1 - dRect.x0; 472 unsigned int height = dRect.y1 - dRect.y0; 473 unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat()); 474 475 for(unsigned int y = 0; y < height; y++) 476 { 477 memcpy(destBytes, sourceBytes, bytes); 478 479 if(alpha0xFF) 480 { 481 for(unsigned int x = 0; x < width; x++) 482 { 483 destBytes[4 * x + 3] = 0xFF; 484 } 485 } 486 487 sourceBytes += sourcePitch; 488 destBytes += destPitch; 489 } 490 491 source->unlockInternal(); 492 dest->unlockInternal(); 493 } 494 else 495 { 496 blit(source, sRect, dest, dRect, scaling && filter); 497 } 498 499 return true; 500 } 501 502 bool Device::bindResources() 503 { 504 if(!bindViewport()) 505 { 506 return false; // Zero-area target region 507 } 508 509 return true; 510 } 511 512 bool Device::bindViewport() 513 { 514 if(viewport.width <= 0 || viewport.height <= 0) 515 { 516 return false; 517 } 518 519 if(scissorEnable) 520 { 521 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1) 522 { 523 return false; 524 } 525 526 sw::Rect scissor; 527 scissor.x0 = scissorRect.x0; 528 scissor.x1 = scissorRect.x1; 529 scissor.y0 = scissorRect.y0; 530 scissor.y1 = scissorRect.y1; 531 532 setScissor(scissor); 533 } 534 else 535 { 536 sw::Rect scissor; 537 scissor.x0 = viewport.x0; 538 scissor.x1 = viewport.x0 + viewport.width; 539 scissor.y0 = viewport.y0; 540 scissor.y1 = viewport.y0 + viewport.height; 541 542 if(renderTarget) 543 { 544 scissor.x0 = max(scissor.x0, 0); 545 scissor.x1 = min(scissor.x1, renderTarget->getWidth()); 546 scissor.y0 = max(scissor.y0, 0); 547 scissor.y1 = min(scissor.y1, renderTarget->getHeight()); 548 } 549 550 if(depthBuffer) 551 { 552 scissor.x0 = max(scissor.x0, 0); 553 scissor.x1 = min(scissor.x1, depthBuffer->getWidth()); 554 scissor.y0 = max(scissor.y0, 0); 555 scissor.y1 = min(scissor.y1, depthBuffer->getHeight()); 556 } 557 558 if(stencilBuffer) 559 { 560 scissor.x0 = max(scissor.x0, 0); 561 scissor.x1 = min(scissor.x1, stencilBuffer->getWidth()); 562 scissor.y0 = max(scissor.y0, 0); 563 scissor.y1 = min(scissor.y1, stencilBuffer->getHeight()); 564 } 565 566 setScissor(scissor); 567 } 568 569 sw::Viewport view; 570 view.x0 = (float)viewport.x0; 571 view.y0 = (float)viewport.y0; 572 view.width = (float)viewport.width; 573 view.height = (float)viewport.height; 574 view.minZ = viewport.minZ; 575 view.maxZ = viewport.maxZ; 576 577 Renderer::setViewport(view); 578 579 return true; 580 } 581 582 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) 583 { 584 if(!rect) 585 { 586 return true; 587 } 588 589 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) 590 { 591 return false; 592 } 593 594 if(rect->x0 < 0 || rect->y0 < 0) 595 { 596 return false; 597 } 598 599 if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight()) 600 { 601 return false; 602 } 603 604 return true; 605 } 606 607 void Device::finish() 608 { 609 synchronize(); 610 } 611} 612