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