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