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 { RectTsw::RectT28 RectT() {} RectTsw::RectT29 RectT(T x0i, T y0i, T x1i, T y1i) : x0(x0i), y0(y0i), x1(x1i), y1(y1i) {} 30 clipsw::RectT31 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 widthsw::RectT39 T width() const { return x1 - x0; } heightsw::RectT40 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 { SliceRectTsw::SliceRectT53 SliceRectT() : slice(0) {} SliceRectTsw::SliceRectT54 SliceRectT(const RectT<T>& rect) : RectT<T>(rect), slice(0) {} SliceRectTsw::SliceRectT55 SliceRectT(const RectT<T>& rect, int s) : RectT<T>(rect), slice(s) {} SliceRectTsw::SliceRectT56 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 ENUM_UNDERLYING_TYPE_UNSIGNED_INT 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 // Floating-point formats 141 FORMAT_A16F, 142 FORMAT_R16F, 143 FORMAT_G16R16F, 144 FORMAT_B16G16R16F, 145 FORMAT_X16B16G16R16F, 146 FORMAT_A16B16G16R16F, 147 FORMAT_X16B16G16R16F_UNSIGNED, 148 FORMAT_A32F, 149 FORMAT_R32F, 150 FORMAT_G32R32F, 151 FORMAT_B32G32R32F, 152 FORMAT_X32B32G32R32F, 153 FORMAT_A32B32G32R32F, 154 FORMAT_X32B32G32R32F_UNSIGNED, 155 // Bump map formats 156 FORMAT_V8U8, 157 FORMAT_L6V5U5, 158 FORMAT_Q8W8V8U8, 159 FORMAT_X8L8V8U8, 160 FORMAT_A2W10V10U10, 161 FORMAT_V16U16, 162 FORMAT_A16W16V16U16, 163 FORMAT_Q16W16V16U16, 164 // Luminance formats 165 FORMAT_L8, 166 FORMAT_A4L4, 167 FORMAT_L16, 168 FORMAT_A8L8, 169 FORMAT_L16F, 170 FORMAT_A16L16F, 171 FORMAT_L32F, 172 FORMAT_A32L32F, 173 // Depth/stencil formats 174 FORMAT_D16, 175 FORMAT_D32, 176 FORMAT_D24X8, 177 FORMAT_D24S8, 178 FORMAT_D24FS8, 179 FORMAT_D32F, // Quad layout 180 FORMAT_D32FS8, // Quad layout 181 FORMAT_D32F_COMPLEMENTARY, // Quad layout, 1 - z 182 FORMAT_D32FS8_COMPLEMENTARY, // Quad layout, 1 - z 183 FORMAT_D32F_LOCKABLE, // Linear layout 184 FORMAT_D32FS8_TEXTURE, // Linear layout, no PCF 185 FORMAT_D32F_SHADOW, // Linear layout, PCF 186 FORMAT_D32FS8_SHADOW, // Linear layout, PCF 187 FORMAT_DF24S8, 188 FORMAT_DF16S8, 189 FORMAT_INTZ, 190 FORMAT_S8, 191 // Quad layout framebuffer 192 FORMAT_X8G8R8B8Q, 193 FORMAT_A8G8R8B8Q, 194 // YUV formats 195 FORMAT_YV12_BT601, 196 FORMAT_YV12_BT709, 197 FORMAT_YV12_JFIF, // Full-swing BT.601 198 199 FORMAT_LAST = FORMAT_YV12_JFIF 200 }; 201 202 enum Lock 203 { 204 LOCK_UNLOCKED, 205 LOCK_READONLY, 206 LOCK_WRITEONLY, 207 LOCK_READWRITE, 208 LOCK_DISCARD, 209 LOCK_UPDATE // Write access which doesn't dirty the buffer, because it's being updated with the sibling's data. 210 }; 211 212 class [[clang::lto_visibility_public]] Surface 213 { 214 private: 215 struct Buffer 216 { 217 friend Surface; 218 219 private: 220 void write(int x, int y, int z, const Color<float> &color); 221 void write(int x, int y, const Color<float> &color); 222 void write(void *element, const Color<float> &color); 223 Color<float> read(int x, int y, int z) const; 224 Color<float> read(int x, int y) const; 225 Color<float> read(void *element) const; 226 Color<float> sample(float x, float y, float z) const; 227 Color<float> sample(float x, float y, int layer) const; 228 229 void *lockRect(int x, int y, int z, Lock lock); 230 void unlockRect(); 231 232 void *buffer; 233 int width; 234 int height; 235 int depth; 236 short border; 237 short samples; 238 239 int bytes; 240 int pitchB; 241 int pitchP; 242 int sliceB; 243 int sliceP; 244 245 Format format; 246 AtomicInt lock; 247 248 bool dirty; // Sibling internal/external buffer doesn't match. 249 }; 250 251 protected: 252 Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice); 253 Surface(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0); 254 255 public: 256 static Surface *create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice); 257 static Surface *create(Resource *texture, int width, int height, int depth, int border, int samples, Format format, bool lockable, bool renderTarget, int pitchP = 0); 258 259 virtual ~Surface() = 0; 260 261 inline void *lock(int x, int y, int z, Lock lock, Accessor client, bool internal = false); 262 inline void unlock(bool internal = false); 263 inline int getWidth() const; 264 inline int getHeight() const; 265 inline int getDepth() const; 266 inline int getBorder() const; 267 inline Format getFormat(bool internal = false) const; 268 inline int getPitchB(bool internal = false) const; 269 inline int getPitchP(bool internal = false) const; 270 inline int getSliceB(bool internal = false) const; 271 inline int getSliceP(bool internal = false) const; 272 273 void *lockExternal(int x, int y, int z, Lock lock, Accessor client); 274 void unlockExternal(); 275 inline Format getExternalFormat() const; 276 inline int getExternalPitchB() const; 277 inline int getExternalPitchP() const; 278 inline int getExternalSliceB() const; 279 inline int getExternalSliceP() const; 280 281 virtual void *lockInternal(int x, int y, int z, Lock lock, Accessor client) = 0; 282 virtual void unlockInternal() = 0; 283 inline Format getInternalFormat() const; 284 inline int getInternalPitchB() const; 285 inline int getInternalPitchP() const; 286 inline int getInternalSliceB() const; 287 inline int getInternalSliceP() const; 288 289 void *lockStencil(int x, int y, int front, Accessor client); 290 void unlockStencil(); 291 inline Format getStencilFormat() const; 292 inline int getStencilPitchB() const; 293 inline int getStencilSliceB() const; 294 295 void sync(); // Wait for lock(s) to be released. requiresSync() const296 virtual bool requiresSync() const { return false; } 297 inline bool isUnlocked() const; // Only reliable after sync(). 298 299 inline int getSamples() const; 300 inline int getMultiSampleCount() const; 301 inline int getSuperSampleCount() const; 302 303 bool isEntire(const Rect& rect) const; 304 Rect getRect() const; 305 void clearDepth(float depth, int x0, int y0, int width, int height); 306 void clearStencil(unsigned char stencil, unsigned char mask, int x0, int y0, int width, int height); 307 void fill(const Color<float> &color, int x0, int y0, int width, int height); 308 309 Color<float> readExternal(int x, int y, int z) const; 310 Color<float> readExternal(int x, int y) const; 311 Color<float> sampleExternal(float x, float y, float z) const; 312 Color<float> sampleExternal(float x, float y) const; 313 void writeExternal(int x, int y, int z, const Color<float> &color); 314 void writeExternal(int x, int y, const Color<float> &color); 315 316 void copyInternal(const Surface* src, int x, int y, float srcX, float srcY, bool filter); 317 void copyInternal(const Surface* src, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter); 318 319 enum Edge { TOP, BOTTOM, RIGHT, LEFT }; 320 void copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge); 321 void computeCubeCorner(int x0, int y0, int x1, int y1); 322 323 bool hasStencil() const; 324 bool hasDepth() const; 325 bool hasPalette() const; 326 bool isRenderTarget() const; 327 328 bool hasDirtyContents() const; 329 void markContentsClean(); 330 inline bool isExternalDirty() const; 331 Resource *getResource(); 332 333 static int bytes(Format format); 334 static int pitchB(int width, int border, Format format, bool target); 335 static int pitchP(int width, int border, Format format, bool target); 336 static int sliceB(int width, int height, int border, Format format, bool target); 337 static int sliceP(int width, int height, int border, Format format, bool target); 338 static size_t size(int width, int height, int depth, int border, int samples, Format format); 339 340 static bool isStencil(Format format); 341 static bool isDepth(Format format); 342 static bool hasQuadLayout(Format format); 343 static bool isPalette(Format format); 344 345 static bool isFloatFormat(Format format); 346 static bool isUnsignedComponent(Format format, int component); 347 static bool isSRGBreadable(Format format); 348 static bool isSRGBwritable(Format format); 349 static bool isSRGBformat(Format format); 350 static bool isCompressed(Format format); 351 static bool isSignedNonNormalizedInteger(Format format); 352 static bool isUnsignedNonNormalizedInteger(Format format); 353 static bool isNonNormalizedInteger(Format format); 354 static bool isNormalizedInteger(Format format); 355 static int componentCount(Format format); 356 357 static void setTexturePalette(unsigned int *palette); 358 359 private: 360 sw::Resource *resource; 361 362 typedef unsigned char byte; 363 typedef unsigned short word; 364 typedef unsigned int dword; 365 typedef uint64_t qword; 366 367 struct DXT1 368 { 369 word c0; 370 word c1; 371 dword lut; 372 }; 373 374 struct DXT3 375 { 376 qword a; 377 378 word c0; 379 word c1; 380 dword lut; 381 }; 382 383 struct DXT5 384 { 385 union 386 { 387 struct 388 { 389 byte a0; 390 byte a1; 391 }; 392 393 qword alut; // Skip first 16 bit 394 }; 395 396 word c0; 397 word c1; 398 dword clut; 399 }; 400 401 struct ATI2 402 { 403 union 404 { 405 struct 406 { 407 byte y0; 408 byte y1; 409 }; 410 411 qword ylut; // Skip first 16 bit 412 }; 413 414 union 415 { 416 struct 417 { 418 byte x0; 419 byte x1; 420 }; 421 422 qword xlut; // Skip first 16 bit 423 }; 424 }; 425 426 struct ATI1 427 { 428 union 429 { 430 struct 431 { 432 byte r0; 433 byte r1; 434 }; 435 436 qword rlut; // Skip first 16 bit 437 }; 438 }; 439 440 static void decodeR8G8B8(Buffer &destination, Buffer &source); 441 static void decodeX1R5G5B5(Buffer &destination, Buffer &source); 442 static void decodeA1R5G5B5(Buffer &destination, Buffer &source); 443 static void decodeX4R4G4B4(Buffer &destination, Buffer &source); 444 static void decodeA4R4G4B4(Buffer &destination, Buffer &source); 445 static void decodeP8(Buffer &destination, Buffer &source); 446 447 static void decodeDXT1(Buffer &internal, Buffer &external); 448 static void decodeDXT3(Buffer &internal, Buffer &external); 449 static void decodeDXT5(Buffer &internal, Buffer &external); 450 static void decodeATI1(Buffer &internal, Buffer &external); 451 static void decodeATI2(Buffer &internal, Buffer &external); 452 static void decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned); 453 static void decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB); 454 455 static void update(Buffer &destination, Buffer &source); 456 static void genericUpdate(Buffer &destination, Buffer &source); 457 static void *allocateBuffer(int width, int height, int depth, int border, int samples, Format format); 458 static void memfill4(void *buffer, int pattern, int bytes); 459 460 bool identicalBuffers() const; 461 Format selectInternalFormat(Format format) const; 462 463 void resolve(); 464 465 Buffer external; 466 Buffer internal; 467 Buffer stencil; 468 469 const bool lockable; 470 const bool renderTarget; 471 472 bool dirtyContents; // Sibling surfaces need updating (mipmaps / cube borders). 473 unsigned int paletteUsed; 474 475 static unsigned int *palette; // FIXME: Not multi-device safe 476 static unsigned int paletteID; 477 478 bool hasParent; 479 bool ownExternal; 480 }; 481 } 482 483 #undef min 484 #undef max 485 486 namespace sw 487 { lock(int x,int y,int z,Lock lock,Accessor client,bool internal)488 void *Surface::lock(int x, int y, int z, Lock lock, Accessor client, bool internal) 489 { 490 return internal ? lockInternal(x, y, z, lock, client) : lockExternal(x, y, z, lock, client); 491 } 492 unlock(bool internal)493 void Surface::unlock(bool internal) 494 { 495 return internal ? unlockInternal() : unlockExternal(); 496 } 497 getWidth() const498 int Surface::getWidth() const 499 { 500 return external.width; 501 } 502 getHeight() const503 int Surface::getHeight() const 504 { 505 return external.height; 506 } 507 getDepth() const508 int Surface::getDepth() const 509 { 510 return external.depth; 511 } 512 getBorder() const513 int Surface::getBorder() const 514 { 515 return internal.border; 516 } 517 getFormat(bool internal) const518 Format Surface::getFormat(bool internal) const 519 { 520 return internal ? getInternalFormat() : getExternalFormat(); 521 } 522 getPitchB(bool internal) const523 int Surface::getPitchB(bool internal) const 524 { 525 return internal ? getInternalPitchB() : getExternalPitchB(); 526 } 527 getPitchP(bool internal) const528 int Surface::getPitchP(bool internal) const 529 { 530 return internal ? getInternalPitchP() : getExternalPitchP(); 531 } 532 getSliceB(bool internal) const533 int Surface::getSliceB(bool internal) const 534 { 535 return internal ? getInternalSliceB() : getExternalSliceB(); 536 } 537 getSliceP(bool internal) const538 int Surface::getSliceP(bool internal) const 539 { 540 return internal ? getInternalSliceP() : getExternalSliceP(); 541 } 542 getExternalFormat() const543 Format Surface::getExternalFormat() const 544 { 545 return external.format; 546 } 547 getExternalPitchB() const548 int Surface::getExternalPitchB() const 549 { 550 return external.pitchB; 551 } 552 getExternalPitchP() const553 int Surface::getExternalPitchP() const 554 { 555 return external.pitchP; 556 } 557 getExternalSliceB() const558 int Surface::getExternalSliceB() const 559 { 560 return external.sliceB; 561 } 562 getExternalSliceP() const563 int Surface::getExternalSliceP() const 564 { 565 return external.sliceP; 566 } 567 getInternalFormat() const568 Format Surface::getInternalFormat() const 569 { 570 return internal.format; 571 } 572 getInternalPitchB() const573 int Surface::getInternalPitchB() const 574 { 575 return internal.pitchB; 576 } 577 getInternalPitchP() const578 int Surface::getInternalPitchP() const 579 { 580 return internal.pitchP; 581 } 582 getInternalSliceB() const583 int Surface::getInternalSliceB() const 584 { 585 return internal.sliceB; 586 } 587 getInternalSliceP() const588 int Surface::getInternalSliceP() const 589 { 590 return internal.sliceP; 591 } 592 getStencilFormat() const593 Format Surface::getStencilFormat() const 594 { 595 return stencil.format; 596 } 597 getStencilPitchB() const598 int Surface::getStencilPitchB() const 599 { 600 return stencil.pitchB; 601 } 602 getStencilSliceB() const603 int Surface::getStencilSliceB() const 604 { 605 return stencil.sliceB; 606 } 607 getSamples() const608 int Surface::getSamples() const 609 { 610 return internal.samples; 611 } 612 getMultiSampleCount() const613 int Surface::getMultiSampleCount() const 614 { 615 return sw::min((int)internal.samples, 4); 616 } 617 getSuperSampleCount() const618 int Surface::getSuperSampleCount() const 619 { 620 return internal.samples > 4 ? internal.samples / 4 : 1; 621 } 622 isUnlocked() const623 bool Surface::isUnlocked() const 624 { 625 return external.lock == LOCK_UNLOCKED && 626 internal.lock == LOCK_UNLOCKED && 627 stencil.lock == LOCK_UNLOCKED; 628 } 629 isExternalDirty() const630 bool Surface::isExternalDirty() const 631 { 632 return external.buffer && external.buffer != internal.buffer && external.dirty; 633 } 634 } 635 636 #endif // sw_Surface_hpp 637