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.
requiresSync() const324 		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 {
lock(int x,int y,int z,Lock lock,Accessor client,bool internal)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 
unlock(bool internal)522 	void Surface::unlock(bool internal)
523 	{
524 		return internal ? unlockInternal() : unlockExternal();
525 	}
526 
getWidth() const527 	int Surface::getWidth() const
528 	{
529 		return external.width;
530 	}
531 
getHeight() const532 	int Surface::getHeight() const
533 	{
534 		return external.height;
535 	}
536 
getDepth() const537 	int Surface::getDepth() const
538 	{
539 		return external.depth;
540 	}
541 
getBorder() const542 	int Surface::getBorder() const
543 	{
544 		return internal.border;
545 	}
546 
getFormat(bool internal) const547 	Format Surface::getFormat(bool internal) const
548 	{
549 		return internal ? getInternalFormat() : getExternalFormat();
550 	}
551 
getPitchB(bool internal) const552 	int Surface::getPitchB(bool internal) const
553 	{
554 		return internal ? getInternalPitchB() : getExternalPitchB();
555 	}
556 
getPitchP(bool internal) const557 	int Surface::getPitchP(bool internal) const
558 	{
559 		return internal ? getInternalPitchP() : getExternalPitchP();
560 	}
561 
getSliceB(bool internal) const562 	int Surface::getSliceB(bool internal) const
563 	{
564 		return internal ? getInternalSliceB() : getExternalSliceB();
565 	}
566 
getSliceP(bool internal) const567 	int Surface::getSliceP(bool internal) const
568 	{
569 		return internal ? getInternalSliceP() : getExternalSliceP();
570 	}
571 
getExternalFormat() const572 	Format Surface::getExternalFormat() const
573 	{
574 		return external.format;
575 	}
576 
getExternalPitchB() const577 	int Surface::getExternalPitchB() const
578 	{
579 		return external.pitchB;
580 	}
581 
getExternalPitchP() const582 	int Surface::getExternalPitchP() const
583 	{
584 		return external.pitchP;
585 	}
586 
getExternalSliceB() const587 	int Surface::getExternalSliceB() const
588 	{
589 		return external.sliceB;
590 	}
591 
getExternalSliceP() const592 	int Surface::getExternalSliceP() const
593 	{
594 		return external.sliceP;
595 	}
596 
getInternalFormat() const597 	Format Surface::getInternalFormat() const
598 	{
599 		return internal.format;
600 	}
601 
getInternalPitchB() const602 	int Surface::getInternalPitchB() const
603 	{
604 		return internal.pitchB;
605 	}
606 
getInternalPitchP() const607 	int Surface::getInternalPitchP() const
608 	{
609 		return internal.pitchP;
610 	}
611 
getInternalSliceB() const612 	int Surface::getInternalSliceB() const
613 	{
614 		return internal.sliceB;
615 	}
616 
getInternalSliceP() const617 	int Surface::getInternalSliceP() const
618 	{
619 		return internal.sliceP;
620 	}
621 
getStencilFormat() const622 	Format Surface::getStencilFormat() const
623 	{
624 		return stencil.format;
625 	}
626 
getStencilPitchB() const627 	int Surface::getStencilPitchB() const
628 	{
629 		return stencil.pitchB;
630 	}
631 
getStencilSliceB() const632 	int Surface::getStencilSliceB() const
633 	{
634 		return stencil.sliceB;
635 	}
636 
getSamples() const637 	int Surface::getSamples() const
638 	{
639 		return internal.samples;
640 	}
641 
getMultiSampleCount() const642 	int Surface::getMultiSampleCount() const
643 	{
644 		return sw::min((int)internal.samples, 4);
645 	}
646 
getSuperSampleCount() const647 	int Surface::getSuperSampleCount() const
648 	{
649 		return internal.samples > 4 ? internal.samples / 4 : 1;
650 	}
651 
isUnlocked() const652 	bool Surface::isUnlocked() const
653 	{
654 		return external.lock == LOCK_UNLOCKED &&
655 		       internal.lock == LOCK_UNLOCKED &&
656 		       stencil.lock == LOCK_UNLOCKED;
657 	}
658 
isExternalDirty() const659 	bool Surface::isExternalDirty() const
660 	{
661 		return external.buffer && external.buffer != internal.buffer && external.dirty;
662 	}
663 }
664 
665 #endif   // sw_Surface_hpp
666