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 "Device/Config.hpp" 20 #include "System/Resource.hpp" 21 #include <vulkan/vulkan.h> 22 23 namespace sw 24 { 25 class Resource; 26 27 template <typename T> struct RectT 28 { 29 RectT() {} 30 RectT(T x0i, T y0i, T x1i, T y1i) : x0(x0i), y0(y0i), x1(x1i), y1(y1i) {} 31 32 void clip(T minX, T minY, T maxX, T maxY) 33 { 34 x0 = clamp(x0, minX, maxX); 35 y0 = clamp(y0, minY, maxY); 36 x1 = clamp(x1, minX, maxX); 37 y1 = clamp(y1, minY, maxY); 38 } 39 40 T width() const { return x1 - x0; } 41 T height() const { return y1 - y0; } 42 43 T x0; // Inclusive 44 T y0; // Inclusive 45 T x1; // Exclusive 46 T y1; // Exclusive 47 }; 48 49 typedef RectT<int> Rect; 50 typedef RectT<float> RectF; 51 52 template<typename T> struct SliceRectT : public RectT<T> 53 { 54 SliceRectT() : slice(0) {} 55 SliceRectT(const RectT<T>& rect) : RectT<T>(rect), slice(0) {} 56 SliceRectT(const RectT<T>& rect, int s) : RectT<T>(rect), slice(s) {} 57 SliceRectT(T x0, T y0, T x1, T y1, int s) : RectT<T>(x0, y0, x1, y1), slice(s) {} 58 int slice; 59 }; 60 61 typedef SliceRectT<int> SliceRect; 62 typedef SliceRectT<float> SliceRectF; 63 64 enum Lock 65 { 66 LOCK_UNLOCKED, 67 LOCK_READONLY, 68 LOCK_WRITEONLY, 69 LOCK_READWRITE, 70 LOCK_DISCARD, 71 LOCK_UPDATE // Write access which doesn't dirty the buffer, because it's being updated with the sibling's data. 72 }; 73 74 class Surface 75 { 76 private: 77 struct Buffer 78 { 79 friend Surface; 80 81 private: 82 void write(int x, int y, int z, const Color<float> &color); 83 void write(int x, int y, const Color<float> &color); 84 void write(void *element, const Color<float> &color); 85 Color<float> read(int x, int y, int z) const; 86 Color<float> read(int x, int y) const; 87 Color<float> read(void *element) const; 88 Color<float> sample(float x, float y, float z) const; 89 Color<float> sample(float x, float y, int layer) const; 90 91 void *lockRect(int x, int y, int z, Lock lock); 92 void unlockRect(); 93 94 void *buffer; 95 int width; 96 int height; 97 int depth; 98 short border; 99 short samples; 100 101 int bytes; 102 int pitchB; 103 int pitchP; 104 int sliceB; 105 int sliceP; 106 107 VkFormat format; 108 AtomicInt lock; 109 110 bool dirty; // Sibling internal/external buffer doesn't match. 111 }; 112 113 protected: 114 Surface(int width, int height, int depth, VkFormat format, void *pixels, int pitch, int slice); 115 Surface(Resource *texture, int width, int height, int depth, int border, int samples, VkFormat format, bool lockable, bool renderTarget, int pitchP = 0); 116 117 public: 118 static Surface *create(int width, int height, int depth, VkFormat format, void *pixels, int pitch, int slice); 119 static Surface *create(Resource *texture, int width, int height, int depth, int border, int samples, VkFormat format, bool lockable, bool renderTarget, int pitchP = 0); 120 121 virtual ~Surface() = 0; 122 123 inline void *lock(int x, int y, int z, Lock lock, Accessor client, bool internal = false); 124 inline void unlock(bool internal = false); 125 inline int getWidth() const; 126 inline int getHeight() const; 127 inline int getDepth() const; 128 inline int getBorder() const; 129 inline VkFormat getFormat(bool internal = false) const; 130 inline int getPitchB(bool internal = false) const; 131 inline int getPitchP(bool internal = false) const; 132 inline int getSliceB(bool internal = false) const; 133 inline int getSliceP(bool internal = false) const; 134 135 void *lockExternal(int x, int y, int z, Lock lock, Accessor client); 136 void unlockExternal(); 137 inline VkFormat getExternalFormat() const; 138 inline int getExternalPitchB() const; 139 inline int getExternalPitchP() const; 140 inline int getExternalSliceB() const; 141 inline int getExternalSliceP() const; 142 143 virtual void *lockInternal(int x, int y, int z, Lock lock, Accessor client) = 0; 144 virtual void unlockInternal() = 0; 145 inline VkFormat getInternalFormat() const; 146 inline int getInternalPitchB() const; 147 inline int getInternalPitchP() const; 148 inline int getInternalSliceB() const; 149 inline int getInternalSliceP() const; 150 151 void *lockStencil(int x, int y, int front, Accessor client); 152 void unlockStencil(); 153 inline VkFormat getStencilFormat() const; 154 inline int getStencilPitchB() const; 155 inline int getStencilSliceB() const; 156 157 void sync(); // Wait for lock(s) to be released. 158 virtual bool requiresSync() const { return false; } 159 inline bool isUnlocked() const; // Only reliable after sync(). 160 161 inline int getSamples() const; 162 inline int getMultiSampleCount() const; 163 inline int getSuperSampleCount() const; 164 165 bool isEntire(const Rect& rect) const; 166 Rect getRect() const; 167 void clearDepth(float depth, int x0, int y0, int width, int height); 168 void clearStencil(unsigned char stencil, unsigned char mask, int x0, int y0, int width, int height); 169 void fill(const Color<float> &color, int x0, int y0, int width, int height); 170 171 Color<float> readExternal(int x, int y, int z) const; 172 Color<float> readExternal(int x, int y) const; 173 Color<float> sampleExternal(float x, float y, float z) const; 174 Color<float> sampleExternal(float x, float y) const; 175 void writeExternal(int x, int y, int z, const Color<float> &color); 176 void writeExternal(int x, int y, const Color<float> &color); 177 178 void copyInternal(const Surface* src, int x, int y, float srcX, float srcY, bool filter); 179 void copyInternal(const Surface* src, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter); 180 181 enum Edge { TOP, BOTTOM, RIGHT, LEFT }; 182 void copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge); 183 void computeCubeCorner(int x0, int y0, int x1, int y1); 184 185 bool hasStencil() const; 186 bool hasDepth() const; 187 bool isRenderTarget() const; 188 189 bool hasDirtyContents() const; 190 void markContentsClean(); 191 inline bool isExternalDirty() const; 192 Resource *getResource(); 193 194 static int bytes(VkFormat format); 195 static int pitchB(int width, int border, VkFormat format, bool target); 196 static int pitchP(int width, int border, VkFormat format, bool target); 197 static int sliceB(int width, int height, int border, VkFormat format, bool target); 198 static int sliceP(int width, int height, int border, VkFormat format, bool target); 199 static size_t size(int width, int height, int depth, int border, int samples, VkFormat format); 200 201 static bool isStencil(VkFormat format); 202 static bool isDepth(VkFormat format); 203 static bool hasQuadLayout(VkFormat format); 204 205 static bool isFloatFormat(VkFormat format); 206 static bool isUnsignedComponent(VkFormat format, int component); 207 static bool isSRGBreadable(VkFormat format); 208 static bool isSRGBwritable(VkFormat format); 209 static bool isSRGBformat(VkFormat format); 210 static bool isCompressed(VkFormat format); 211 static bool isSignedNonNormalizedInteger(VkFormat format); 212 static bool isUnsignedNonNormalizedInteger(VkFormat format); 213 static bool isNonNormalizedInteger(VkFormat format); 214 static bool isNormalizedInteger(VkFormat format); 215 static int componentCount(VkFormat format); 216 217 private: 218 sw::Resource *resource; 219 220 typedef unsigned char byte; 221 typedef unsigned short word; 222 typedef unsigned int dword; 223 typedef uint64_t qword; 224 225 struct DXT1 226 { 227 word c0; 228 word c1; 229 dword lut; 230 }; 231 232 struct DXT3 233 { 234 qword a; 235 236 word c0; 237 word c1; 238 dword lut; 239 }; 240 241 struct DXT5 242 { 243 union 244 { 245 struct 246 { 247 byte a0; 248 byte a1; 249 }; 250 251 qword alut; // Skip first 16 bit 252 }; 253 254 word c0; 255 word c1; 256 dword clut; 257 }; 258 259 struct ATI2 260 { 261 union 262 { 263 struct 264 { 265 byte y0; 266 byte y1; 267 }; 268 269 qword ylut; // Skip first 16 bit 270 }; 271 272 union 273 { 274 struct 275 { 276 byte x0; 277 byte x1; 278 }; 279 280 qword xlut; // Skip first 16 bit 281 }; 282 }; 283 284 struct ATI1 285 { 286 union 287 { 288 struct 289 { 290 byte r0; 291 byte r1; 292 }; 293 294 qword rlut; // Skip first 16 bit 295 }; 296 }; 297 298 static void decodeDXT1(Buffer &internal, Buffer &external); 299 static void decodeDXT3(Buffer &internal, Buffer &external); 300 static void decodeDXT5(Buffer &internal, Buffer &external); 301 static void decodeATI1(Buffer &internal, Buffer &external); 302 static void decodeATI2(Buffer &internal, Buffer &external); 303 static void decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned); 304 static void decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB); 305 static void decodeASTC(Buffer &internal, Buffer &external, int xSize, int ySize, int zSize, bool isSRGB); 306 307 static void update(Buffer &destination, Buffer &source); 308 static void genericUpdate(Buffer &destination, Buffer &source); 309 static void *allocateBuffer(int width, int height, int depth, int border, int samples, VkFormat format); 310 static void memfill4(void *buffer, int pattern, int bytes); 311 312 bool identicalBuffers() const; 313 VkFormat selectInternalFormat(VkFormat format) const; 314 315 void resolve(); 316 317 Buffer external; 318 Buffer internal; 319 Buffer stencil; 320 321 const bool lockable; 322 const bool renderTarget; 323 324 bool dirtyContents; // Sibling surfaces need updating (mipmaps / cube borders). 325 326 bool hasParent; 327 bool ownExternal; 328 }; 329 } 330 331 #undef min 332 #undef max 333 334 namespace sw 335 { 336 void *Surface::lock(int x, int y, int z, Lock lock, Accessor client, bool internal) 337 { 338 return internal ? lockInternal(x, y, z, lock, client) : lockExternal(x, y, z, lock, client); 339 } 340 341 void Surface::unlock(bool internal) 342 { 343 return internal ? unlockInternal() : unlockExternal(); 344 } 345 346 int Surface::getWidth() const 347 { 348 return external.width; 349 } 350 351 int Surface::getHeight() const 352 { 353 return external.height; 354 } 355 356 int Surface::getDepth() const 357 { 358 return external.depth; 359 } 360 361 int Surface::getBorder() const 362 { 363 return internal.border; 364 } 365 366 VkFormat Surface::getFormat(bool internal) const 367 { 368 return internal ? getInternalFormat() : getExternalFormat(); 369 } 370 371 int Surface::getPitchB(bool internal) const 372 { 373 return internal ? getInternalPitchB() : getExternalPitchB(); 374 } 375 376 int Surface::getPitchP(bool internal) const 377 { 378 return internal ? getInternalPitchP() : getExternalPitchP(); 379 } 380 381 int Surface::getSliceB(bool internal) const 382 { 383 return internal ? getInternalSliceB() : getExternalSliceB(); 384 } 385 386 int Surface::getSliceP(bool internal) const 387 { 388 return internal ? getInternalSliceP() : getExternalSliceP(); 389 } 390 391 VkFormat Surface::getExternalFormat() const 392 { 393 return external.format; 394 } 395 396 int Surface::getExternalPitchB() const 397 { 398 return external.pitchB; 399 } 400 401 int Surface::getExternalPitchP() const 402 { 403 return external.pitchP; 404 } 405 406 int Surface::getExternalSliceB() const 407 { 408 return external.sliceB; 409 } 410 411 int Surface::getExternalSliceP() const 412 { 413 return external.sliceP; 414 } 415 416 VkFormat Surface::getInternalFormat() const 417 { 418 return internal.format; 419 } 420 421 int Surface::getInternalPitchB() const 422 { 423 return internal.pitchB; 424 } 425 426 int Surface::getInternalPitchP() const 427 { 428 return internal.pitchP; 429 } 430 431 int Surface::getInternalSliceB() const 432 { 433 return internal.sliceB; 434 } 435 436 int Surface::getInternalSliceP() const 437 { 438 return internal.sliceP; 439 } 440 441 VkFormat Surface::getStencilFormat() const 442 { 443 return stencil.format; 444 } 445 446 int Surface::getStencilPitchB() const 447 { 448 return stencil.pitchB; 449 } 450 451 int Surface::getStencilSliceB() const 452 { 453 return stencil.sliceB; 454 } 455 456 int Surface::getSamples() const 457 { 458 return internal.samples; 459 } 460 461 int Surface::getMultiSampleCount() const 462 { 463 return sw::min((int)internal.samples, 4); 464 } 465 466 int Surface::getSuperSampleCount() const 467 { 468 return internal.samples > 4 ? internal.samples / 4 : 1; 469 } 470 471 bool Surface::isUnlocked() const 472 { 473 return external.lock == LOCK_UNLOCKED && 474 internal.lock == LOCK_UNLOCKED && 475 stencil.lock == LOCK_UNLOCKED; 476 } 477 478 bool Surface::isExternalDirty() const 479 { 480 return external.buffer && external.buffer != internal.buffer && external.dirty; 481 } 482 } 483 484 #endif // sw_Surface_hpp 485