Home | History | Annotate | Download | only in Renderer
      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 
     22 namespace 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 
    515 namespace 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