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 "libANGLE/Context.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 #include "libANGLE/renderer/vulkan/ImageVk.h"
17 #include "libANGLE/renderer/vulkan/RendererVk.h"
18 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
19 #include "libANGLE/renderer/vulkan/SyncVk.h"
20 #include "libANGLE/trace.h"
21 
22 namespace rx
23 {
24 
DisplayVk(const egl::DisplayState & state)25 DisplayVk::DisplayVk(const egl::DisplayState &state)
26     : DisplayImpl(state), vk::Context(new RendererVk()), mScratchBuffer(1000u)
27 {}
28 
~DisplayVk()29 DisplayVk::~DisplayVk()
30 {
31     delete mRenderer;
32 }
33 
initialize(egl::Display * display)34 egl::Error DisplayVk::initialize(egl::Display *display)
35 {
36     ASSERT(mRenderer != nullptr && display != nullptr);
37     angle::Result result = mRenderer->initialize(this, display, getWSIExtension(), getWSILayer());
38     ANGLE_TRY(angle::ToEGL(result, this, EGL_NOT_INITIALIZED));
39     return egl::NoError();
40 }
41 
terminate()42 void DisplayVk::terminate()
43 {
44     mRenderer->reloadVolkIfNeeded();
45 
46     ASSERT(mRenderer);
47     mRenderer->onDestroy();
48 }
49 
makeCurrent(egl::Surface *,egl::Surface *,gl::Context *)50 egl::Error DisplayVk::makeCurrent(egl::Surface * /*drawSurface*/,
51                                   egl::Surface * /*readSurface*/,
52                                   gl::Context * /*context*/)
53 {
54     return egl::NoError();
55 }
56 
testDeviceLost()57 bool DisplayVk::testDeviceLost()
58 {
59     return mRenderer->isDeviceLost();
60 }
61 
restoreLostDevice(const egl::Display * display)62 egl::Error DisplayVk::restoreLostDevice(const egl::Display *display)
63 {
64     // A vulkan device cannot be restored, the entire renderer would have to be re-created along
65     // with any other EGL objects that reference it.
66     return egl::EglBadDisplay();
67 }
68 
getVendorString() const69 std::string DisplayVk::getVendorString() const
70 {
71     std::string vendorString = "Google Inc.";
72     if (mRenderer)
73     {
74         vendorString += " " + mRenderer->getVendorString();
75     }
76 
77     return vendorString;
78 }
79 
createDevice()80 DeviceImpl *DisplayVk::createDevice()
81 {
82     UNIMPLEMENTED();
83     return nullptr;
84 }
85 
waitClient(const gl::Context * context)86 egl::Error DisplayVk::waitClient(const gl::Context *context)
87 {
88     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
89     ContextVk *contextVk = vk::GetImpl(context);
90     return angle::ToEGL(contextVk->finishImpl(), this, EGL_BAD_ACCESS);
91 }
92 
waitNative(const gl::Context * context,EGLint engine)93 egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine)
94 {
95     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitNative");
96     return angle::ResultToEGL(waitNativeImpl());
97 }
98 
waitNativeImpl()99 angle::Result DisplayVk::waitNativeImpl()
100 {
101     return angle::Result::Continue;
102 }
103 
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)104 SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
105                                             EGLNativeWindowType window,
106                                             const egl::AttributeMap &attribs)
107 {
108     return createWindowSurfaceVk(state, window);
109 }
110 
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)111 SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
112                                              const egl::AttributeMap &attribs)
113 {
114     ASSERT(mRenderer);
115     return new OffscreenSurfaceVk(state);
116 }
117 
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)118 SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
119                                                       EGLenum buftype,
120                                                       EGLClientBuffer clientBuffer,
121                                                       const egl::AttributeMap &attribs)
122 {
123     UNIMPLEMENTED();
124     return static_cast<SurfaceImpl *>(0);
125 }
126 
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)127 SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
128                                             NativePixmapType nativePixmap,
129                                             const egl::AttributeMap &attribs)
130 {
131     UNIMPLEMENTED();
132     return static_cast<SurfaceImpl *>(0);
133 }
134 
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)135 ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
136                                   const gl::Context *context,
137                                   EGLenum target,
138                                   const egl::AttributeMap &attribs)
139 {
140     return new ImageVk(state, context);
141 }
142 
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)143 rx::ContextImpl *DisplayVk::createContext(const gl::State &state,
144                                           gl::ErrorSet *errorSet,
145                                           const egl::Config *configuration,
146                                           const gl::Context *shareContext,
147                                           const egl::AttributeMap &attribs)
148 {
149     return new ContextVk(state, errorSet, mRenderer);
150 }
151 
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)152 StreamProducerImpl *DisplayVk::createStreamProducerD3DTexture(
153     egl::Stream::ConsumerType consumerType,
154     const egl::AttributeMap &attribs)
155 {
156     UNIMPLEMENTED();
157     return static_cast<StreamProducerImpl *>(0);
158 }
159 
createSync(const egl::AttributeMap & attribs)160 EGLSyncImpl *DisplayVk::createSync(const egl::AttributeMap &attribs)
161 {
162     return new EGLSyncVk(attribs);
163 }
164 
getMaxSupportedESVersion() const165 gl::Version DisplayVk::getMaxSupportedESVersion() const
166 {
167     return mRenderer->getMaxSupportedESVersion();
168 }
169 
getMaxConformantESVersion() const170 gl::Version DisplayVk::getMaxConformantESVersion() const
171 {
172     return mRenderer->getMaxConformantESVersion();
173 }
174 
generateExtensions(egl::DisplayExtensions * outExtensions) const175 void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
176 {
177     outExtensions->createContextRobustness      = getRenderer()->getNativeExtensions().robustness;
178     outExtensions->surfaceOrientation           = true;
179     outExtensions->displayTextureShareGroup     = true;
180     outExtensions->robustResourceInitialization = true;
181 
182     // The Vulkan implementation will always say that EGL_KHR_swap_buffers_with_damage is supported.
183     // When the Vulkan driver supports VK_KHR_incremental_present, it will use it.  Otherwise, it
184     // will ignore the hint and do a regular swap.
185     outExtensions->swapBuffersWithDamage = true;
186 
187     outExtensions->fenceSync = true;
188     outExtensions->waitSync  = true;
189 
190     outExtensions->image                 = true;
191     outExtensions->imageBase             = true;
192     outExtensions->imagePixmap           = false;  // ANGLE does not support pixmaps
193     outExtensions->glTexture2DImage      = true;
194     outExtensions->glTextureCubemapImage = true;
195     outExtensions->glTexture3DImage      = false;
196     outExtensions->glRenderbufferImage   = true;
197     outExtensions->imageNativeBuffer =
198         getRenderer()->getFeatures().supportsAndroidHardwareBuffer.enabled;
199     outExtensions->surfacelessContext = true;
200     outExtensions->glColorspace = getRenderer()->getFeatures().supportsSwapchainColorspace.enabled;
201 
202 #if defined(ANGLE_PLATFORM_ANDROID)
203     outExtensions->framebufferTargetANDROID = true;
204 #endif  // defined(ANGLE_PLATFORM_ANDROID)
205 
206     // Disable context priority when non-zero memory init is enabled. This enforces a queue order.
207     outExtensions->contextPriority = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
208     outExtensions->noConfigContext = true;
209 
210 #if defined(ANGLE_PLATFORM_GGP)
211     outExtensions->ggpStreamDescriptor = true;
212     outExtensions->swapWithFrameToken  = true;
213 #endif  // defined(ANGLE_PLATFORM_GGP)
214 }
215 
generateCaps(egl::Caps * outCaps) const216 void DisplayVk::generateCaps(egl::Caps *outCaps) const
217 {
218     outCaps->textureNPOT = true;
219 }
220 
getWSILayer() const221 const char *DisplayVk::getWSILayer() const
222 {
223     return nullptr;
224 }
225 
getScratchBuffer(size_t requstedSizeBytes,angle::MemoryBuffer ** scratchBufferOut) const226 bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes,
227                                  angle::MemoryBuffer **scratchBufferOut) const
228 {
229     return mScratchBuffer.get(requstedSizeBytes, scratchBufferOut);
230 }
231 
handleError(VkResult result,const char * file,const char * function,unsigned int line)232 void DisplayVk::handleError(VkResult result,
233                             const char *file,
234                             const char *function,
235                             unsigned int line)
236 {
237     ASSERT(result != VK_SUCCESS);
238 
239     std::stringstream errorStream;
240     errorStream << "Internal Vulkan error: " << VulkanResultString(result) << ", in " << file
241                 << ", " << function << ":" << line << ".";
242     mStoredErrorString = errorStream.str();
243 
244     if (result == VK_ERROR_DEVICE_LOST)
245     {
246         WARN() << mStoredErrorString;
247         mRenderer->notifyDeviceLost();
248     }
249 }
250 
251 // TODO(jmadill): Remove this. http://anglebug.com/3041
getEGLError(EGLint errorCode)252 egl::Error DisplayVk::getEGLError(EGLint errorCode)
253 {
254     return egl::Error(errorCode, 0, std::move(mStoredErrorString));
255 }
256 
populateFeatureList(angle::FeatureList * features)257 void DisplayVk::populateFeatureList(angle::FeatureList *features)
258 {
259     mRenderer->getFeatures().populateFeatureList(features);
260 }
261 
262 }  // namespace rx
263