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 #ifndef sw_Surface_hpp 16 #define sw_Surface_hpp 17 18 #include "Color.hpp" 19 #include "Main/Config.hpp" 20 #include "Common/Resource.hpp" 21 22 namespace sw 23 { 24 class Resource; 25 26 template <typename T> struct RectT 27 { 28 RectT() {} 29 RectT(T x0i, T y0i, T x1i, T y1i) : x0(x0i), y0(y0i), x1(x1i), y1(y1i) {} 30 31 void clip(T minX, T minY, T maxX, T maxY) 32 { 33 x0 = clamp(x0, minX, maxX); 34 y0 = clamp(y0, minY, maxY); 35 x1 = clamp(x1, minX, maxX); 36 y1 = clamp(y1, minY, maxY); 37 } 38 39 T width() const { return x1 - x0; } 40 T height() const { return y1 - y0; } 41 42 T x0; // Inclusive 43 T y0; // Inclusive 44 T x1; // Exclusive 45 T y1; // Exclusive 46 }; 47 48 typedef RectT<int> Rect; 49 typedef RectT<float> RectF; 50 51 template<typename T> struct SliceRectT : public RectT<T> 52 { 53 SliceRectT() : slice(0) {} 54 SliceRectT(const RectT<T>& rect) : RectT<T>(rect), slice(0) {} 55 SliceRectT(const RectT<T>& rect, int s) : RectT<T>(rect), slice(s) {} 56 SliceRectT(T x0, T y0, T x1, T y1, int s) : RectT<T>(x0, y0, x1, y1), slice(s) {} 57 int slice; 58 }; 59 60 typedef SliceRectT<int> SliceRect; 61 typedef SliceRectT<float> SliceRectF; 62 63 enum Format : unsigned char 64 { 65 FORMAT_NULL, 66 67 FORMAT_A8, 68 FORMAT_R8I, 69 FORMAT_R8UI, 70 FORMAT_R8_SNORM, 71 FORMAT_R8, 72 FORMAT_R16I, 73 FORMAT_R16UI, 74 FORMAT_R32I, 75 FORMAT_R32UI, 76 FORMAT_R3G3B2, 77 FORMAT_A8R3G3B2, 78 FORMAT_X4R4G4B4, 79 FORMAT_A4R4G4B4, 80 FORMAT_R4G4B4A4, 81 FORMAT_R5G6B5, 82 FORMAT_R8G8B8, 83 FORMAT_B8G8R8, 84 FORMAT_X8R8G8B8, 85 FORMAT_A8R8G8B8, 86 FORMAT_X8B8G8R8I, 87 FORMAT_X8B8G8R8UI, 88 FORMAT_X8B8G8R8_SNORM, 89 FORMAT_X8B8G8R8, 90 FORMAT_A8B8G8R8I, 91 FORMAT_A8B8G8R8UI, 92 FORMAT_A8B8G8R8_SNORM, 93 FORMAT_A8B8G8R8, 94 FORMAT_SRGB8_X8, 95 FORMAT_SRGB8_A8, 96 FORMAT_X1R5G5B5, 97 FORMAT_A1R5G5B5, 98 FORMAT_R5G5B5A1, 99 FORMAT_G8R8I, 100 FORMAT_G8R8UI, 101 FORMAT_G8R8_SNORM, 102 FORMAT_G8R8, 103 FORMAT_G16R16, 104 FORMAT_G16R16I, 105 FORMAT_G16R16UI, 106 FORMAT_G32R32I, 107 FORMAT_G32R32UI, 108 FORMAT_A2R10G10B10, 109 FORMAT_A2B10G10R10, 110 FORMAT_A2B10G10R10UI, 111 FORMAT_A16B16G16R16, 112 FORMAT_X16B16G16R16I, 113 FORMAT_X16B16G16R16UI, 114 FORMAT_A16B16G16R16I, 115 FORMAT_A16B16G16R16UI, 116 FORMAT_X32B32G32R32I, 117 FORMAT_X32B32G32R32UI, 118 FORMAT_A32B32G32R32I, 119 FORMAT_A32B32G32R32UI, 120 // Paletted formats 121 FORMAT_P8, 122 FORMAT_A8P8, 123 // Compressed formats 124 FORMAT_DXT1, 125 FORMAT_DXT3, 126 FORMAT_DXT5, 127 FORMAT_ATI1, 128 FORMAT_ATI2, 129 FORMAT_ETC1, 130 FORMAT_R11_EAC, 131 FORMAT_SIGNED_R11_EAC, 132 FORMAT_RG11_EAC, 133 FORMAT_SIGNED_RG11_EAC, 134 FORMAT_RGB8_ETC2, 135 FORMAT_SRGB8_ETC2, 136 FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 137 FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 138 FORMAT_RGBA8_ETC2_EAC, 139 FORMAT_SRGB8_ALPHA8_ETC2_EAC, 140 FORMAT_RGBA_ASTC_4x4_KHR, 141 FORMAT_RGBA_ASTC_5x4_KHR, 142 FORMAT_RGBA_ASTC_5x5_KHR, 143 FORMAT_RGBA_ASTC_6x5_KHR, 144 FORMAT_RGBA_ASTC_6x6_KHR, 145 FORMAT_RGBA_ASTC_8x5_KHR, 146 FORMAT_RGBA_ASTC_8x6_KHR, 147 FORMAT_RGBA_ASTC_8x8_KHR, 148 FORMAT_RGBA_ASTC_10x5_KHR, 149 FORMAT_RGBA_ASTC_10x6_KHR, 150 FORMAT_RGBA_ASTC_10x8_KHR, 151 FORMAT_RGBA_ASTC_10x10_KHR, 152 FORMAT_RGBA_ASTC_12x10_KHR, 153 FORMAT_RGBA_ASTC_12x12_KHR, 154 FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR, 155 FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR, 156 FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR, 157 FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR, 158 FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR, 159 FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR, 160 FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR, 161 FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR, 162 FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR, 163 FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR, 164 FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR, 165 FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR, 166 FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR, 167 FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR, 168 // Floating-point formats 169 FORMAT_A16F, 170 FORMAT_R16F, 171 FORMAT_G16R16F, 172 FORMAT_B16G16R16F, 173 FORMAT_X16B16G16R16F, 174 FORMAT_A16B16G16R16F, 175 FORMAT_X16B16G16R16F_UNSIGNED, 176 FORMAT_A32F, 177 FORMAT_R32F, 178 FORMAT_G32R32F, 179 FORMAT_B32G32R32F, 180 FORMAT_X32B32G32R32F, 181 FORMAT_A32B32G32R32F, 182 FORMAT_X32B32G32R32F_UNSIGNED, 183 // Bump map formats 184 FORMAT_V8U8, 185 FORMAT_L6V5U5, 186 FORMAT_Q8W8V8U8, 187 FORMAT_X8L8V8U8, 188 FORMAT_A2W10V10U10, 189 FORMAT_V16U16, 190 FORMAT_A16W16V16U16, 191 FORMAT_Q16W16V16U16, 192 // Luminance formats 193 FORMAT_L8, 194 FORMAT_A4L4, 195 FORMAT_L16, 196 FORMAT_A8L8, 197 FORMAT_L16F, 198 FORMAT_A16L16F, 199 FORMAT_L32F, 200 FORMAT_A32L32F, 201 // Depth/stencil formats 202 FORMAT_D16, 203 FORMAT_D32, 204 FORMAT_D24X8, 205 FORMAT_D24S8, 206 FORMAT_D24FS8, 207 FORMAT_D32F, // Quad layout 208 FORMAT_D32FS8, // Quad layout 209 FORMAT_D32F_COMPLEMENTARY, // Quad layout, 1 - z 210 FORMAT_D32FS8_COMPLEMENTARY, // Quad layout, 1 - z 211 FORMAT_D32F_LOCKABLE, // Linear layout 212 FORMAT_D32FS8_TEXTURE, // Linear layout, no PCF 213 FORMAT_D32F_SHADOW, // Linear layout, PCF 214 FORMAT_D32FS8_SHADOW, // Linear layout, PCF 215 FORMAT_DF24S8, 216 FORMAT_DF16S8, 217 FORMAT_INTZ, 218 FORMAT_S8, 219 // Quad layout framebuffer 220 FORMAT_X8G8R8B8Q, 221 FORMAT_A8G8R8B8Q, 222 // YUV formats 223 FORMAT_YV12_BT601, 224 FORMAT_YV12_BT709, 225 FORMAT_YV12_JFIF, // Full-swing BT.601 226 227 FORMAT_LAST = FORMAT_YV12_JFIF 228 }; 229 230 enum Lock 231 { 232 LOCK_UNLOCKED, 233 LOCK_READONLY, 234 LOCK_WRITEONLY, 235 LOCK_READWRITE, 236 LOCK_DISCARD, 237 LOCK_UPDATE // Write access which doesn't dirty the buffer, because it's being updated with the sibling's data. 238 }; 239 240 class [[clang::lto_visibility_public]] Surface 241 { 242 private: 243 struct Buffer 244 { 245 friend Surface; 246 247 private: 248 void write(int x, int y, int z, const Color<float> &color); 249 void write(int x, int y, const Color<float> &color); 250 void write(void *element, const Color<float> &color); 251 Color<float> read(int x, int y, int z) const; 252 Color<float> read(int x, int y) const; 253 Color<float> read(void *element) const; 254 Color<float> sample(float x, float y, float z) const; 255 Color<float> sample(float x, float y, int layer) const; 256 257 void *lockRect(int x, int y, int z, Lock lock); 258 void unlockRect(); 259 260 void *buffer; 261 int width; 262 int height; 263 int depth; 264 short border; 265 short samples; 266 267 int bytes; 268 int pitchB; 269 int pitchP; 270 int sliceB; 271 int sliceP; 272 273 Format format; 274 AtomicInt lock; 275 276 bool dirty; // Sibling internal/external buffer doesn't match. 277 }; 278 279 protected: 280 Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice); 281 Surface(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0); 282 283 public: 284 static Surface *create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice); 285 static Surface *create(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0); 286 287 virtual ~Surface() = 0; 288 289 inline void *lock(int x, int y, int z, Lock lock, Accessor client, bool internal = false); 290 inline void unlock(bool internal = false); 291 inline int getWidth() const; 292 inline int getHeight() const; 293 inline int getDepth() const; 294 inline int getBorder() const; 295 inline Format getFormat(bool internal = false) const; 296 inline int getPitchB(bool internal = false) const; 297 inline int getPitchP(bool internal = false) const; 298 inline int getSliceB(bool internal = false) const; 299 inline int getSliceP(bool internal = false) const; 300 301 void *lockExternal(int x, int y, int z, Lock lock, Accessor client); 302 void unlockExternal(); 303 inline Format getExternalFormat() const; 304 inline int getExternalPitchB() const; 305 inline int getExternalPitchP() const; 306 inline int getExternalSliceB() const; 307 inline int getExternalSliceP() const; 308 309 virtual void *lockInternal(int x, int y, int z, Lock lock, Accessor client) = 0; 310 virtual void unlockInternal() = 0; 311 inline Format getInternalFormat() const; 312 inline int getInternalPitchB() const; 313 inline int getInternalPitchP() const; 314 inline int getInternalSliceB() const; 315 inline int getInternalSliceP() const; 316 317 void *lockStencil(int x, int y, int front, Accessor client); 318 void unlockStencil(); 319 inline Format getStencilFormat() const; 320 inline int getStencilPitchB() const; 321 inline int getStencilSliceB() const; 322 323 void sync(); // Wait for lock(s) to be released. 324 virtual bool requiresSync() const { return false; } 325 inline bool isUnlocked() const; // Only reliable after sync(). 326 327 inline int getSamples() const; 328 inline int getMultiSampleCount() const; 329 inline int getSuperSampleCount() const; 330 331 bool isEntire(const Rect& rect) const; 332 Rect getRect() const; 333 void clearDepth(float depth, int x0, int y0, int width, int height); 334 void clearStencil(unsigned char stencil, unsigned char mask, int x0, int y0, int width, int height); 335 void fill(const Color<float> &color, int x0, int y0, int width, int height); 336 337 Color<float> readExternal(int x, int y, int z) const; 338 Color<float> readExternal(int x, int y) const; 339 Color<float> sampleExternal(float x, float y, float z) const; 340 Color<float> sampleExternal(float x, float y) const; 341 void writeExternal(int x, int y, int z, const Color<float> &color); 342 void writeExternal(int x, int y, const Color<float> &color); 343 344 void copyInternal(const Surface* src, int x, int y, float srcX, float srcY, bool filter); 345 void copyInternal(const Surface* src, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter); 346 347 enum Edge { TOP, BOTTOM, RIGHT, LEFT }; 348 void copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge); 349 void computeCubeCorner(int x0, int y0, int x1, int y1); 350 351 bool hasStencil() const; 352 bool hasDepth() const; 353 bool hasPalette() const; 354 bool isRenderTarget() const; 355 356 bool hasDirtyContents() const; 357 void markContentsClean(); 358 inline bool isExternalDirty() const; 359 Resource *getResource(); 360 361 static int bytes(Format format); 362 static int pitchB(int width, int border, Format format, bool target); 363 static int pitchP(int width, int border, Format format, bool target); 364 static int sliceB(int width, int height, int border, Format format, bool target); 365 static int sliceP(int width, int height, int border, Format format, bool target); 366 static size_t size(int width, int height, int depth, int border, int samples, Format format); 367 368 static bool isStencil(Format format); 369 static bool isDepth(Format format); 370 static bool hasQuadLayout(Format format); 371 static bool isPalette(Format format); 372 373 static bool isFloatFormat(Format format); 374 static bool isUnsignedComponent(Format format, int component); 375 static bool isSRGBreadable(Format format); 376 static bool isSRGBwritable(Format format); 377 static bool isSRGBformat(Format format); 378 static bool isCompressed(Format format); 379 static bool isSignedNonNormalizedInteger(Format format); 380 static bool isUnsignedNonNormalizedInteger(Format format); 381 static bool isNonNormalizedInteger(Format format); 382 static bool isNormalizedInteger(Format format); 383 static int componentCount(Format format); 384 385 static void setTexturePalette(unsigned int *palette); 386 387 private: 388 sw::Resource *resource; 389 390 typedef unsigned char byte; 391 typedef unsigned short word; 392 typedef unsigned int dword; 393 typedef uint64_t qword; 394 395 struct DXT1 396 { 397 word c0; 398 word c1; 399 dword lut; 400 }; 401 402 struct DXT3 403 { 404 qword a; 405 406 word c0; 407 word c1; 408 dword lut; 409 }; 410 411 struct DXT5 412 { 413 union 414 { 415 struct 416 { 417 byte a0; 418 byte a1; 419 }; 420 421 qword alut; // Skip first 16 bit 422 }; 423 424 word c0; 425 word c1; 426 dword clut; 427 }; 428 429 struct ATI2 430 { 431 union 432 { 433 struct 434 { 435 byte y0; 436 byte y1; 437 }; 438 439 qword ylut; // Skip first 16 bit 440 }; 441 442 union 443 { 444 struct 445 { 446 byte x0; 447 byte x1; 448 }; 449 450 qword xlut; // Skip first 16 bit 451 }; 452 }; 453 454 struct ATI1 455 { 456 union 457 { 458 struct 459 { 460 byte r0; 461 byte r1; 462 }; 463 464 qword rlut; // Skip first 16 bit 465 }; 466 }; 467 468 static void decodeR8G8B8(Buffer &destination, Buffer &source); 469 static void decodeX1R5G5B5(Buffer &destination, Buffer &source); 470 static void decodeA1R5G5B5(Buffer &destination, Buffer &source); 471 static void decodeX4R4G4B4(Buffer &destination, Buffer &source); 472 static void decodeA4R4G4B4(Buffer &destination, Buffer &source); 473 static void decodeP8(Buffer &destination, Buffer &source); 474 475 static void decodeDXT1(Buffer &internal, Buffer &external); 476 static void decodeDXT3(Buffer &internal, Buffer &external); 477 static void decodeDXT5(Buffer &internal, Buffer &external); 478 static void decodeATI1(Buffer &internal, Buffer &external); 479 static void decodeATI2(Buffer &internal, Buffer &external); 480 static void decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned); 481 static void decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB); 482 static void decodeASTC(Buffer &internal, Buffer &external, int xSize, int ySize, int zSize, bool isSRGB); 483 484 static void update(Buffer &destination, Buffer &source); 485 static void genericUpdate(Buffer &destination, Buffer &source); 486 static void *allocateBuffer(int width, int height, int depth, int border, int samples, Format format); 487 static void memfill4(void *buffer, int pattern, int bytes); 488 489 bool identicalBuffers() const; 490 Format selectInternalFormat(Format format) const; 491 492 void resolve(); 493 494 Buffer external; 495 Buffer internal; 496 Buffer stencil; 497 498 const bool lockable; 499 const bool renderTarget; 500 501 bool dirtyContents; // Sibling surfaces need updating (mipmaps / cube borders). 502 unsigned int paletteUsed; 503 504 static unsigned int *palette; // FIXME: Not multi-device safe 505 static unsigned int paletteID; 506 507 bool hasParent; 508 bool ownExternal; 509 }; 510 } 511 512 #undef min 513 #undef max 514 515 namespace sw 516 { 517 void *Surface::lock(int x, int y, int z, Lock lock, Accessor client, bool internal) 518 { 519 return internal ? lockInternal(x, y, z, lock, client) : lockExternal(x, y, z, lock, client); 520 } 521 522 void Surface::unlock(bool internal) 523 { 524 return internal ? unlockInternal() : unlockExternal(); 525 } 526 527 int Surface::getWidth() const 528 { 529 return external.width; 530 } 531 532 int Surface::getHeight() const 533 { 534 return external.height; 535 } 536 537 int Surface::getDepth() const 538 { 539 return external.depth; 540 } 541 542 int Surface::getBorder() const 543 { 544 return internal.border; 545 } 546 547 Format Surface::getFormat(bool internal) const 548 { 549 return internal ? getInternalFormat() : getExternalFormat(); 550 } 551 552 int Surface::getPitchB(bool internal) const 553 { 554 return internal ? getInternalPitchB() : getExternalPitchB(); 555 } 556 557 int Surface::getPitchP(bool internal) const 558 { 559 return internal ? getInternalPitchP() : getExternalPitchP(); 560 } 561 562 int Surface::getSliceB(bool internal) const 563 { 564 return internal ? getInternalSliceB() : getExternalSliceB(); 565 } 566 567 int Surface::getSliceP(bool internal) const 568 { 569 return internal ? getInternalSliceP() : getExternalSliceP(); 570 } 571 572 Format Surface::getExternalFormat() const 573 { 574 return external.format; 575 } 576 577 int Surface::getExternalPitchB() const 578 { 579 return external.pitchB; 580 } 581 582 int Surface::getExternalPitchP() const 583 { 584 return external.pitchP; 585 } 586 587 int Surface::getExternalSliceB() const 588 { 589 return external.sliceB; 590 } 591 592 int Surface::getExternalSliceP() const 593 { 594 return external.sliceP; 595 } 596 597 Format Surface::getInternalFormat() const 598 { 599 return internal.format; 600 } 601 602 int Surface::getInternalPitchB() const 603 { 604 return internal.pitchB; 605 } 606 607 int Surface::getInternalPitchP() const 608 { 609 return internal.pitchP; 610 } 611 612 int Surface::getInternalSliceB() const 613 { 614 return internal.sliceB; 615 } 616 617 int Surface::getInternalSliceP() const 618 { 619 return internal.sliceP; 620 } 621 622 Format Surface::getStencilFormat() const 623 { 624 return stencil.format; 625 } 626 627 int Surface::getStencilPitchB() const 628 { 629 return stencil.pitchB; 630 } 631 632 int Surface::getStencilSliceB() const 633 { 634 return stencil.sliceB; 635 } 636 637 int Surface::getSamples() const 638 { 639 return internal.samples; 640 } 641 642 int Surface::getMultiSampleCount() const 643 { 644 return sw::min((int)internal.samples, 4); 645 } 646 647 int Surface::getSuperSampleCount() const 648 { 649 return internal.samples > 4 ? internal.samples / 4 : 1; 650 } 651 652 bool Surface::isUnlocked() const 653 { 654 return external.lock == LOCK_UNLOCKED && 655 internal.lock == LOCK_UNLOCKED && 656 stencil.lock == LOCK_UNLOCKED; 657 } 658 659 bool Surface::isExternalDirty() const 660 { 661 return external.buffer && external.buffer != internal.buffer && external.dirty; 662 } 663 } 664 665 #endif // sw_Surface_hpp 666