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