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 	{
RectTsw::RectT29 		RectT() {}
RectTsw::RectT30 		RectT(T x0i, T y0i, T x1i, T y1i) : x0(x0i), y0(y0i), x1(x1i), y1(y1i) {}
31 
clipsw::RectT32 		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 
widthsw::RectT40 		T width() const  { return x1 - x0; }
heightsw::RectT41 		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 	{
SliceRectTsw::SliceRectT54 		SliceRectT() : slice(0) {}
SliceRectTsw::SliceRectT55 		SliceRectT(const RectT<T>& rect) : RectT<T>(rect), slice(0) {}
SliceRectTsw::SliceRectT56 		SliceRectT(const RectT<T>& rect, int s) : RectT<T>(rect), slice(s) {}
SliceRectTsw::SliceRectT57 		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.
requiresSync() const158 		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 {
lock(int x,int y,int z,Lock lock,Accessor client,bool internal)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 
unlock(bool internal)341 	void Surface::unlock(bool internal)
342 	{
343 		return internal ? unlockInternal() : unlockExternal();
344 	}
345 
getWidth() const346 	int Surface::getWidth() const
347 	{
348 		return external.width;
349 	}
350 
getHeight() const351 	int Surface::getHeight() const
352 	{
353 		return external.height;
354 	}
355 
getDepth() const356 	int Surface::getDepth() const
357 	{
358 		return external.depth;
359 	}
360 
getBorder() const361 	int Surface::getBorder() const
362 	{
363 		return internal.border;
364 	}
365 
getFormat(bool internal) const366 	VkFormat Surface::getFormat(bool internal) const
367 	{
368 		return internal ? getInternalFormat() : getExternalFormat();
369 	}
370 
getPitchB(bool internal) const371 	int Surface::getPitchB(bool internal) const
372 	{
373 		return internal ? getInternalPitchB() : getExternalPitchB();
374 	}
375 
getPitchP(bool internal) const376 	int Surface::getPitchP(bool internal) const
377 	{
378 		return internal ? getInternalPitchP() : getExternalPitchP();
379 	}
380 
getSliceB(bool internal) const381 	int Surface::getSliceB(bool internal) const
382 	{
383 		return internal ? getInternalSliceB() : getExternalSliceB();
384 	}
385 
getSliceP(bool internal) const386 	int Surface::getSliceP(bool internal) const
387 	{
388 		return internal ? getInternalSliceP() : getExternalSliceP();
389 	}
390 
getExternalFormat() const391 	VkFormat Surface::getExternalFormat() const
392 	{
393 		return external.format;
394 	}
395 
getExternalPitchB() const396 	int Surface::getExternalPitchB() const
397 	{
398 		return external.pitchB;
399 	}
400 
getExternalPitchP() const401 	int Surface::getExternalPitchP() const
402 	{
403 		return external.pitchP;
404 	}
405 
getExternalSliceB() const406 	int Surface::getExternalSliceB() const
407 	{
408 		return external.sliceB;
409 	}
410 
getExternalSliceP() const411 	int Surface::getExternalSliceP() const
412 	{
413 		return external.sliceP;
414 	}
415 
getInternalFormat() const416 	VkFormat Surface::getInternalFormat() const
417 	{
418 		return internal.format;
419 	}
420 
getInternalPitchB() const421 	int Surface::getInternalPitchB() const
422 	{
423 		return internal.pitchB;
424 	}
425 
getInternalPitchP() const426 	int Surface::getInternalPitchP() const
427 	{
428 		return internal.pitchP;
429 	}
430 
getInternalSliceB() const431 	int Surface::getInternalSliceB() const
432 	{
433 		return internal.sliceB;
434 	}
435 
getInternalSliceP() const436 	int Surface::getInternalSliceP() const
437 	{
438 		return internal.sliceP;
439 	}
440 
getStencilFormat() const441 	VkFormat Surface::getStencilFormat() const
442 	{
443 		return stencil.format;
444 	}
445 
getStencilPitchB() const446 	int Surface::getStencilPitchB() const
447 	{
448 		return stencil.pitchB;
449 	}
450 
getStencilSliceB() const451 	int Surface::getStencilSliceB() const
452 	{
453 		return stencil.sliceB;
454 	}
455 
getSamples() const456 	int Surface::getSamples() const
457 	{
458 		return internal.samples;
459 	}
460 
getMultiSampleCount() const461 	int Surface::getMultiSampleCount() const
462 	{
463 		return sw::min((int)internal.samples, 4);
464 	}
465 
getSuperSampleCount() const466 	int Surface::getSuperSampleCount() const
467 	{
468 		return internal.samples > 4 ? internal.samples / 4 : 1;
469 	}
470 
isUnlocked() const471 	bool Surface::isUnlocked() const
472 	{
473 		return external.lock == LOCK_UNLOCKED &&
474 		       internal.lock == LOCK_UNLOCKED &&
475 		       stencil.lock == LOCK_UNLOCKED;
476 	}
477 
isExternalDirty() const478 	bool Surface::isExternalDirty() const
479 	{
480 		return external.buffer && external.buffer != internal.buffer && external.dirty;
481 	}
482 }
483 
484 #endif   // sw_Surface_hpp
485