• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // DisplayVk.cpp:
7 //    Implements the class methods for DisplayVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/DisplayVk.h"
11 
12 #include "common/debug.h"
13 #include "common/system_utils.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/renderer/vulkan/BufferVk.h"
17 #include "libANGLE/renderer/vulkan/ContextVk.h"
18 #include "libANGLE/renderer/vulkan/DeviceVk.h"
19 #include "libANGLE/renderer/vulkan/ImageVk.h"
20 #include "libANGLE/renderer/vulkan/RendererVk.h"
21 #include "libANGLE/renderer/vulkan/ShareGroupVk.h"
22 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
23 #include "libANGLE/renderer/vulkan/SyncVk.h"
24 #include "libANGLE/renderer/vulkan/TextureVk.h"
25 #include "libANGLE/renderer/vulkan/VkImageImageSiblingVk.h"
26 
27 namespace rx
28 {
29 
30 namespace
31 {
32 // Query surface format and colorspace support.
GetSupportedFormatColorspaces(VkPhysicalDevice physicalDevice,const angle::FeaturesVk & featuresVk,VkSurfaceKHR surface,std::vector<VkSurfaceFormat2KHR> * surfaceFormatsOut)33 void GetSupportedFormatColorspaces(VkPhysicalDevice physicalDevice,
34                                    const angle::FeaturesVk &featuresVk,
35                                    VkSurfaceKHR surface,
36                                    std::vector<VkSurfaceFormat2KHR> *surfaceFormatsOut)
37 {
38     ASSERT(surfaceFormatsOut);
39     surfaceFormatsOut->clear();
40 
41     constexpr VkSurfaceFormat2KHR kSurfaceFormat2Initializer = {
42         VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR,
43         nullptr,
44         {VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
45 
46     if (featuresVk.supportsSurfaceCapabilities2Extension.enabled)
47     {
48         VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2 = {};
49         surfaceInfo2.sType          = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
50         surfaceInfo2.surface        = surface;
51         uint32_t surfaceFormatCount = 0;
52 
53         // Query the count first
54         VkResult result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
55                                                                 &surfaceFormatCount, nullptr);
56         ASSERT(result == VK_SUCCESS);
57         ASSERT(surfaceFormatCount > 0);
58 
59         // Query the VkSurfaceFormat2KHR list
60         std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount,
61                                                          kSurfaceFormat2Initializer);
62         result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
63                                                        &surfaceFormatCount, surfaceFormats2.data());
64         ASSERT(result == VK_SUCCESS);
65 
66         *surfaceFormatsOut = std::move(surfaceFormats2);
67     }
68     else
69     {
70         uint32_t surfaceFormatCount = 0;
71         // Query the count first
72         VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
73                                                                &surfaceFormatCount, nullptr);
74         ASSERT(result == VK_SUCCESS);
75 
76         // Query the VkSurfaceFormatKHR list
77         std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
78         result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount,
79                                                       surfaceFormats.data());
80         ASSERT(result == VK_SUCCESS);
81 
82         // Copy over data from std::vector<VkSurfaceFormatKHR> to std::vector<VkSurfaceFormat2KHR>
83         std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount,
84                                                          kSurfaceFormat2Initializer);
85         for (size_t index = 0; index < surfaceFormatCount; index++)
86         {
87             surfaceFormats2[index].surfaceFormat.format = surfaceFormats[index].format;
88         }
89 
90         *surfaceFormatsOut = std::move(surfaceFormats2);
91     }
92 }
93 }  // namespace
94 
DisplayVk(const egl::DisplayState & state)95 DisplayVk::DisplayVk(const egl::DisplayState &state)
96     : DisplayImpl(state),
97       vk::Context(new RendererVk()),
98       mScratchBuffer(1000u),
99       mSupportedColorspaceFormatsMap{}
100 {}
101 
~DisplayVk()102 DisplayVk::~DisplayVk()
103 {
104     delete mRenderer;
105 }
106 
initialize(egl::Display * display)107 egl::Error DisplayVk::initialize(egl::Display *display)
108 {
109     ASSERT(mRenderer != nullptr && display != nullptr);
110     angle::Result result = mRenderer->initialize(this, display, getWSIExtension(), getWSILayer());
111     ANGLE_TRY(angle::ToEGL(result, EGL_NOT_INITIALIZED));
112     // Query and cache supported surface format and colorspace for later use.
113     initSupportedSurfaceFormatColorspaces();
114     return egl::NoError();
115 }
116 
terminate()117 void DisplayVk::terminate()
118 {
119     mRenderer->reloadVolkIfNeeded();
120 
121     ASSERT(mRenderer);
122     mRenderer->onDestroy(this);
123 }
124 
makeCurrent(egl::Display *,egl::Surface *,egl::Surface *,gl::Context *)125 egl::Error DisplayVk::makeCurrent(egl::Display * /*display*/,
126                                   egl::Surface * /*drawSurface*/,
127                                   egl::Surface * /*readSurface*/,
128                                   gl::Context * /*context*/)
129 {
130     // Ensure the appropriate global DebugAnnotator is used
131     ASSERT(mRenderer);
132     mRenderer->setGlobalDebugAnnotator();
133 
134     return egl::NoError();
135 }
136 
testDeviceLost()137 bool DisplayVk::testDeviceLost()
138 {
139     return mRenderer->isDeviceLost();
140 }
141 
restoreLostDevice(const egl::Display * display)142 egl::Error DisplayVk::restoreLostDevice(const egl::Display *display)
143 {
144     // A vulkan device cannot be restored, the entire renderer would have to be re-created along
145     // with any other EGL objects that reference it.
146     return egl::EglBadDisplay();
147 }
148 
getRendererDescription()149 std::string DisplayVk::getRendererDescription()
150 {
151     if (mRenderer)
152     {
153         return mRenderer->getRendererDescription();
154     }
155     return std::string();
156 }
157 
getVendorString()158 std::string DisplayVk::getVendorString()
159 {
160     if (mRenderer)
161     {
162         return mRenderer->getVendorString();
163     }
164     return std::string();
165 }
166 
getVersionString(bool includeFullVersion)167 std::string DisplayVk::getVersionString(bool includeFullVersion)
168 {
169     if (mRenderer)
170     {
171         return mRenderer->getVersionString(includeFullVersion);
172     }
173     return std::string();
174 }
175 
createDevice()176 DeviceImpl *DisplayVk::createDevice()
177 {
178     return new DeviceVk();
179 }
180 
waitClient(const gl::Context * context)181 egl::Error DisplayVk::waitClient(const gl::Context *context)
182 {
183     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
184     ContextVk *contextVk = vk::GetImpl(context);
185     return angle::ToEGL(contextVk->finishImpl(RenderPassClosureReason::EGLWaitClient),
186                         EGL_BAD_ACCESS);
187 }
188 
waitNative(const gl::Context * context,EGLint engine)189 egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine)
190 {
191     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitNative");
192     return angle::ResultToEGL(waitNativeImpl());
193 }
194 
waitNativeImpl()195 angle::Result DisplayVk::waitNativeImpl()
196 {
197     return angle::Result::Continue;
198 }
199 
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)200 SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
201                                             EGLNativeWindowType window,
202                                             const egl::AttributeMap &attribs)
203 {
204     return createWindowSurfaceVk(state, window);
205 }
206 
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)207 SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
208                                              const egl::AttributeMap &attribs)
209 {
210     ASSERT(mRenderer);
211     return new OffscreenSurfaceVk(state, mRenderer);
212 }
213 
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)214 SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
215                                                       EGLenum buftype,
216                                                       EGLClientBuffer clientBuffer,
217                                                       const egl::AttributeMap &attribs)
218 {
219     UNIMPLEMENTED();
220     return static_cast<SurfaceImpl *>(0);
221 }
222 
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)223 SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
224                                             NativePixmapType nativePixmap,
225                                             const egl::AttributeMap &attribs)
226 {
227     UNIMPLEMENTED();
228     return static_cast<SurfaceImpl *>(0);
229 }
230 
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)231 ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
232                                   const gl::Context *context,
233                                   EGLenum target,
234                                   const egl::AttributeMap &attribs)
235 {
236     return new ImageVk(state, context);
237 }
238 
createShareGroup(const egl::ShareGroupState & state)239 ShareGroupImpl *DisplayVk::createShareGroup(const egl::ShareGroupState &state)
240 {
241     return new ShareGroupVk(state);
242 }
243 
isConfigFormatSupported(VkFormat format) const244 bool DisplayVk::isConfigFormatSupported(VkFormat format) const
245 {
246     // Requires VK_GOOGLE_surfaceless_query extension to be supported.
247     ASSERT(mRenderer->getFeatures().supportsSurfacelessQueryExtension.enabled);
248 
249     // A format is considered supported if it is supported in atleast 1 colorspace.
250     using ColorspaceFormatSetItem =
251         const std::pair<const VkColorSpaceKHR, std::unordered_set<VkFormat>>;
252     for (ColorspaceFormatSetItem &colorspaceFormatSetItem : mSupportedColorspaceFormatsMap)
253     {
254         if (colorspaceFormatSetItem.second.count(format) > 0)
255         {
256             return true;
257         }
258     }
259 
260     return false;
261 }
262 
isSurfaceFormatColorspacePairSupported(VkSurfaceKHR surface,VkFormat format,VkColorSpaceKHR colorspace) const263 bool DisplayVk::isSurfaceFormatColorspacePairSupported(VkSurfaceKHR surface,
264                                                        VkFormat format,
265                                                        VkColorSpaceKHR colorspace) const
266 {
267     if (mSupportedColorspaceFormatsMap.size() > 0)
268     {
269         return mSupportedColorspaceFormatsMap.count(colorspace) > 0 &&
270                mSupportedColorspaceFormatsMap.at(colorspace).count(format) > 0;
271     }
272     else
273     {
274         const angle::FeaturesVk &featuresVk = mRenderer->getFeatures();
275         std::vector<VkSurfaceFormat2KHR> surfaceFormats;
276         GetSupportedFormatColorspaces(mRenderer->getPhysicalDevice(), featuresVk, surface,
277                                       &surfaceFormats);
278 
279         if (!featuresVk.supportsSurfaceCapabilities2Extension.enabled)
280         {
281             if (surfaceFormats.size() == 1u &&
282                 surfaceFormats[0].surfaceFormat.format == VK_FORMAT_UNDEFINED)
283             {
284                 return true;
285             }
286         }
287 
288         for (const VkSurfaceFormat2KHR &surfaceFormat : surfaceFormats)
289         {
290             if (surfaceFormat.surfaceFormat.format == format &&
291                 surfaceFormat.surfaceFormat.colorSpace == colorspace)
292             {
293                 return true;
294             }
295         }
296     }
297 
298     return false;
299 }
300 
isColorspaceSupported(VkColorSpaceKHR colorspace) const301 bool DisplayVk::isColorspaceSupported(VkColorSpaceKHR colorspace) const
302 {
303     return mSupportedColorspaceFormatsMap.count(colorspace) > 0;
304 }
305 
initSupportedSurfaceFormatColorspaces()306 void DisplayVk::initSupportedSurfaceFormatColorspaces()
307 {
308     const angle::FeaturesVk &featuresVk = mRenderer->getFeatures();
309     if (featuresVk.supportsSurfacelessQueryExtension.enabled &&
310         featuresVk.supportsSurfaceCapabilities2Extension.enabled)
311     {
312         // Use the VK_GOOGLE_surfaceless_query extension to query supported surface formats and
313         // colorspaces by using a VK_NULL_HANDLE for the VkSurfaceKHR handle.
314         std::vector<VkSurfaceFormat2KHR> surfaceFormats;
315         GetSupportedFormatColorspaces(mRenderer->getPhysicalDevice(), featuresVk, VK_NULL_HANDLE,
316                                       &surfaceFormats);
317         for (const VkSurfaceFormat2KHR &surfaceFormat : surfaceFormats)
318         {
319             // Cache supported VkFormat and VkColorSpaceKHR for later use
320             VkFormat format            = surfaceFormat.surfaceFormat.format;
321             VkColorSpaceKHR colorspace = surfaceFormat.surfaceFormat.colorSpace;
322 
323             ASSERT(format != VK_FORMAT_UNDEFINED);
324 
325             mSupportedColorspaceFormatsMap[colorspace].insert(format);
326         }
327 
328         ASSERT(mSupportedColorspaceFormatsMap.size() > 0);
329     }
330     else
331     {
332         mSupportedColorspaceFormatsMap.clear();
333     }
334 }
335 
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)336 ContextImpl *DisplayVk::createContext(const gl::State &state,
337                                       gl::ErrorSet *errorSet,
338                                       const egl::Config *configuration,
339                                       const gl::Context *shareContext,
340                                       const egl::AttributeMap &attribs)
341 {
342     return new ContextVk(state, errorSet, mRenderer);
343 }
344 
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)345 StreamProducerImpl *DisplayVk::createStreamProducerD3DTexture(
346     egl::Stream::ConsumerType consumerType,
347     const egl::AttributeMap &attribs)
348 {
349     UNIMPLEMENTED();
350     return static_cast<StreamProducerImpl *>(0);
351 }
352 
createSync(const egl::AttributeMap & attribs)353 EGLSyncImpl *DisplayVk::createSync(const egl::AttributeMap &attribs)
354 {
355     return new EGLSyncVk(attribs);
356 }
357 
getMaxSupportedESVersion() const358 gl::Version DisplayVk::getMaxSupportedESVersion() const
359 {
360     return mRenderer->getMaxSupportedESVersion();
361 }
362 
getMaxConformantESVersion() const363 gl::Version DisplayVk::getMaxConformantESVersion() const
364 {
365     return mRenderer->getMaxConformantESVersion();
366 }
367 
getMaxSupportedDesktopVersion() const368 Optional<gl::Version> DisplayVk::getMaxSupportedDesktopVersion() const
369 {
370     return gl::Version{4, 6};
371 }
372 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const373 egl::Error DisplayVk::validateImageClientBuffer(const gl::Context *context,
374                                                 EGLenum target,
375                                                 EGLClientBuffer clientBuffer,
376                                                 const egl::AttributeMap &attribs) const
377 {
378     switch (target)
379     {
380         case EGL_VULKAN_IMAGE_ANGLE:
381         {
382             VkImage *vkImage = reinterpret_cast<VkImage *>(clientBuffer);
383             if (!vkImage || *vkImage == VK_NULL_HANDLE)
384             {
385                 return egl::EglBadParameter() << "clientBuffer is invalid.";
386             }
387 
388             GLenum internalFormat =
389                 static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_NONE));
390             switch (internalFormat)
391             {
392                 case GL_RGBA:
393                 case GL_BGRA_EXT:
394                 case GL_RGB:
395                 case GL_RED_EXT:
396                 case GL_RG_EXT:
397                 case GL_RGB10_A2_EXT:
398                 case GL_R16_EXT:
399                 case GL_RG16_EXT:
400                 case GL_NONE:
401                     break;
402                 default:
403                     return egl::EglBadParameter() << "Invalid EGLImage texture internal format: 0x"
404                                                   << std::hex << internalFormat;
405             }
406 
407             uint64_t hi = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE));
408             uint64_t lo = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE));
409             uint64_t info = ((hi & 0xffffffff) << 32) | (lo & 0xffffffff);
410             if (reinterpret_cast<const VkImageCreateInfo *>(info)->sType !=
411                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
412             {
413                 return egl::EglBadParameter()
414                        << "EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE and "
415                           "EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE are not pointing to a "
416                           "valid VkImageCreateInfo structure.";
417             }
418 
419             return egl::NoError();
420         }
421         default:
422             return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
423     }
424 }
425 
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)426 ExternalImageSiblingImpl *DisplayVk::createExternalImageSibling(const gl::Context *context,
427                                                                 EGLenum target,
428                                                                 EGLClientBuffer buffer,
429                                                                 const egl::AttributeMap &attribs)
430 {
431     switch (target)
432     {
433         case EGL_VULKAN_IMAGE_ANGLE:
434             return new VkImageImageSiblingVk(buffer, attribs);
435         default:
436             return DisplayImpl::createExternalImageSibling(context, target, buffer, attribs);
437     }
438 }
439 
generateExtensions(egl::DisplayExtensions * outExtensions) const440 void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
441 {
442     outExtensions->createContextRobustness    = getRenderer()->getNativeExtensions().robustnessEXT;
443     outExtensions->surfaceOrientation         = true;
444     outExtensions->displayTextureShareGroup   = true;
445     outExtensions->displaySemaphoreShareGroup = true;
446     outExtensions->robustResourceInitializationANGLE = true;
447 
448     // The Vulkan implementation will always say that EGL_KHR_swap_buffers_with_damage is supported.
449     // When the Vulkan driver supports VK_KHR_incremental_present, it will use it.  Otherwise, it
450     // will ignore the hint and do a regular swap.
451     outExtensions->swapBuffersWithDamage = true;
452 
453     outExtensions->fenceSync = true;
454     outExtensions->waitSync  = true;
455 
456     outExtensions->image                 = true;
457     outExtensions->imageBase             = true;
458     outExtensions->imagePixmap           = false;  // ANGLE does not support pixmaps
459     outExtensions->glTexture2DImage      = true;
460     outExtensions->glTextureCubemapImage = true;
461     outExtensions->glTexture3DImage =
462         getRenderer()->getFeatures().supportsSampler2dViewOf3d.enabled;
463     outExtensions->glRenderbufferImage = true;
464     outExtensions->imageNativeBuffer =
465         getRenderer()->getFeatures().supportsAndroidHardwareBuffer.enabled;
466     outExtensions->surfacelessContext = true;
467     outExtensions->glColorspace       = true;
468     outExtensions->imageGlColorspace =
469         outExtensions->glColorspace && getRenderer()->getFeatures().supportsImageFormatList.enabled;
470 
471 #if defined(ANGLE_PLATFORM_ANDROID)
472     outExtensions->getNativeClientBufferANDROID = true;
473     outExtensions->framebufferTargetANDROID     = true;
474 #endif  // defined(ANGLE_PLATFORM_ANDROID)
475 
476     // EGL_EXT_image_dma_buf_import is only exposed if EGL_EXT_image_dma_buf_import_modifiers can
477     // also be exposed.  The Vulkan extensions that support these EGL extensions are not split in
478     // the same way; both Vulkan extensions are needed for EGL_EXT_image_dma_buf_import, and with
479     // both Vulkan extensions, EGL_EXT_image_dma_buf_import_modifiers is also supportable.
480     outExtensions->imageDmaBufImportEXT =
481         getRenderer()->getFeatures().supportsExternalMemoryDmaBufAndModifiers.enabled;
482     outExtensions->imageDmaBufImportModifiersEXT = outExtensions->imageDmaBufImportEXT;
483 
484     // Disable context priority when non-zero memory init is enabled. This enforces a queue order.
485     outExtensions->contextPriority = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
486     outExtensions->noConfigContext = true;
487 
488 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
489     outExtensions->nativeFenceSyncANDROID =
490         getRenderer()->getFeatures().supportsAndroidNativeFenceSync.enabled;
491 #endif  // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
492 
493 #if defined(ANGLE_PLATFORM_GGP)
494     outExtensions->ggpStreamDescriptor = true;
495     outExtensions->swapWithFrameToken  = getRenderer()->getFeatures().supportsGGPFrameToken.enabled;
496 #endif  // defined(ANGLE_PLATFORM_GGP)
497 
498     outExtensions->bufferAgeEXT = true;
499 
500     outExtensions->protectedContentEXT =
501         (getRenderer()->getFeatures().supportsProtectedMemory.enabled &&
502          getRenderer()->getFeatures().supportsSurfaceProtectedSwapchains.enabled);
503 
504     outExtensions->createSurfaceSwapIntervalANGLE = true;
505 
506     outExtensions->mutableRenderBufferKHR =
507         getRenderer()->getFeatures().supportsSharedPresentableImageExtension.enabled;
508 
509     outExtensions->vulkanImageANGLE = true;
510 
511     outExtensions->lockSurface3KHR =
512         getRenderer()->getFeatures().supportsLockSurfaceExtension.enabled;
513 
514     outExtensions->partialUpdateKHR = true;
515 
516     outExtensions->timestampSurfaceAttributeANGLE =
517         getRenderer()->getFeatures().supportsTimestampSurfaceAttribute.enabled;
518 
519     outExtensions->eglColorspaceAttributePassthroughANGLE =
520         outExtensions->glColorspace &&
521         getRenderer()->getFeatures().eglColorspaceAttributePassthrough.enabled;
522 
523     // If EGL_KHR_gl_colorspace extension is supported check if other colorspace extensions
524     // can be supported as well.
525     if (outExtensions->glColorspace)
526     {
527         if (isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT))
528         {
529             outExtensions->glColorspaceDisplayP3            = true;
530             outExtensions->glColorspaceDisplayP3Passthrough = true;
531         }
532 
533         outExtensions->glColorspaceDisplayP3Linear =
534             isColorspaceSupported(VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT);
535         outExtensions->glColorspaceScrgb =
536             isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT);
537         outExtensions->glColorspaceScrgbLinear =
538             isColorspaceSupported(VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT);
539     }
540 }
541 
generateCaps(egl::Caps * outCaps) const542 void DisplayVk::generateCaps(egl::Caps *outCaps) const
543 {
544     outCaps->textureNPOT = true;
545     outCaps->stencil8    = getRenderer()->getNativeExtensions().textureStencil8OES;
546 }
547 
getWSILayer() const548 const char *DisplayVk::getWSILayer() const
549 {
550     return nullptr;
551 }
552 
isUsingSwapchain() const553 bool DisplayVk::isUsingSwapchain() const
554 {
555     return true;
556 }
557 
getScratchBuffer(size_t requstedSizeBytes,angle::MemoryBuffer ** scratchBufferOut) const558 bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes,
559                                  angle::MemoryBuffer **scratchBufferOut) const
560 {
561     return mScratchBuffer.get(requstedSizeBytes, scratchBufferOut);
562 }
563 
handleError(VkResult result,const char * file,const char * function,unsigned int line)564 void DisplayVk::handleError(VkResult result,
565                             const char *file,
566                             const char *function,
567                             unsigned int line)
568 {
569     ASSERT(result != VK_SUCCESS);
570 
571     std::stringstream errorStream;
572     errorStream << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
573                 << ", in " << file << ", " << function << ":" << line << ".";
574     std::string errorString = errorStream.str();
575 
576     if (result == VK_ERROR_DEVICE_LOST)
577     {
578         WARN() << errorString;
579         mRenderer->notifyDeviceLost();
580     }
581 
582     // Note: the errorCode will be set later in angle::ToEGL where it's available.
583     *egl::Display::GetCurrentThreadErrorScratchSpace() = egl::Error(0, 0, std::move(errorString));
584 }
585 
initializeFrontendFeatures(angle::FrontendFeatures * features) const586 void DisplayVk::initializeFrontendFeatures(angle::FrontendFeatures *features) const
587 {
588     mRenderer->initializeFrontendFeatures(features);
589 }
590 
populateFeatureList(angle::FeatureList * features)591 void DisplayVk::populateFeatureList(angle::FeatureList *features)
592 {
593     mRenderer->getFeatures().populateFeatureList(features);
594 }
595 }  // namespace rx
596