• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	{
RectTsw::RectT28 		RectT() {}
RectTsw::RectT29 		RectT(T x0i, T y0i, T x1i, T y1i) : x0(x0i), y0(y0i), x1(x1i), y1(y1i) {}
30 
clipsw::RectT31 		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 
widthsw::RectT39 		T width() const  { return x1 - x0; }
heightsw::RectT40 		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 	{
SliceRectTsw::SliceRectT53 		SliceRectT() : slice(0) {}
SliceRectTsw::SliceRectT54 		SliceRectT(const RectT<T>& rect) : RectT<T>(rect), slice(0) {}
SliceRectTsw::SliceRectT55 		SliceRectT(const RectT<T>& rect, int s) : RectT<T>(rect), slice(s) {}
SliceRectTsw::SliceRectT56 		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 		inline bool isUnlocked() const;   // Only reliable after sync().
325 
326 		inline int getSamples() const;
327 		inline int getMultiSampleCount() const;
328 		inline int getSuperSampleCount() const;
329 
330 		bool isEntire(const Rect& rect) const;
331 		Rect getRect() const;
332 		void clearDepth(float depth, int x0, int y0, int width, int height);
333 		void clearStencil(unsigned char stencil, unsigned char mask, int x0, int y0, int width, int height);
334 		void fill(const Color<float> &color, int x0, int y0, int width, int height);
335 
336 		Color<float> readExternal(int x, int y, int z) const;
337 		Color<float> readExternal(int x, int y) const;
338 		Color<float> sampleExternal(float x, float y, float z) const;
339 		Color<float> sampleExternal(float x, float y) const;
340 		void writeExternal(int x, int y, int z, const Color<float> &color);
341 		void writeExternal(int x, int y, const Color<float> &color);
342 
343 		void copyInternal(const Surface* src, int x, int y, float srcX, float srcY, bool filter);
344 		void copyInternal(const Surface* src, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter);
345 
346 		enum Edge { TOP, BOTTOM, RIGHT, LEFT };
347 		void copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge);
348 		void computeCubeCorner(int x0, int y0, int x1, int y1);
349 
350 		bool hasStencil() const;
351 		bool hasDepth() const;
352 		bool hasPalette() const;
353 		bool isRenderTarget() const;
354 
355 		bool hasDirtyContents() const;
356 		void markContentsClean();
357 		inline bool isExternalDirty() const;
358 		Resource *getResource();
359 
360 		static int bytes(Format format);
361 		static int pitchB(int width, int border, Format format, bool target);
362 		static int pitchP(int width, int border, Format format, bool target);
363 		static int sliceB(int width, int height, int border, Format format, bool target);
364 		static int sliceP(int width, int height, int border, Format format, bool target);
365 		static unsigned int size(int width, int height, int depth, int border, int samples, Format format);   // FIXME: slice * depth
366 
367 		static bool isStencil(Format format);
368 		static bool isDepth(Format format);
369 		static bool hasQuadLayout(Format format);
370 		static bool isPalette(Format format);
371 
372 		static bool isFloatFormat(Format format);
373 		static bool isUnsignedComponent(Format format, int component);
374 		static bool isSRGBreadable(Format format);
375 		static bool isSRGBwritable(Format format);
376 		static bool isSRGBformat(Format format);
377 		static bool isCompressed(Format format);
378 		static bool isSignedNonNormalizedInteger(Format format);
379 		static bool isUnsignedNonNormalizedInteger(Format format);
380 		static bool isNonNormalizedInteger(Format format);
381 		static bool isNormalizedInteger(Format format);
382 		static int componentCount(Format format);
383 
384 		static void setTexturePalette(unsigned int *palette);
385 
386 	private:
387 		sw::Resource *resource;
388 
389 		typedef unsigned char byte;
390 		typedef unsigned short word;
391 		typedef unsigned int dword;
392 		typedef uint64_t qword;
393 
394 		struct DXT1
395 		{
396 			word c0;
397 			word c1;
398 			dword lut;
399 		};
400 
401 		struct DXT3
402 		{
403 			qword a;
404 
405 			word c0;
406 			word c1;
407 			dword lut;
408 		};
409 
410 		struct DXT5
411 		{
412 			union
413 			{
414 				struct
415 				{
416 					byte a0;
417 					byte a1;
418 				};
419 
420 				qword alut;   // Skip first 16 bit
421 			};
422 
423 			word c0;
424 			word c1;
425 			dword clut;
426 		};
427 
428 		struct ATI2
429 		{
430 			union
431 			{
432 				struct
433 				{
434 					byte y0;
435 					byte y1;
436 				};
437 
438 				qword ylut;   // Skip first 16 bit
439 			};
440 
441 			union
442 			{
443 				struct
444 				{
445 					byte x0;
446 					byte x1;
447 				};
448 
449 				qword xlut;   // Skip first 16 bit
450 			};
451 		};
452 
453 		struct ATI1
454 		{
455 			union
456 			{
457 				struct
458 				{
459 					byte r0;
460 					byte r1;
461 				};
462 
463 				qword rlut;   // Skip first 16 bit
464 			};
465 		};
466 
467 		static void decodeR8G8B8(Buffer &destination, Buffer &source);
468 		static void decodeX1R5G5B5(Buffer &destination, Buffer &source);
469 		static void decodeA1R5G5B5(Buffer &destination, Buffer &source);
470 		static void decodeX4R4G4B4(Buffer &destination, Buffer &source);
471 		static void decodeA4R4G4B4(Buffer &destination, Buffer &source);
472 		static void decodeP8(Buffer &destination, Buffer &source);
473 
474 		static void decodeDXT1(Buffer &internal, Buffer &external);
475 		static void decodeDXT3(Buffer &internal, Buffer &external);
476 		static void decodeDXT5(Buffer &internal, Buffer &external);
477 		static void decodeATI1(Buffer &internal, Buffer &external);
478 		static void decodeATI2(Buffer &internal, Buffer &external);
479 		static void decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned);
480 		static void decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB);
481 		static void decodeASTC(Buffer &internal, Buffer &external, int xSize, int ySize, int zSize, bool isSRGB);
482 
483 		static void update(Buffer &destination, Buffer &source);
484 		static void genericUpdate(Buffer &destination, Buffer &source);
485 		static void *allocateBuffer(int width, int height, int depth, int border, int samples, Format format);
486 		static void memfill4(void *buffer, int pattern, int bytes);
487 
488 		bool identicalFormats() const;
489 		Format selectInternalFormat(Format format) const;
490 
491 		void resolve();
492 
493 		Buffer external;
494 		Buffer internal;
495 		Buffer stencil;
496 
497 		const bool lockable;
498 		const bool renderTarget;
499 
500 		bool dirtyContents;   // Sibling surfaces need updating (mipmaps / cube borders).
501 		unsigned int paletteUsed;
502 
503 		static unsigned int *palette;   // FIXME: Not multi-device safe
504 		static unsigned int paletteID;
505 
506 		bool hasParent;
507 		bool ownExternal;
508 	};
509 }
510 
511 #undef min
512 #undef max
513 
514 namespace sw
515 {
lock(int x,int y,int z,Lock lock,Accessor client,bool internal)516 	void *Surface::lock(int x, int y, int z, Lock lock, Accessor client, bool internal)
517 	{
518 		return internal ? lockInternal(x, y, z, lock, client) : lockExternal(x, y, z, lock, client);
519 	}
520 
unlock(bool internal)521 	void Surface::unlock(bool internal)
522 	{
523 		return internal ? unlockInternal() : unlockExternal();
524 	}
525 
getWidth() const526 	int Surface::getWidth() const
527 	{
528 		return external.width;
529 	}
530 
getHeight() const531 	int Surface::getHeight() const
532 	{
533 		return external.height;
534 	}
535 
getDepth() const536 	int Surface::getDepth() const
537 	{
538 		return external.depth;
539 	}
540 
getBorder() const541 	int Surface::getBorder() const
542 	{
543 		return internal.border;
544 	}
545 
getFormat(bool internal) const546 	Format Surface::getFormat(bool internal) const
547 	{
548 		return internal ? getInternalFormat() : getExternalFormat();
549 	}
550 
getPitchB(bool internal) const551 	int Surface::getPitchB(bool internal) const
552 	{
553 		return internal ? getInternalPitchB() : getExternalPitchB();
554 	}
555 
getPitchP(bool internal) const556 	int Surface::getPitchP(bool internal) const
557 	{
558 		return internal ? getInternalPitchP() : getExternalPitchP();
559 	}
560 
getSliceB(bool internal) const561 	int Surface::getSliceB(bool internal) const
562 	{
563 		return internal ? getInternalSliceB() : getExternalSliceB();
564 	}
565 
getSliceP(bool internal) const566 	int Surface::getSliceP(bool internal) const
567 	{
568 		return internal ? getInternalSliceP() : getExternalSliceP();
569 	}
570 
getExternalFormat() const571 	Format Surface::getExternalFormat() const
572 	{
573 		return external.format;
574 	}
575 
getExternalPitchB() const576 	int Surface::getExternalPitchB() const
577 	{
578 		return external.pitchB;
579 	}
580 
getExternalPitchP() const581 	int Surface::getExternalPitchP() const
582 	{
583 		return external.pitchP;
584 	}
585 
getExternalSliceB() const586 	int Surface::getExternalSliceB() const
587 	{
588 		return external.sliceB;
589 	}
590 
getExternalSliceP() const591 	int Surface::getExternalSliceP() const
592 	{
593 		return external.sliceP;
594 	}
595 
getInternalFormat() const596 	Format Surface::getInternalFormat() const
597 	{
598 		return internal.format;
599 	}
600 
getInternalPitchB() const601 	int Surface::getInternalPitchB() const
602 	{
603 		return internal.pitchB;
604 	}
605 
getInternalPitchP() const606 	int Surface::getInternalPitchP() const
607 	{
608 		return internal.pitchP;
609 	}
610 
getInternalSliceB() const611 	int Surface::getInternalSliceB() const
612 	{
613 		return internal.sliceB;
614 	}
615 
getInternalSliceP() const616 	int Surface::getInternalSliceP() const
617 	{
618 		return internal.sliceP;
619 	}
620 
getStencilFormat() const621 	Format Surface::getStencilFormat() const
622 	{
623 		return stencil.format;
624 	}
625 
getStencilPitchB() const626 	int Surface::getStencilPitchB() const
627 	{
628 		return stencil.pitchB;
629 	}
630 
getStencilSliceB() const631 	int Surface::getStencilSliceB() const
632 	{
633 		return stencil.sliceB;
634 	}
635 
getSamples() const636 	int Surface::getSamples() const
637 	{
638 		return internal.samples;
639 	}
640 
getMultiSampleCount() const641 	int Surface::getMultiSampleCount() const
642 	{
643 		return sw::min((int)internal.samples, 4);
644 	}
645 
getSuperSampleCount() const646 	int Surface::getSuperSampleCount() const
647 	{
648 		return internal.samples > 4 ? internal.samples / 4 : 1;
649 	}
650 
isUnlocked() const651 	bool Surface::isUnlocked() const
652 	{
653 		return external.lock == LOCK_UNLOCKED &&
654 		       internal.lock == LOCK_UNLOCKED &&
655 		       stencil.lock == LOCK_UNLOCKED;
656 	}
657 
isExternalDirty() const658 	bool Surface::isExternalDirty() const
659 	{
660 		return external.buffer && external.buffer != internal.buffer && external.dirty;
661 	}
662 }
663 
664 #endif   // sw_Surface_hpp
665