1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Display.cpp: Implements the egl::Display class, representing the abstract
8 // display on which graphics are drawn. Implements EGLDisplay.
9 // [EGL 1.4] section 2.1.2 page 3.
10 
11 #include "libANGLE/Display.h"
12 
13 #include <algorithm>
14 #include <iterator>
15 #include <map>
16 #include <sstream>
17 #include <vector>
18 
19 #include <platform/Platform.h>
20 #include <EGL/eglext.h>
21 
22 #include "common/debug.h"
23 #include "common/mathutil.h"
24 #include "common/platform.h"
25 #include "common/utilities.h"
26 #include "libANGLE/Context.h"
27 #include "libANGLE/Device.h"
28 #include "libANGLE/histogram_macros.h"
29 #include "libANGLE/Image.h"
30 #include "libANGLE/Surface.h"
31 #include "libANGLE/Stream.h"
32 #include "libANGLE/renderer/DisplayImpl.h"
33 #include "libANGLE/renderer/ImageImpl.h"
34 #include "third_party/trace_event/trace_event.h"
35 
36 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
37 #   include "libANGLE/renderer/d3d/DisplayD3D.h"
38 #endif
39 
40 #if defined(ANGLE_ENABLE_OPENGL)
41 #   if defined(ANGLE_PLATFORM_WINDOWS)
42 #       include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
43 #   elif defined(ANGLE_USE_X11)
44 #       include "libANGLE/renderer/gl/glx/DisplayGLX.h"
45 #   elif defined(ANGLE_PLATFORM_APPLE)
46 #       include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
47 #   elif defined(ANGLE_USE_OZONE)
48 #       include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
49 #   elif defined(ANGLE_PLATFORM_ANDROID)
50 #       include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
51 #   else
52 #       error Unsupported OpenGL platform.
53 #   endif
54 #endif
55 
56 #if defined(ANGLE_ENABLE_NULL)
57 #include "libANGLE/renderer/null/DisplayNULL.h"
58 #endif
59 
60 namespace egl
61 {
62 
63 namespace
64 {
65 
66 class DefaultPlatform : public angle::Platform
67 {
68 public:
DefaultPlatform()69     DefaultPlatform() {}
~DefaultPlatform()70     ~DefaultPlatform() override {}
71 };
72 
73 DefaultPlatform *defaultPlatform = nullptr;
74 
InitDefaultPlatformImpl()75 void InitDefaultPlatformImpl()
76 {
77     if (ANGLEPlatformCurrent() == nullptr)
78     {
79         if (defaultPlatform == nullptr)
80         {
81             defaultPlatform = new DefaultPlatform();
82         }
83 
84         ANGLEPlatformInitialize(defaultPlatform);
85     }
86 }
87 
88 typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap;
89 // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
90 // associated with it.
GetWindowSurfaces()91 static WindowSurfaceMap *GetWindowSurfaces()
92 {
93     static WindowSurfaceMap windowSurfaces;
94     return &windowSurfaces;
95 }
96 
97 typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
GetANGLEPlatformDisplayMap()98 static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
99 {
100     static ANGLEPlatformDisplayMap displays;
101     return &displays;
102 }
103 
104 typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
GetDevicePlatformDisplayMap()105 static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
106 {
107     static DevicePlatformDisplayMap displays;
108     return &displays;
109 }
110 
CreateDisplayFromDevice(Device * eglDevice)111 rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
112 {
113     rx::DisplayImpl *impl = nullptr;
114 
115     switch (eglDevice->getType())
116     {
117 #if defined(ANGLE_ENABLE_D3D11)
118         case EGL_D3D11_DEVICE_ANGLE:
119             impl = new rx::DisplayD3D();
120             break;
121 #endif
122 #if defined(ANGLE_ENABLE_D3D9)
123         case EGL_D3D9_DEVICE_ANGLE:
124             // Currently the only way to get EGLDeviceEXT representing a D3D9 device
125             // is to retrieve one from an already-existing EGLDisplay.
126             // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
127             // the already-existing display should be returned.
128             // Therefore this codepath to create a new display from the device
129             // should never be hit.
130             UNREACHABLE();
131             break;
132 #endif
133         default:
134             UNREACHABLE();
135             break;
136     }
137 
138     ASSERT(impl != nullptr);
139     return impl;
140 }
141 
CreateDisplayFromAttribs(const AttributeMap & attribMap)142 rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap)
143 {
144     rx::DisplayImpl *impl = nullptr;
145     EGLAttrib displayType =
146         attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
147     switch (displayType)
148     {
149       case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
150 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
151         // Default to D3D displays
152         impl = new rx::DisplayD3D();
153 #elif defined(ANGLE_USE_X11)
154         impl = new rx::DisplayGLX();
155 #elif defined(ANGLE_PLATFORM_APPLE)
156         impl = new rx::DisplayCGL();
157 #elif defined(ANGLE_USE_OZONE)
158         impl = new rx::DisplayOzone();
159 #elif defined(ANGLE_PLATFORM_ANDROID)
160         impl = new rx::DisplayAndroid();
161 #else
162         // No display available
163         UNREACHABLE();
164 #endif
165         break;
166 
167       case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
168       case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
169 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
170         impl = new rx::DisplayD3D();
171 #else
172         // A D3D display was requested on a platform that doesn't support it
173         UNREACHABLE();
174 #endif
175         break;
176 
177       case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
178 #if defined(ANGLE_ENABLE_OPENGL)
179 #if defined(ANGLE_PLATFORM_WINDOWS)
180         impl = new rx::DisplayWGL();
181 #elif defined(ANGLE_USE_X11)
182         impl = new rx::DisplayGLX();
183 #elif defined(ANGLE_PLATFORM_APPLE)
184         impl = new rx::DisplayCGL();
185 #elif defined(ANGLE_USE_OZONE)
186         // This might work but has never been tried, so disallow for now.
187         impl = nullptr;
188 #elif defined(ANGLE_PLATFORM_ANDROID)
189         // No GL support on this platform, fail display creation.
190         impl = nullptr;
191 #else
192 #error Unsupported OpenGL platform.
193 #endif
194 #else
195         UNREACHABLE();
196 #endif
197         break;
198 
199 #if defined(ANGLE_ENABLE_OPENGL)
200       case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
201 #if defined(ANGLE_PLATFORM_WINDOWS)
202         impl = new rx::DisplayWGL();
203 #elif defined(ANGLE_USE_X11)
204         impl = new rx::DisplayGLX();
205 #elif defined(ANGLE_USE_OZONE)
206         impl = new rx::DisplayOzone();
207 #elif defined(ANGLE_PLATFORM_ANDROID)
208         impl = new rx::DisplayAndroid();
209 #else
210         // No GLES support on this platform, fail display creation.
211         impl = nullptr;
212 #endif
213         break;
214 #endif
215 
216 #if defined(ANGLE_ENABLE_NULL)
217       case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
218           impl = new rx::DisplayNULL();
219           break;
220 #endif
221 
222       default:
223         UNREACHABLE();
224         break;
225     }
226 
227     return impl;
228 }
229 
230 }
231 
GetDisplayFromAttribs(void * native_display,const AttributeMap & attribMap)232 Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap)
233 {
234     // Initialize the global platform if not already
235     InitDefaultPlatformImpl();
236 
237     Display *display = nullptr;
238 
239     EGLNativeDisplayType displayId = reinterpret_cast<EGLNativeDisplayType>(native_display);
240 
241     ANGLEPlatformDisplayMap *displays            = GetANGLEPlatformDisplayMap();
242     ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId);
243     if (iter != displays->end())
244     {
245         display = iter->second;
246     }
247 
248     if (display == nullptr)
249     {
250         // Validate the native display
251         if (!Display::isValidNativeDisplay(displayId))
252         {
253             return NULL;
254         }
255 
256         display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr);
257         displays->insert(std::make_pair(displayId, display));
258     }
259 
260     // Apply new attributes if the display is not initialized yet.
261     if (!display->isInitialized())
262     {
263         rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap);
264         if (impl == nullptr)
265         {
266             // No valid display implementation for these attributes
267             return nullptr;
268         }
269 
270         display->setAttributes(impl, attribMap);
271     }
272 
273     return display;
274 }
275 
GetDisplayFromDevice(void * native_display)276 Display *Display::GetDisplayFromDevice(void *native_display)
277 {
278     // Initialize the global platform if not already
279     InitDefaultPlatformImpl();
280 
281     Display *display = nullptr;
282 
283     Device *eglDevice = reinterpret_cast<Device *>(native_display);
284     ASSERT(Device::IsValidDevice(eglDevice));
285 
286     ANGLEPlatformDisplayMap *anglePlatformDisplays   = GetANGLEPlatformDisplayMap();
287     DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
288 
289     // First see if this eglDevice is in use by a Display created using ANGLE platform
290     for (auto &displayMapEntry : *anglePlatformDisplays)
291     {
292         egl::Display *iterDisplay = displayMapEntry.second;
293         if (iterDisplay->getDevice() == eglDevice)
294         {
295             display = iterDisplay;
296         }
297     }
298 
299     if (display == nullptr)
300     {
301         // See if the eglDevice is in use by a Display created using the DEVICE platform
302         DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice);
303         if (iter != devicePlatformDisplays->end())
304         {
305             display = iter->second;
306         }
307     }
308 
309     if (display == nullptr)
310     {
311         // Otherwise create a new Display
312         display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice);
313         devicePlatformDisplays->insert(std::make_pair(eglDevice, display));
314     }
315 
316     // Apply new attributes if the display is not initialized yet.
317     if (!display->isInitialized())
318     {
319         rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice);
320         display->setAttributes(impl, egl::AttributeMap());
321     }
322 
323     return display;
324 }
325 
Display(EGLenum platform,EGLNativeDisplayType displayId,Device * eglDevice)326 Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
327     : mImplementation(nullptr),
328       mDisplayId(displayId),
329       mAttributeMap(),
330       mConfigSet(),
331       mContextSet(),
332       mStreamSet(),
333       mInitialized(false),
334       mDeviceLost(false),
335       mCaps(),
336       mDisplayExtensions(),
337       mDisplayExtensionString(),
338       mVendorString(),
339       mDevice(eglDevice),
340       mPlatform(platform)
341 {
342 }
343 
~Display()344 Display::~Display()
345 {
346     terminate();
347 
348     if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
349     {
350         ANGLEPlatformDisplayMap *displays      = GetANGLEPlatformDisplayMap();
351         ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId);
352         if (iter != displays->end())
353         {
354             displays->erase(iter);
355         }
356     }
357     else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
358     {
359         DevicePlatformDisplayMap *displays      = GetDevicePlatformDisplayMap();
360         DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
361         if (iter != displays->end())
362         {
363             displays->erase(iter);
364         }
365     }
366     else
367     {
368         UNREACHABLE();
369     }
370 
371     SafeDelete(mDevice);
372     SafeDelete(mImplementation);
373 }
374 
setAttributes(rx::DisplayImpl * impl,const AttributeMap & attribMap)375 void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap)
376 {
377     ASSERT(!mInitialized);
378 
379     ASSERT(impl != nullptr);
380     SafeDelete(mImplementation);
381     mImplementation = impl;
382 
383     mAttributeMap = attribMap;
384 }
385 
initialize()386 Error Display::initialize()
387 {
388     // Re-initialize default platform if it's needed
389     InitDefaultPlatformImpl();
390 
391     SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS");
392     TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
393 
394     ASSERT(mImplementation != nullptr);
395 
396     if (isInitialized())
397     {
398         return egl::Error(EGL_SUCCESS);
399     }
400 
401     Error error = mImplementation->initialize(this);
402     if (error.isError())
403     {
404         // Log extended error message here
405         std::stringstream errorStream;
406         errorStream << "ANGLE Display::initialize error " << error.getID() << ": "
407                     << error.getMessage();
408         ANGLEPlatformCurrent()->logError(errorStream.str().c_str());
409         return error;
410     }
411 
412     mCaps = mImplementation->getCaps();
413 
414     mConfigSet = mImplementation->generateConfigs();
415     if (mConfigSet.size() == 0)
416     {
417         mImplementation->terminate();
418         return Error(EGL_NOT_INITIALIZED);
419     }
420 
421     initDisplayExtensions();
422     initVendorString();
423 
424     // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
425     if (mPlatform != EGL_PLATFORM_DEVICE_EXT)
426     {
427         if (mDisplayExtensions.deviceQuery)
428         {
429             rx::DeviceImpl *impl = nullptr;
430             ANGLE_TRY(mImplementation->getDevice(&impl));
431             ANGLE_TRY(Device::CreateDevice(this, impl, &mDevice));
432         }
433         else
434         {
435             mDevice = nullptr;
436         }
437     }
438     else
439     {
440         // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
441         // an external device
442         ASSERT(mDevice != nullptr);
443     }
444 
445     mInitialized = true;
446 
447     return egl::Error(EGL_SUCCESS);
448 }
449 
terminate()450 void Display::terminate()
451 {
452     makeCurrent(nullptr, nullptr, nullptr);
453 
454     while (!mContextSet.empty())
455     {
456         destroyContext(*mContextSet.begin());
457     }
458 
459     while (!mImageSet.empty())
460     {
461         destroyImage(*mImageSet.begin());
462     }
463 
464     while (!mStreamSet.empty())
465     {
466         destroyStream(*mStreamSet.begin());
467     }
468 
469     while (!mImplementation->getSurfaceSet().empty())
470     {
471         destroySurface(*mImplementation->getSurfaceSet().begin());
472     }
473 
474     mConfigSet.clear();
475 
476     if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
477     {
478         // Don't delete the device if it was created externally using eglCreateDeviceANGLE
479         // We also shouldn't set it to null in case eglInitialize() is called again later
480         SafeDelete(mDevice);
481     }
482 
483     mImplementation->terminate();
484 
485     mInitialized = false;
486 
487     // Never de-init default platform.. terminate is not that final.
488 }
489 
getConfigs(const egl::AttributeMap & attribs) const490 std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
491 {
492     return mConfigSet.filter(attribs);
493 }
494 
getConfigAttrib(const Config * configuration,EGLint attribute,EGLint * value)495 bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value)
496 {
497     switch (attribute)
498     {
499       case EGL_BUFFER_SIZE:               *value = configuration->bufferSize;             break;
500       case EGL_ALPHA_SIZE:                *value = configuration->alphaSize;              break;
501       case EGL_BLUE_SIZE:                 *value = configuration->blueSize;               break;
502       case EGL_GREEN_SIZE:                *value = configuration->greenSize;              break;
503       case EGL_RED_SIZE:                  *value = configuration->redSize;                break;
504       case EGL_DEPTH_SIZE:                *value = configuration->depthSize;              break;
505       case EGL_STENCIL_SIZE:              *value = configuration->stencilSize;            break;
506       case EGL_CONFIG_CAVEAT:             *value = configuration->configCaveat;           break;
507       case EGL_CONFIG_ID:                 *value = configuration->configID;               break;
508       case EGL_LEVEL:                     *value = configuration->level;                  break;
509       case EGL_NATIVE_RENDERABLE:         *value = configuration->nativeRenderable;       break;
510       case EGL_NATIVE_VISUAL_ID:          *value = configuration->nativeVisualID;         break;
511       case EGL_NATIVE_VISUAL_TYPE:        *value = configuration->nativeVisualType;       break;
512       case EGL_SAMPLES:                   *value = configuration->samples;                break;
513       case EGL_SAMPLE_BUFFERS:            *value = configuration->sampleBuffers;          break;
514       case EGL_SURFACE_TYPE:              *value = configuration->surfaceType;            break;
515       case EGL_TRANSPARENT_TYPE:          *value = configuration->transparentType;        break;
516       case EGL_TRANSPARENT_BLUE_VALUE:    *value = configuration->transparentBlueValue;   break;
517       case EGL_TRANSPARENT_GREEN_VALUE:   *value = configuration->transparentGreenValue;  break;
518       case EGL_TRANSPARENT_RED_VALUE:     *value = configuration->transparentRedValue;    break;
519       case EGL_BIND_TO_TEXTURE_RGB:       *value = configuration->bindToTextureRGB;       break;
520       case EGL_BIND_TO_TEXTURE_RGBA:      *value = configuration->bindToTextureRGBA;      break;
521       case EGL_MIN_SWAP_INTERVAL:         *value = configuration->minSwapInterval;        break;
522       case EGL_MAX_SWAP_INTERVAL:         *value = configuration->maxSwapInterval;        break;
523       case EGL_LUMINANCE_SIZE:            *value = configuration->luminanceSize;          break;
524       case EGL_ALPHA_MASK_SIZE:           *value = configuration->alphaMaskSize;          break;
525       case EGL_COLOR_BUFFER_TYPE:         *value = configuration->colorBufferType;        break;
526       case EGL_RENDERABLE_TYPE:           *value = configuration->renderableType;         break;
527       case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                break;
528       case EGL_CONFORMANT:                *value = configuration->conformant;             break;
529       case EGL_MAX_PBUFFER_WIDTH:         *value = configuration->maxPBufferWidth;        break;
530       case EGL_MAX_PBUFFER_HEIGHT:        *value = configuration->maxPBufferHeight;       break;
531       case EGL_MAX_PBUFFER_PIXELS:        *value = configuration->maxPBufferPixels;       break;
532 
533       case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
534           if (!getExtensions().surfaceOrientation)
535           {
536               return false;
537           }
538           *value = configuration->optimalOrientation;
539           break;
540 
541       default:
542         return false;
543     }
544 
545     return true;
546 }
547 
createWindowSurface(const Config * configuration,EGLNativeWindowType window,const AttributeMap & attribs,Surface ** outSurface)548 Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
549                                    Surface **outSurface)
550 {
551     if (mImplementation->testDeviceLost())
552     {
553         ANGLE_TRY(restoreLostDevice());
554     }
555 
556     std::unique_ptr<Surface> surface(
557         new WindowSurface(mImplementation, configuration, window, attribs));
558     ANGLE_TRY(surface->initialize());
559 
560     ASSERT(outSurface != nullptr);
561     *outSurface = surface.release();
562     mImplementation->getSurfaceSet().insert(*outSurface);
563 
564     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
565     ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
566     windowSurfaces->insert(std::make_pair(window, *outSurface));
567 
568     return egl::Error(EGL_SUCCESS);
569 }
570 
createPbufferSurface(const Config * configuration,const AttributeMap & attribs,Surface ** outSurface)571 Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface)
572 {
573     ASSERT(isInitialized());
574 
575     if (mImplementation->testDeviceLost())
576     {
577         ANGLE_TRY(restoreLostDevice());
578     }
579 
580     std::unique_ptr<Surface> surface(new PbufferSurface(mImplementation, configuration, attribs));
581     ANGLE_TRY(surface->initialize());
582 
583     ASSERT(outSurface != nullptr);
584     *outSurface = surface.release();
585     mImplementation->getSurfaceSet().insert(*outSurface);
586 
587     return egl::Error(EGL_SUCCESS);
588 }
589 
createPbufferFromClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,Surface ** outSurface)590 Error Display::createPbufferFromClientBuffer(const Config *configuration,
591                                              EGLenum buftype,
592                                              EGLClientBuffer clientBuffer,
593                                              const AttributeMap &attribs,
594                                              Surface **outSurface)
595 {
596     ASSERT(isInitialized());
597 
598     if (mImplementation->testDeviceLost())
599     {
600         ANGLE_TRY(restoreLostDevice());
601     }
602 
603     std::unique_ptr<Surface> surface(
604         new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs));
605     ANGLE_TRY(surface->initialize());
606 
607     ASSERT(outSurface != nullptr);
608     *outSurface = surface.release();
609     mImplementation->getSurfaceSet().insert(*outSurface);
610 
611     return egl::Error(EGL_SUCCESS);
612 }
613 
createPixmapSurface(const Config * configuration,NativePixmapType nativePixmap,const AttributeMap & attribs,Surface ** outSurface)614 Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
615                                    Surface **outSurface)
616 {
617     ASSERT(isInitialized());
618 
619     if (mImplementation->testDeviceLost())
620     {
621         ANGLE_TRY(restoreLostDevice());
622     }
623 
624     std::unique_ptr<Surface> surface(
625         new PixmapSurface(mImplementation, configuration, nativePixmap, attribs));
626     ANGLE_TRY(surface->initialize());
627 
628     ASSERT(outSurface != nullptr);
629     *outSurface = surface.release();
630     mImplementation->getSurfaceSet().insert(*outSurface);
631 
632     return egl::Error(EGL_SUCCESS);
633 }
634 
createImage(gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attribs,Image ** outImage)635 Error Display::createImage(gl::Context *context,
636                            EGLenum target,
637                            EGLClientBuffer buffer,
638                            const AttributeMap &attribs,
639                            Image **outImage)
640 {
641     ASSERT(isInitialized());
642 
643     if (mImplementation->testDeviceLost())
644     {
645         ANGLE_TRY(restoreLostDevice());
646     }
647 
648     egl::ImageSibling *sibling = nullptr;
649     if (IsTextureTarget(target))
650     {
651         sibling = context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
652     }
653     else if (IsRenderbufferTarget(target))
654     {
655         sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
656     }
657     else
658     {
659         UNREACHABLE();
660     }
661     ASSERT(sibling != nullptr);
662 
663     rx::ImageImpl *imageImpl = mImplementation->createImage(target, sibling, attribs);
664     ASSERT(imageImpl != nullptr);
665 
666     ANGLE_TRY(imageImpl->initialize());
667 
668     Image *image = new Image(imageImpl, target, sibling, attribs);
669 
670     ASSERT(outImage != nullptr);
671     *outImage = image;
672 
673     // Add this image to the list of all images and hold a ref to it.
674     image->addRef();
675     mImageSet.insert(image);
676 
677     return egl::Error(EGL_SUCCESS);
678 }
679 
createStream(const AttributeMap & attribs,Stream ** outStream)680 Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
681 {
682     ASSERT(isInitialized());
683 
684     Stream *stream = new Stream(this, attribs);
685 
686     ASSERT(stream != nullptr);
687     mStreamSet.insert(stream);
688 
689     ASSERT(outStream != nullptr);
690     *outStream = stream;
691 
692     return Error(EGL_SUCCESS);
693 }
694 
createContext(const Config * configuration,gl::Context * shareContext,const AttributeMap & attribs,gl::Context ** outContext)695 Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
696                              gl::Context **outContext)
697 {
698     ASSERT(isInitialized());
699 
700     if (mImplementation->testDeviceLost())
701     {
702         ANGLE_TRY(restoreLostDevice());
703     }
704 
705     gl::Context *context = new gl::Context(mImplementation, configuration, shareContext, attribs);
706 
707     ASSERT(context != nullptr);
708     mContextSet.insert(context);
709 
710     ASSERT(outContext != nullptr);
711     *outContext = context;
712     return egl::Error(EGL_SUCCESS);
713 }
714 
makeCurrent(egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)715 Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
716 {
717     ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
718 
719     if (context != nullptr && drawSurface != nullptr)
720     {
721         ASSERT(readSurface == drawSurface);
722         context->makeCurrent(drawSurface);
723     }
724 
725     return egl::Error(EGL_SUCCESS);
726 }
727 
restoreLostDevice()728 Error Display::restoreLostDevice()
729 {
730     for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
731     {
732         if ((*ctx)->isResetNotificationEnabled())
733         {
734             // If reset notifications have been requested, application must delete all contexts first
735             return Error(EGL_CONTEXT_LOST);
736         }
737     }
738 
739     return mImplementation->restoreLostDevice();
740 }
741 
destroySurface(Surface * surface)742 void Display::destroySurface(Surface *surface)
743 {
744     if (surface->getType() == EGL_WINDOW_BIT)
745     {
746         WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
747         ASSERT(windowSurfaces);
748 
749         bool surfaceRemoved = false;
750         for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++)
751         {
752             if (iter->second == surface)
753             {
754                 windowSurfaces->erase(iter);
755                 surfaceRemoved = true;
756                 break;
757             }
758         }
759 
760         ASSERT(surfaceRemoved);
761     }
762 
763     mImplementation->destroySurface(surface);
764 }
765 
destroyImage(egl::Image * image)766 void Display::destroyImage(egl::Image *image)
767 {
768     auto iter = mImageSet.find(image);
769     ASSERT(iter != mImageSet.end());
770     (*iter)->release();
771     mImageSet.erase(iter);
772 }
773 
destroyStream(egl::Stream * stream)774 void Display::destroyStream(egl::Stream *stream)
775 {
776     mStreamSet.erase(stream);
777     SafeDelete(stream);
778 }
779 
destroyContext(gl::Context * context)780 void Display::destroyContext(gl::Context *context)
781 {
782     mContextSet.erase(context);
783     SafeDelete(context);
784 }
785 
isDeviceLost() const786 bool Display::isDeviceLost() const
787 {
788     ASSERT(isInitialized());
789     return mDeviceLost;
790 }
791 
testDeviceLost()792 bool Display::testDeviceLost()
793 {
794     ASSERT(isInitialized());
795 
796     if (!mDeviceLost && mImplementation->testDeviceLost())
797     {
798         notifyDeviceLost();
799     }
800 
801     return mDeviceLost;
802 }
803 
notifyDeviceLost()804 void Display::notifyDeviceLost()
805 {
806     if (mDeviceLost)
807     {
808         return;
809     }
810 
811     for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
812     {
813         (*context)->markContextLost();
814     }
815 
816     mDeviceLost = true;
817 }
818 
waitClient() const819 Error Display::waitClient() const
820 {
821     return mImplementation->waitClient();
822 }
823 
waitNative(EGLint engine,egl::Surface * drawSurface,egl::Surface * readSurface) const824 Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const
825 {
826     return mImplementation->waitNative(engine, drawSurface, readSurface);
827 }
828 
getCaps() const829 const Caps &Display::getCaps() const
830 {
831     return mCaps;
832 }
833 
isInitialized() const834 bool Display::isInitialized() const
835 {
836     return mInitialized;
837 }
838 
isValidConfig(const Config * config) const839 bool Display::isValidConfig(const Config *config) const
840 {
841     return mConfigSet.contains(config);
842 }
843 
isValidContext(const gl::Context * context) const844 bool Display::isValidContext(const gl::Context *context) const
845 {
846     return mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end();
847 }
848 
isValidSurface(const Surface * surface) const849 bool Display::isValidSurface(const Surface *surface) const
850 {
851     return mImplementation->getSurfaceSet().find(const_cast<Surface *>(surface)) !=
852            mImplementation->getSurfaceSet().end();
853 }
854 
isValidImage(const Image * image) const855 bool Display::isValidImage(const Image *image) const
856 {
857     return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
858 }
859 
isValidStream(const Stream * stream) const860 bool Display::isValidStream(const Stream *stream) const
861 {
862     return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
863 }
864 
hasExistingWindowSurface(EGLNativeWindowType window)865 bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
866 {
867     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
868     ASSERT(windowSurfaces);
869 
870     return windowSurfaces->find(window) != windowSurfaces->end();
871 }
872 
GenerateClientExtensions()873 static ClientExtensions GenerateClientExtensions()
874 {
875     ClientExtensions extensions;
876 
877     extensions.clientExtensions = true;
878     extensions.platformBase = true;
879     extensions.platformANGLE = true;
880 
881 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
882     extensions.platformANGLED3D = true;
883     extensions.platformDevice   = true;
884 #endif
885 
886 #if defined(ANGLE_ENABLE_OPENGL)
887     extensions.platformANGLEOpenGL = true;
888 #endif
889 
890 #if defined(ANGLE_ENABLE_NULL)
891     extensions.platformANGLENULL = true;
892 #endif
893 
894 #if defined(ANGLE_ENABLE_D3D11)
895     extensions.deviceCreation      = true;
896     extensions.deviceCreationD3D11 = true;
897     extensions.experimentalPresentPath = true;
898 #endif
899 
900 #if defined(ANGLE_USE_X11)
901     extensions.x11Visual = true;
902 #endif
903 
904     extensions.clientGetAllProcAddresses = true;
905 
906     return extensions;
907 }
908 
909 template <typename T>
GenerateExtensionsString(const T & extensions)910 static std::string GenerateExtensionsString(const T &extensions)
911 {
912     std::vector<std::string> extensionsVector = extensions.getStrings();
913 
914     std::ostringstream stream;
915     std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " "));
916     return stream.str();
917 }
918 
getClientExtensions()919 const ClientExtensions &Display::getClientExtensions()
920 {
921     static const ClientExtensions clientExtensions = GenerateClientExtensions();
922     return clientExtensions;
923 }
924 
getClientExtensionString()925 const std::string &Display::getClientExtensionString()
926 {
927     static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions());
928     return clientExtensionsString;
929 }
930 
initDisplayExtensions()931 void Display::initDisplayExtensions()
932 {
933     mDisplayExtensions = mImplementation->getExtensions();
934 
935     // Some extensions are always available because they are implemented in the EGL layer.
936     mDisplayExtensions.createContext        = true;
937     mDisplayExtensions.createContextNoError = true;
938     mDisplayExtensions.createContextWebGLCompatibility = true;
939     mDisplayExtensions.createContextBindGeneratesResource = true;
940 
941     // Force EGL_KHR_get_all_proc_addresses on.
942     mDisplayExtensions.getAllProcAddresses = true;
943 
944     mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
945 }
946 
isValidNativeWindow(EGLNativeWindowType window) const947 bool Display::isValidNativeWindow(EGLNativeWindowType window) const
948 {
949     return mImplementation->isValidNativeWindow(window);
950 }
951 
validateClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs)952 Error Display::validateClientBuffer(const Config *configuration,
953                                     EGLenum buftype,
954                                     EGLClientBuffer clientBuffer,
955                                     const AttributeMap &attribs)
956 {
957     return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
958 }
959 
isValidDisplay(const egl::Display * display)960 bool Display::isValidDisplay(const egl::Display *display)
961 {
962     const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
963     for (const auto &displayPair : *anglePlatformDisplayMap)
964     {
965         if (displayPair.second == display)
966         {
967             return true;
968         }
969     }
970 
971     const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
972     for (const auto &displayPair : *devicePlatformDisplayMap)
973     {
974         if (displayPair.second == display)
975         {
976             return true;
977         }
978     }
979 
980     return false;
981 }
982 
isValidNativeDisplay(EGLNativeDisplayType display)983 bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
984 {
985     // TODO(jmadill): handle this properly
986     if (display == EGL_DEFAULT_DISPLAY)
987     {
988         return true;
989     }
990 
991 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_STORE)
992     if (display == EGL_SOFTWARE_DISPLAY_ANGLE ||
993         display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
994         display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
995     {
996         return true;
997     }
998     return (WindowFromDC(display) != NULL);
999 #else
1000     return true;
1001 #endif
1002 }
1003 
initVendorString()1004 void Display::initVendorString()
1005 {
1006     mVendorString = mImplementation->getVendorString();
1007 }
1008 
getExtensions() const1009 const DisplayExtensions &Display::getExtensions() const
1010 {
1011     return mDisplayExtensions;
1012 }
1013 
getExtensionString() const1014 const std::string &Display::getExtensionString() const
1015 {
1016     return mDisplayExtensionString;
1017 }
1018 
getVendorString() const1019 const std::string &Display::getVendorString() const
1020 {
1021     return mVendorString;
1022 }
1023 
getDevice() const1024 Device *Display::getDevice() const
1025 {
1026     return mDevice;
1027 }
1028 
getMaxSupportedESVersion() const1029 gl::Version Display::getMaxSupportedESVersion() const
1030 {
1031     return mImplementation->getMaxSupportedESVersion();
1032 }
1033 }
1034