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