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
22namespace 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
515namespace 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