Home | History | Annotate | Download | only in Device
      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