• 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 // Display.cpp: Implements the egl::Display class, representing the abstract
16 // display on which graphics are drawn. Implements EGLDisplay.
17 // [EGL 1.4] section 2.1.2 page 3.
18 
19 #include "Display.h"
20 
21 #include "main.h"
22 #include "libEGL/Surface.hpp"
23 #include "libEGL/Context.hpp"
24 #include "common/Image.hpp"
25 #include "common/debug.h"
26 #include "Common/RecursiveLock.hpp"
27 
28 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
29 #include <vndk/window.h>
30 #include <sys/ioctl.h>
31 #include <linux/fb.h>
32 #include <fcntl.h>
33 #elif defined(USE_X11)
34 #include "Main/libX11.hpp"
35 #elif defined(__APPLE__)
36 #include "OSXUtils.hpp"
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <IOSurface/IOSurface.h>
39 #endif
40 
41 #include <algorithm>
42 #include <vector>
43 #include <map>
44 
45 namespace egl
46 {
47 
48 class DisplayImplementation : public Display
49 {
50 public:
DisplayImplementation(EGLDisplay dpy,void * nativeDisplay)51 	DisplayImplementation(EGLDisplay dpy, void *nativeDisplay) : Display(dpy, nativeDisplay) {}
~DisplayImplementation()52 	~DisplayImplementation() override {}
53 
getSharedImage(EGLImageKHR name)54 	Image *getSharedImage(EGLImageKHR name) override
55 	{
56 		return Display::getSharedImage(name);
57 	}
58 };
59 
get(EGLDisplay dpy)60 Display *Display::get(EGLDisplay dpy)
61 {
62 	if(dpy != PRIMARY_DISPLAY && dpy != HEADLESS_DISPLAY)   // We only support the default display
63 	{
64 		return nullptr;
65 	}
66 
67 	static void *nativeDisplay = nullptr;
68 
69 	#if defined(USE_X11)
70 		// Even if the application provides a native display handle, we open (and close) our own connection
71 		if(!nativeDisplay && dpy != HEADLESS_DISPLAY && libX11 && libX11->XOpenDisplay)
72 		{
73 			nativeDisplay = libX11->XOpenDisplay(NULL);
74 		}
75 	#endif
76 
77 	static DisplayImplementation display(dpy, nativeDisplay);
78 
79 	return &display;
80 }
81 
Display(EGLDisplay eglDisplay,void * nativeDisplay)82 Display::Display(EGLDisplay eglDisplay, void *nativeDisplay) : eglDisplay(eglDisplay), nativeDisplay(nativeDisplay)
83 {
84 	mMinSwapInterval = 1;
85 	mMaxSwapInterval = 1;
86 }
87 
~Display()88 Display::~Display()
89 {
90 	terminate();
91 
92 	#if defined(USE_X11)
93 		if(nativeDisplay && libX11->XCloseDisplay)
94 		{
95 			libX11->XCloseDisplay((::Display*)nativeDisplay);
96 		}
97 	#endif
98 }
99 
100 #if !defined(__i386__) && defined(_M_IX86)
101 	#define __i386__ 1
102 #endif
103 
104 #if !defined(__x86_64__) && (defined(_M_AMD64) || defined (_M_X64))
105 	#define __x86_64__ 1
106 #endif
107 
108 #if defined(__i386__) || defined(__x86_64__)
cpuid(int registers[4],int info)109 static void cpuid(int registers[4], int info)
110 {
111 	#if defined(__i386__) || defined(__x86_64__)
112 		#if defined(_WIN32)
113 			__cpuid(registers, info);
114 		#else
115 			__asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info));
116 		#endif
117 	#else
118 		registers[0] = 0;
119 		registers[1] = 0;
120 		registers[2] = 0;
121 		registers[3] = 0;
122 	#endif
123 }
124 
detectSSE()125 static bool detectSSE()
126 {
127 	int registers[4];
128 	cpuid(registers, 1);
129 	return (registers[3] & 0x02000000) != 0;
130 }
131 #endif
132 
initialize()133 bool Display::initialize()
134 {
135 	if(isInitialized())
136 	{
137 		return true;
138 	}
139 
140 	#if defined(__i386__) || defined(__x86_64__)
141 		if(!detectSSE())
142 		{
143 			return false;
144 		}
145 	#endif
146 
147 	mMinSwapInterval = 0;
148 	mMaxSwapInterval = 4;
149 
150 	const int samples[] =
151 	{
152 		0,
153 		2,
154 		4
155 	};
156 
157 	const sw::Format renderTargetFormats[] =
158 	{
159 	//	sw::FORMAT_A1R5G5B5,
160 	//  sw::FORMAT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
161 		sw::FORMAT_A8R8G8B8,
162 		sw::FORMAT_A8B8G8R8,
163 		sw::FORMAT_R5G6B5,
164 	//  sw::FORMAT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
165 		sw::FORMAT_X8R8G8B8,
166 		sw::FORMAT_X8B8G8R8
167 	};
168 
169 	const sw::Format depthStencilFormats[] =
170 	{
171 		sw::FORMAT_NULL,
172 	//  sw::FORMAT_D16_LOCKABLE,
173 		sw::FORMAT_D32,
174 	//  sw::FORMAT_D15S1,
175 		sw::FORMAT_D24S8,
176 		sw::FORMAT_D24X8,
177 	//  sw::FORMAT_D24X4S4,
178 		sw::FORMAT_D16,
179 	//  sw::FORMAT_D32F_LOCKABLE,
180 	//  sw::FORMAT_D24FS8
181 	};
182 
183 	sw::Format currentDisplayFormat = getDisplayFormat();
184 	ConfigSet configSet;
185 
186 	for(unsigned int samplesIndex = 0; samplesIndex < sizeof(samples) / sizeof(int); samplesIndex++)
187 	{
188 		for(sw::Format renderTargetFormat : renderTargetFormats)
189 		{
190 			for(sw::Format depthStencilFormat : depthStencilFormats)
191 			{
192 				configSet.add(currentDisplayFormat, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, samples[samplesIndex]);
193 			}
194 		}
195 	}
196 
197 	// Give the sorted configs a unique ID and store them internally
198 	EGLint index = 1;
199 	for(ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
200 	{
201 		Config configuration = *config;
202 		configuration.mConfigID = index;
203 		index++;
204 
205 		mConfigSet.mSet.insert(configuration);
206 	}
207 
208 	if(!isInitialized())
209 	{
210 		terminate();
211 
212 		return false;
213 	}
214 
215 	return true;
216 }
217 
terminate()218 void Display::terminate()
219 {
220 	while(!mSurfaceSet.empty())
221 	{
222 		destroySurface(*mSurfaceSet.begin());
223 	}
224 
225 	while(!mContextSet.empty())
226 	{
227 		destroyContext(*mContextSet.begin());
228 	}
229 
230 	while(!mSharedImageNameSpace.empty())
231 	{
232 		destroySharedImage(reinterpret_cast<EGLImageKHR>((intptr_t)mSharedImageNameSpace.firstName()));
233 	}
234 }
235 
getConfigs(EGLConfig * configs,const EGLint * attribList,EGLint configSize,EGLint * numConfig)236 bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
237 {
238 	return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
239 }
240 
getConfigAttrib(EGLConfig config,EGLint attribute,EGLint * value)241 bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
242 {
243 	const egl::Config *configuration = mConfigSet.get(config);
244 
245 	switch(attribute)
246 	{
247 	case EGL_BUFFER_SIZE:                *value = configuration->mBufferSize;               break;
248 	case EGL_ALPHA_SIZE:                 *value = configuration->mAlphaSize;                break;
249 	case EGL_BLUE_SIZE:                  *value = configuration->mBlueSize;                 break;
250 	case EGL_GREEN_SIZE:                 *value = configuration->mGreenSize;                break;
251 	case EGL_RED_SIZE:                   *value = configuration->mRedSize;                  break;
252 	case EGL_DEPTH_SIZE:                 *value = configuration->mDepthSize;                break;
253 	case EGL_STENCIL_SIZE:               *value = configuration->mStencilSize;              break;
254 	case EGL_CONFIG_CAVEAT:              *value = configuration->mConfigCaveat;             break;
255 	case EGL_CONFIG_ID:                  *value = configuration->mConfigID;                 break;
256 	case EGL_LEVEL:                      *value = configuration->mLevel;                    break;
257 	case EGL_NATIVE_RENDERABLE:          *value = configuration->mNativeRenderable;         break;
258 	case EGL_NATIVE_VISUAL_ID:           *value = configuration->mNativeVisualID;           break;
259 	case EGL_NATIVE_VISUAL_TYPE:         *value = configuration->mNativeVisualType;         break;
260 	case EGL_SAMPLES:                    *value = configuration->mSamples;                  break;
261 	case EGL_SAMPLE_BUFFERS:             *value = configuration->mSampleBuffers;            break;
262 	case EGL_SURFACE_TYPE:               *value = configuration->mSurfaceType;              break;
263 	case EGL_TRANSPARENT_TYPE:           *value = configuration->mTransparentType;          break;
264 	case EGL_TRANSPARENT_BLUE_VALUE:     *value = configuration->mTransparentBlueValue;     break;
265 	case EGL_TRANSPARENT_GREEN_VALUE:    *value = configuration->mTransparentGreenValue;    break;
266 	case EGL_TRANSPARENT_RED_VALUE:      *value = configuration->mTransparentRedValue;      break;
267 	case EGL_BIND_TO_TEXTURE_RGB:        *value = configuration->mBindToTextureRGB;         break;
268 	case EGL_BIND_TO_TEXTURE_RGBA:       *value = configuration->mBindToTextureRGBA;        break;
269 	case EGL_MIN_SWAP_INTERVAL:          *value = configuration->mMinSwapInterval;          break;
270 	case EGL_MAX_SWAP_INTERVAL:          *value = configuration->mMaxSwapInterval;          break;
271 	case EGL_LUMINANCE_SIZE:             *value = configuration->mLuminanceSize;            break;
272 	case EGL_ALPHA_MASK_SIZE:            *value = configuration->mAlphaMaskSize;            break;
273 	case EGL_COLOR_BUFFER_TYPE:          *value = configuration->mColorBufferType;          break;
274 	case EGL_RENDERABLE_TYPE:            *value = configuration->mRenderableType;           break;
275 	case EGL_MATCH_NATIVE_PIXMAP:        *value = EGL_FALSE; UNIMPLEMENTED();               break;
276 	case EGL_CONFORMANT:                 *value = configuration->mConformant;               break;
277 	case EGL_MAX_PBUFFER_WIDTH:          *value = configuration->mMaxPBufferWidth;          break;
278 	case EGL_MAX_PBUFFER_HEIGHT:         *value = configuration->mMaxPBufferHeight;         break;
279 	case EGL_MAX_PBUFFER_PIXELS:         *value = configuration->mMaxPBufferPixels;         break;
280 	case EGL_RECORDABLE_ANDROID:         *value = configuration->mRecordableAndroid;        break;
281 	case EGL_FRAMEBUFFER_TARGET_ANDROID: *value = configuration->mFramebufferTargetAndroid; break;
282 	case EGL_BIND_TO_TEXTURE_TARGET_ANGLE: *value = configuration->mBindToTextureTargetANGLE; break;
283 	default:
284 		return false;
285 	}
286 
287 	return true;
288 }
289 
createWindowSurface(EGLNativeWindowType window,EGLConfig config,const EGLAttrib * attribList)290 EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLAttrib *attribList)
291 {
292 	const Config *configuration = mConfigSet.get(config);
293 
294 	if(attribList)
295 	{
296 		while(*attribList != EGL_NONE)
297 		{
298 			switch(attribList[0])
299 			{
300 			case EGL_RENDER_BUFFER:
301 				switch(attribList[1])
302 				{
303 				case EGL_BACK_BUFFER:
304 					break;
305 				case EGL_SINGLE_BUFFER:
306 					return error(EGL_BAD_MATCH, EGL_NO_SURFACE);   // Rendering directly to front buffer not supported
307 				default:
308 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
309 				}
310 				break;
311 			case EGL_VG_COLORSPACE:
312 				return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
313 			case EGL_VG_ALPHA_FORMAT:
314 				return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
315 			default:
316 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
317 			}
318 
319 			attribList += 2;
320 		}
321 	}
322 
323 	if(hasExistingWindowSurface(window))
324 	{
325 		return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
326 	}
327 
328 	Surface *surface = new WindowSurface(this, configuration, window);
329 
330 	if(!surface->initialize())
331 	{
332 		surface->release();
333 		return EGL_NO_SURFACE;
334 	}
335 
336 	surface->addRef();
337 	mSurfaceSet.insert(surface);
338 
339 	return success(surface);
340 }
341 
createPBufferSurface(EGLConfig config,const EGLint * attribList,EGLClientBuffer clientBuffer)342 EGLSurface Display::createPBufferSurface(EGLConfig config, const EGLint *attribList, EGLClientBuffer clientBuffer)
343 {
344 	EGLint width = -1, height = -1, ioSurfacePlane = -1;
345 	EGLenum textureFormat = EGL_NO_TEXTURE;
346 	EGLenum textureTarget = EGL_NO_TEXTURE;
347 	EGLenum clientBufferFormat = EGL_NO_TEXTURE;
348 	EGLenum clientBufferType = EGL_NO_TEXTURE;
349 	EGLBoolean largestPBuffer = EGL_FALSE;
350 	const Config *configuration = mConfigSet.get(config);
351 
352 	if(attribList)
353 	{
354 		while(*attribList != EGL_NONE)
355 		{
356 			switch(attribList[0])
357 			{
358 			case EGL_WIDTH:
359 				width = attribList[1];
360 				break;
361 			case EGL_HEIGHT:
362 				height = attribList[1];
363 				break;
364 			case EGL_LARGEST_PBUFFER:
365 				largestPBuffer = attribList[1];
366 				break;
367 			case EGL_TEXTURE_FORMAT:
368 				switch(attribList[1])
369 				{
370 				case EGL_NO_TEXTURE:
371 				case EGL_TEXTURE_RGB:
372 				case EGL_TEXTURE_RGBA:
373 					textureFormat = attribList[1];
374 					break;
375 				default:
376 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
377 				}
378 				break;
379 			case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
380 				switch(attribList[1])
381 				{
382 				case GL_RED:
383 				case GL_R16UI:
384 				case GL_RG:
385 				case GL_RGB:
386 				case GL_BGRA_EXT:
387 				case GL_RGBA:
388 					clientBufferFormat = attribList[1];
389 					break;
390 				default:
391 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
392 				}
393 				break;
394 			case EGL_TEXTURE_TYPE_ANGLE:
395 				switch(attribList[1])
396 				{
397 				case GL_UNSIGNED_BYTE:
398 				case GL_UNSIGNED_SHORT:
399 				case GL_HALF_FLOAT_OES:
400 				case GL_HALF_FLOAT:
401 					clientBufferType = attribList[1];
402 					break;
403 				default:
404 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
405 				}
406 				break;
407 			case EGL_IOSURFACE_PLANE_ANGLE:
408 				if(attribList[1] < 0)
409 				{
410 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
411 				}
412 				ioSurfacePlane = attribList[1];
413 				break;
414 			case EGL_TEXTURE_TARGET:
415 				switch(attribList[1])
416 				{
417 				case EGL_NO_TEXTURE:
418 				case EGL_TEXTURE_2D:
419 				case EGL_TEXTURE_RECTANGLE_ANGLE:
420 					textureTarget = attribList[1];
421 					break;
422 				default:
423 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
424 				}
425 				break;
426 			case EGL_MIPMAP_TEXTURE:
427 				if(attribList[1] != EGL_FALSE)
428 				{
429 					UNIMPLEMENTED();
430 					return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
431 				}
432 				break;
433 			case EGL_VG_COLORSPACE:
434 				return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
435 			case EGL_VG_ALPHA_FORMAT:
436 				return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
437 			default:
438 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
439 			}
440 
441 			attribList += 2;
442 		}
443 	}
444 
445 	if(width < 0 || height < 0)
446 	{
447 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
448 	}
449 
450 	if(width == 0 || height == 0)
451 	{
452 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
453 	}
454 
455 	if((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
456 	   (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
457 	{
458 		return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
459 	}
460 
461 	if(!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
462 	{
463 		return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
464 	}
465 
466 	if(clientBuffer)
467 	{
468 		switch(clientBufferType)
469 		{
470 		case GL_UNSIGNED_BYTE:
471 			switch(clientBufferFormat)
472 			{
473 			case GL_RED:
474 			case GL_RG:
475 			case GL_RGB:
476 			case GL_BGRA_EXT:
477 				break;
478 			case GL_R16UI:
479 			case GL_RGBA:
480 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
481 			default:
482 				return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
483 			}
484 			break;
485 		case GL_UNSIGNED_SHORT:
486 			switch(clientBufferFormat)
487 			{
488 			case GL_R16UI:
489 				break;
490 			case GL_RED:
491 			case GL_RG:
492 			case GL_BGRA_EXT:
493 			case GL_RGBA:
494 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
495 			default:
496 				return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
497 			}
498 			break;
499 		case GL_HALF_FLOAT_OES:
500 		case GL_HALF_FLOAT:
501 			switch(clientBufferFormat)
502 			{
503 			case GL_RGBA:
504 				break;
505 			case GL_RED:
506 			case GL_R16UI:
507 			case GL_RG:
508 			case GL_BGRA_EXT:
509 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
510 			default:
511 				return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
512 			}
513 			break;
514 		default:
515 			return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
516 		}
517 
518 		if(ioSurfacePlane < 0)
519 		{
520 			return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
521 		}
522 
523 		if(textureFormat != EGL_TEXTURE_RGBA)
524 		{
525 			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
526 		}
527 
528 		if(textureTarget != EGL_TEXTURE_RECTANGLE_ANGLE)
529 		{
530 			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
531 		}
532 
533 #if defined(__APPLE__)
534 		IOSurfaceRef ioSurface = reinterpret_cast<IOSurfaceRef>(clientBuffer);
535 		size_t planeCount = IOSurfaceGetPlaneCount(ioSurface);
536 		if((static_cast<size_t>(width) > IOSurfaceGetWidthOfPlane(ioSurface, ioSurfacePlane)) ||
537 		   (static_cast<size_t>(height) > IOSurfaceGetHeightOfPlane(ioSurface, ioSurfacePlane)) ||
538 		   ((planeCount != 0) && static_cast<size_t>(ioSurfacePlane) >= planeCount))
539 		{
540 			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
541 		}
542 #endif
543 	}
544 	else
545 	{
546 		if((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
547 		   ((textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)))
548 		{
549 			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
550 		}
551 	}
552 
553 	Surface *surface = new PBufferSurface(this, configuration, width, height, textureFormat, textureTarget, clientBufferFormat, clientBufferType, largestPBuffer, clientBuffer, ioSurfacePlane);
554 
555 	if(!surface->initialize())
556 	{
557 		surface->release();
558 		return EGL_NO_SURFACE;
559 	}
560 
561 	surface->addRef();
562 	mSurfaceSet.insert(surface);
563 
564 	return success(surface);
565 }
566 
createContext(EGLConfig configHandle,const egl::Context * shareContext,EGLint clientVersion)567 EGLContext Display::createContext(EGLConfig configHandle, const egl::Context *shareContext, EGLint clientVersion)
568 {
569 	const egl::Config *config = mConfigSet.get(configHandle);
570 	egl::Context *context = nullptr;
571 
572 	if(clientVersion == 1 && config->mRenderableType & EGL_OPENGL_ES_BIT)
573 	{
574 		if(libGLES_CM)
575 		{
576 			context = libGLES_CM->es1CreateContext(this, shareContext, config);
577 		}
578 	}
579 	else if((clientVersion == 2 && config->mRenderableType & EGL_OPENGL_ES2_BIT) ||
580 	        (clientVersion == 3 && config->mRenderableType & EGL_OPENGL_ES3_BIT))
581 	{
582 		if(libGLESv2)
583 		{
584 			context = libGLESv2->es2CreateContext(this, shareContext, config);
585 		}
586 	}
587 	else
588 	{
589 		return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
590 	}
591 
592 	if(!context)
593 	{
594 		return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
595 	}
596 
597 	context->addRef();
598 	mContextSet.insert(context);
599 
600 	return success(context);
601 }
602 
createSync(Context * context)603 EGLSyncKHR Display::createSync(Context *context)
604 {
605 	FenceSync *fenceSync = new egl::FenceSync(context);
606 	mSyncSet.insert(fenceSync);
607 	return fenceSync;
608 }
609 
destroySurface(egl::Surface * surface)610 void Display::destroySurface(egl::Surface *surface)
611 {
612 	surface->release();
613 	mSurfaceSet.erase(surface);
614 
615 	if(surface == getCurrentDrawSurface())
616 	{
617 		setCurrentDrawSurface(nullptr);
618 	}
619 
620 	if(surface == getCurrentReadSurface())
621 	{
622 		setCurrentReadSurface(nullptr);
623 	}
624 }
625 
destroyContext(egl::Context * context)626 void Display::destroyContext(egl::Context *context)
627 {
628 	context->release();
629 	mContextSet.erase(context);
630 
631 	if(context == getCurrentContext())
632 	{
633 		setCurrentContext(nullptr);
634 		setCurrentDrawSurface(nullptr);
635 		setCurrentReadSurface(nullptr);
636 	}
637 }
638 
destroySync(FenceSync * sync)639 void Display::destroySync(FenceSync *sync)
640 {
641 	{
642 		mSyncSet.erase(sync);
643 	}
644 	delete sync;
645 }
646 
isInitialized() const647 bool Display::isInitialized() const
648 {
649 	return mConfigSet.size() > 0;
650 }
651 
isValidConfig(EGLConfig config)652 bool Display::isValidConfig(EGLConfig config)
653 {
654 	return mConfigSet.get(config) != nullptr;
655 }
656 
isValidContext(egl::Context * context)657 bool Display::isValidContext(egl::Context *context)
658 {
659 	return mContextSet.find(context) != mContextSet.end();
660 }
661 
isValidSurface(egl::Surface * surface)662 bool Display::isValidSurface(egl::Surface *surface)
663 {
664 	return mSurfaceSet.find(surface) != mSurfaceSet.end();
665 }
666 
isValidWindow(EGLNativeWindowType window)667 bool Display::isValidWindow(EGLNativeWindowType window)
668 {
669 	#if defined(_WIN32)
670 		return IsWindow(window) == TRUE;
671 	#elif defined(__ANDROID__)
672 		if(!window)
673 		{
674 			ERR("%s called with window==NULL %s:%d", __FUNCTION__, __FILE__, __LINE__);
675 			return false;
676 		}
677 		return true;
678 	#elif defined(USE_X11)
679 		if(nativeDisplay)
680 		{
681 			XWindowAttributes windowAttributes;
682 			Status status = libX11->XGetWindowAttributes((::Display*)nativeDisplay, window, &windowAttributes);
683 
684 			return status != 0;
685 		}
686 		return false;
687 	#elif defined(__linux__)
688 		return false;  // Non X11 linux is headless only
689 	#elif defined(__APPLE__)
690 		return sw::OSX::IsValidWindow(window);
691 	#elif defined(__Fuchsia__)
692 		// TODO(crbug.com/800951): Integrate with Mozart.
693 		return true;
694 	#else
695 		#error "Display::isValidWindow unimplemented for this platform"
696 		return false;
697 	#endif
698 }
699 
hasExistingWindowSurface(EGLNativeWindowType window)700 bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
701 {
702 	for(const auto &surface : mSurfaceSet)
703 	{
704 		if(surface->isWindowSurface())
705 		{
706 			if(surface->getWindowHandle() == window)
707 			{
708 				return true;
709 			}
710 		}
711 	}
712 
713 	return false;
714 }
715 
isValidSync(FenceSync * sync)716 bool Display::isValidSync(FenceSync *sync)
717 {
718 	return mSyncSet.find(sync) != mSyncSet.end();
719 }
720 
getMinSwapInterval() const721 EGLint Display::getMinSwapInterval() const
722 {
723 	return mMinSwapInterval;
724 }
725 
getMaxSwapInterval() const726 EGLint Display::getMaxSwapInterval() const
727 {
728 	return mMaxSwapInterval;
729 }
730 
getEGLDisplay() const731 EGLDisplay Display::getEGLDisplay() const
732 {
733 	return eglDisplay;
734 }
735 
getNativeDisplay() const736 void *Display::getNativeDisplay() const
737 {
738 	return nativeDisplay;
739 }
740 
createSharedImage(Image * image)741 EGLImageKHR Display::createSharedImage(Image *image)
742 {
743 	return reinterpret_cast<EGLImageKHR>((intptr_t)mSharedImageNameSpace.allocate(image));
744 }
745 
destroySharedImage(EGLImageKHR image)746 bool Display::destroySharedImage(EGLImageKHR image)
747 {
748 	GLuint name = (GLuint)reinterpret_cast<intptr_t>(image);
749 	Image *eglImage = mSharedImageNameSpace.find(name);
750 
751 	if(!eglImage)
752 	{
753 		return false;
754 	}
755 
756 	eglImage->destroyShared();
757 	mSharedImageNameSpace.remove(name);
758 
759 	return true;
760 }
761 
getSharedImage(EGLImageKHR image)762 Image *Display::getSharedImage(EGLImageKHR image)
763 {
764 	GLuint name = (GLuint)reinterpret_cast<intptr_t>(image);
765 	return mSharedImageNameSpace.find(name);
766 }
767 
getDisplayFormat() const768 sw::Format Display::getDisplayFormat() const
769 {
770 	#if defined(_WIN32)
771 		HDC deviceContext = GetDC(0);
772 		unsigned int bpp = ::GetDeviceCaps(deviceContext, BITSPIXEL);
773 		ReleaseDC(0, deviceContext);
774 
775 		switch(bpp)
776 		{
777 		case 32: return sw::FORMAT_X8R8G8B8;
778 		case 24: return sw::FORMAT_R8G8B8;
779 		case 16: return sw::FORMAT_R5G6B5;
780 		default: UNREACHABLE(bpp);   // Unexpected display mode color depth
781 		}
782 	#elif defined(__ANDROID__)
783 	#if !defined(ANDROID_NDK_BUILD)
784 		static const char *const framebuffer[] =
785 		{
786 			"/dev/graphics/fb0",
787 			"/dev/fb0",
788 			0
789 		};
790 
791 		for(int i = 0; framebuffer[i]; i++)
792 		{
793 			int fd = open(framebuffer[i], O_RDONLY, 0);
794 
795 			if(fd != -1)
796 			{
797 				struct fb_var_screeninfo info;
798 				int io = ioctl(fd, FBIOGET_VSCREENINFO, &info);
799 				close(fd);
800 
801 				if(io >= 0)
802 				{
803 					switch(info.bits_per_pixel)
804 					{
805 					case 16:
806 						return sw::FORMAT_R5G6B5;
807 					case 32:
808 						if(info.red.length    == 8 && info.red.offset    == 16 &&
809 						   info.green.length  == 8 && info.green.offset  == 8  &&
810 						   info.blue.length   == 8 && info.blue.offset   == 0  &&
811 						   info.transp.length == 0)
812 						{
813 							return sw::FORMAT_X8R8G8B8;
814 						}
815 						if(info.red.length    == 8 && info.red.offset    == 0  &&
816 						   info.green.length  == 8 && info.green.offset  == 8  &&
817 						   info.blue.length   == 8 && info.blue.offset   == 16 &&
818 						   info.transp.length == 0)
819 						{
820 							return sw::FORMAT_X8B8G8R8;
821 						}
822 						if(info.red.length    == 8 && info.red.offset    == 16 &&
823 						   info.green.length  == 8 && info.green.offset  == 8  &&
824 						   info.blue.length   == 8 && info.blue.offset   == 0  &&
825 						   info.transp.length == 8 && info.transp.offset == 24)
826 						{
827 							return sw::FORMAT_A8R8G8B8;
828 						}
829 						if(info.red.length    == 8 && info.red.offset    == 0  &&
830 						   info.green.length  == 8 && info.green.offset  == 8  &&
831 						   info.blue.length   == 8 && info.blue.offset   == 16 &&
832 						   info.transp.length == 8 && info.transp.offset == 24)
833 						{
834 							return sw::FORMAT_A8B8G8R8;
835 						}
836 						else UNIMPLEMENTED();
837 					default:
838 						UNIMPLEMENTED();
839 					}
840 				}
841 			}
842 		}
843 	#endif // !defined_ANDROID_NDK_BUILD)
844 
845 		// No framebuffer device found, or we're in user space
846 		return sw::FORMAT_X8B8G8R8;
847 	#elif defined(USE_X11)
848 		if(nativeDisplay)
849 		{
850 			Screen *screen = libX11->XDefaultScreenOfDisplay((::Display*)nativeDisplay);
851 			unsigned int bpp = libX11->XPlanesOfScreen(screen);
852 
853 			switch(bpp)
854 			{
855 			case 32: return sw::FORMAT_X8R8G8B8;
856 			case 24: return sw::FORMAT_R8G8B8;
857 			case 16: return sw::FORMAT_R5G6B5;
858 			default: UNREACHABLE(bpp);   // Unexpected display mode color depth
859 			}
860 		}
861 		else
862 		{
863 			return sw::FORMAT_X8R8G8B8;
864 		}
865 	#elif defined(__linux__)  // Non X11 linux is headless only
866 		return sw::FORMAT_A8B8G8R8;
867 	#elif defined(__APPLE__)
868 		return sw::FORMAT_A8B8G8R8;
869 	#elif defined(__Fuchsia__)
870 		return sw::FORMAT_A8B8G8R8;
871 	#else
872 		#error "Display::isValidWindow unimplemented for this platform"
873 	#endif
874 
875 	return sw::FORMAT_X8R8G8B8;
876 }
877 
878 }
879