• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 // RendererGL.cpp: Implements the class methods for RendererGL.
8 
9 #include "libANGLE/renderer/gl/RendererGL.h"
10 
11 #include <EGL/eglext.h>
12 
13 #include "common/debug.h"
14 #include "libANGLE/AttributeMap.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/Path.h"
18 #include "libANGLE/State.h"
19 #include "libANGLE/Surface.h"
20 #include "libANGLE/renderer/gl/BlitGL.h"
21 #include "libANGLE/renderer/gl/BufferGL.h"
22 #include "libANGLE/renderer/gl/ClearMultiviewGL.h"
23 #include "libANGLE/renderer/gl/CompilerGL.h"
24 #include "libANGLE/renderer/gl/ContextGL.h"
25 #include "libANGLE/renderer/gl/DisplayGL.h"
26 #include "libANGLE/renderer/gl/FenceNVGL.h"
27 #include "libANGLE/renderer/gl/FramebufferGL.h"
28 #include "libANGLE/renderer/gl/FunctionsGL.h"
29 #include "libANGLE/renderer/gl/PathGL.h"
30 #include "libANGLE/renderer/gl/ProgramGL.h"
31 #include "libANGLE/renderer/gl/QueryGL.h"
32 #include "libANGLE/renderer/gl/RenderbufferGL.h"
33 #include "libANGLE/renderer/gl/SamplerGL.h"
34 #include "libANGLE/renderer/gl/ShaderGL.h"
35 #include "libANGLE/renderer/gl/StateManagerGL.h"
36 #include "libANGLE/renderer/gl/SurfaceGL.h"
37 #include "libANGLE/renderer/gl/SyncGL.h"
38 #include "libANGLE/renderer/gl/TextureGL.h"
39 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
40 #include "libANGLE/renderer/gl/VertexArrayGL.h"
41 #include "libANGLE/renderer/gl/renderergl_utils.h"
42 #include "libANGLE/renderer/renderer_utils.h"
43 
44 namespace
45 {
46 
GatherPaths(const std::vector<gl::Path * > & paths)47 std::vector<GLuint> GatherPaths(const std::vector<gl::Path *> &paths)
48 {
49     std::vector<GLuint> ret;
50     ret.reserve(paths.size());
51 
52     for (const auto *p : paths)
53     {
54         const auto *pathObj = rx::GetImplAs<rx::PathGL>(p);
55         ret.push_back(pathObj->getPathID());
56     }
57     return ret;
58 }
59 
SetMaxShaderCompilerThreads(const rx::FunctionsGL * functions,GLuint count)60 void SetMaxShaderCompilerThreads(const rx::FunctionsGL *functions, GLuint count)
61 {
62     if (functions->maxShaderCompilerThreadsKHR != nullptr)
63     {
64         functions->maxShaderCompilerThreadsKHR(count);
65     }
66     else
67     {
68         ASSERT(functions->maxShaderCompilerThreadsARB != nullptr);
69         functions->maxShaderCompilerThreadsARB(count);
70     }
71 }
72 
73 #if defined(ANGLE_PLATFORM_ANDROID)
74 const char *kIgnoredErrors[] = {
75     // Wrong error message on Android Q Pixel 2. http://anglebug.com/3491
76     "FreeAllocationOnTimestamp - Reference to buffer created from "
77     "different context without a share list. Application failed to pass "
78     "share_context to eglCreateContext. Results are undefined.",
79 };
80 #endif  // defined(ANGLE_PLATFORM_ANDROID)
81 }  // namespace
82 
LogGLDebugMessage(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)83 static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source,
84                                                    GLenum type,
85                                                    GLuint id,
86                                                    GLenum severity,
87                                                    GLsizei length,
88                                                    const GLchar *message,
89                                                    const void *userParam)
90 {
91     std::string sourceText;
92     switch (source)
93     {
94         case GL_DEBUG_SOURCE_API:
95             sourceText = "OpenGL";
96             break;
97         case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
98             sourceText = "Windows";
99             break;
100         case GL_DEBUG_SOURCE_SHADER_COMPILER:
101             sourceText = "Shader Compiler";
102             break;
103         case GL_DEBUG_SOURCE_THIRD_PARTY:
104             sourceText = "Third Party";
105             break;
106         case GL_DEBUG_SOURCE_APPLICATION:
107             sourceText = "Application";
108             break;
109         case GL_DEBUG_SOURCE_OTHER:
110             sourceText = "Other";
111             break;
112         default:
113             sourceText = "UNKNOWN";
114             break;
115     }
116 
117     std::string typeText;
118     switch (type)
119     {
120         case GL_DEBUG_TYPE_ERROR:
121             typeText = "Error";
122             break;
123         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
124             typeText = "Deprecated behavior";
125             break;
126         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
127             typeText = "Undefined behavior";
128             break;
129         case GL_DEBUG_TYPE_PORTABILITY:
130             typeText = "Portability";
131             break;
132         case GL_DEBUG_TYPE_PERFORMANCE:
133             typeText = "Performance";
134             break;
135         case GL_DEBUG_TYPE_OTHER:
136             typeText = "Other";
137             break;
138         case GL_DEBUG_TYPE_MARKER:
139             typeText = "Marker";
140             break;
141         default:
142             typeText = "UNKNOWN";
143             break;
144     }
145 
146     std::string severityText;
147     switch (severity)
148     {
149         case GL_DEBUG_SEVERITY_HIGH:
150             severityText = "High";
151             break;
152         case GL_DEBUG_SEVERITY_MEDIUM:
153             severityText = "Medium";
154             break;
155         case GL_DEBUG_SEVERITY_LOW:
156             severityText = "Low";
157             break;
158         case GL_DEBUG_SEVERITY_NOTIFICATION:
159             severityText = "Notification";
160             break;
161         default:
162             severityText = "UNKNOWN";
163             break;
164     }
165 
166 #if defined(ANGLE_PLATFORM_ANDROID)
167     if (type == GL_DEBUG_TYPE_ERROR)
168     {
169         for (const char *&err : kIgnoredErrors)
170         {
171             if (strncmp(err, message, length) == 0)
172             {
173                 // There is only one ignored message right now and it is quite spammy, around 3MB
174                 // for a complete end2end tests run, so don't print it even as a warning.
175                 return;
176             }
177         }
178     }
179 #endif  // defined(ANGLE_PLATFORM_ANDROID)
180 
181     if (type == GL_DEBUG_TYPE_ERROR)
182     {
183         ERR() << std::endl
184               << "\tSource: " << sourceText << std::endl
185               << "\tType: " << typeText << std::endl
186               << "\tID: " << gl::FmtHex(id) << std::endl
187               << "\tSeverity: " << severityText << std::endl
188               << "\tMessage: " << message;
189     }
190     else if (type != GL_DEBUG_TYPE_PERFORMANCE)
191     {
192         // Don't print performance warnings. They tend to be very spammy in the dEQP test suite and
193         // there is very little we can do about them.
194 
195         // TODO(ynovikov): filter into WARN and INFO if INFO is ever implemented
196         WARN() << std::endl
197                << "\tSource: " << sourceText << std::endl
198                << "\tType: " << typeText << std::endl
199                << "\tID: " << gl::FmtHex(id) << std::endl
200                << "\tSeverity: " << severityText << std::endl
201                << "\tMessage: " << message;
202     }
203 }
204 
205 namespace rx
206 {
207 
RendererGL(std::unique_ptr<FunctionsGL> functions,const egl::AttributeMap & attribMap,DisplayGL * display)208 RendererGL::RendererGL(std::unique_ptr<FunctionsGL> functions,
209                        const egl::AttributeMap &attribMap,
210                        DisplayGL *display)
211     : mMaxSupportedESVersion(0, 0),
212       mFunctions(std::move(functions)),
213       mStateManager(nullptr),
214       mBlitter(nullptr),
215       mMultiviewClearer(nullptr),
216       mUseDebugOutput(false),
217       mCapsInitialized(false),
218       mMultiviewImplementationType(MultiviewImplementationTypeGL::UNSPECIFIED),
219       mNativeParallelCompileEnabled(false)
220 {
221     ASSERT(mFunctions);
222     nativegl_gl::InitializeFeatures(mFunctions.get(), &mFeatures);
223     OverrideFeaturesWithDisplayState(&mFeatures, display->getState());
224     mStateManager =
225         new StateManagerGL(mFunctions.get(), getNativeCaps(), getNativeExtensions(), mFeatures);
226     mBlitter          = new BlitGL(mFunctions.get(), mFeatures, mStateManager);
227     mMultiviewClearer = new ClearMultiviewGL(mFunctions.get(), mStateManager);
228 
229     bool hasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
230                           mFunctions->hasGLExtension("GL_KHR_debug") ||
231                           mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
232                           mFunctions->hasGLESExtension("GL_KHR_debug");
233 
234     mUseDebugOutput = hasDebugOutput && ShouldUseDebugLayers(attribMap);
235 
236     if (mUseDebugOutput)
237     {
238         mFunctions->enable(GL_DEBUG_OUTPUT);
239         mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
240         mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
241                                         nullptr, GL_TRUE);
242         mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0,
243                                         nullptr, GL_TRUE);
244         mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
245                                         nullptr, GL_FALSE);
246         mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION,
247                                         0, nullptr, GL_FALSE);
248         mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr);
249     }
250 
251     if (mFeatures.initializeCurrentVertexAttributes.enabled)
252     {
253         GLint maxVertexAttribs = 0;
254         mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
255 
256         for (GLint i = 0; i < maxVertexAttribs; ++i)
257         {
258             mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f);
259         }
260     }
261 
262     if (hasNativeParallelCompile() && !mNativeParallelCompileEnabled)
263     {
264         SetMaxShaderCompilerThreads(mFunctions.get(), 0xffffffff);
265         mNativeParallelCompileEnabled = true;
266     }
267 }
268 
~RendererGL()269 RendererGL::~RendererGL()
270 {
271     SafeDelete(mBlitter);
272     SafeDelete(mMultiviewClearer);
273     SafeDelete(mStateManager);
274 
275     std::lock_guard<std::mutex> lock(mWorkerMutex);
276 
277     ASSERT(mCurrentWorkerContexts.empty());
278     mWorkerContextPool.clear();
279 }
280 
flush()281 angle::Result RendererGL::flush()
282 {
283     mFunctions->flush();
284     return angle::Result::Continue;
285 }
286 
finish()287 angle::Result RendererGL::finish()
288 {
289     if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
290     {
291         mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
292     }
293 
294     mFunctions->finish();
295 
296     if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
297     {
298         mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
299     }
300 
301     return angle::Result::Continue;
302 }
303 
stencilFillPath(const gl::State & state,const gl::Path * path,GLenum fillMode,GLuint mask)304 void RendererGL::stencilFillPath(const gl::State &state,
305                                  const gl::Path *path,
306                                  GLenum fillMode,
307                                  GLuint mask)
308 {
309     const auto *pathObj = GetImplAs<PathGL>(path);
310 
311     mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask);
312 
313     ASSERT(mFunctions->getError() == GL_NO_ERROR);
314 }
315 
stencilStrokePath(const gl::State & state,const gl::Path * path,GLint reference,GLuint mask)316 void RendererGL::stencilStrokePath(const gl::State &state,
317                                    const gl::Path *path,
318                                    GLint reference,
319                                    GLuint mask)
320 {
321     const auto *pathObj = GetImplAs<PathGL>(path);
322 
323     mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask);
324 
325     ASSERT(mFunctions->getError() == GL_NO_ERROR);
326 }
327 
coverFillPath(const gl::State & state,const gl::Path * path,GLenum coverMode)328 void RendererGL::coverFillPath(const gl::State &state, const gl::Path *path, GLenum coverMode)
329 {
330 
331     const auto *pathObj = GetImplAs<PathGL>(path);
332     mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode);
333 
334     ASSERT(mFunctions->getError() == GL_NO_ERROR);
335 }
336 
coverStrokePath(const gl::State & state,const gl::Path * path,GLenum coverMode)337 void RendererGL::coverStrokePath(const gl::State &state, const gl::Path *path, GLenum coverMode)
338 {
339     const auto *pathObj = GetImplAs<PathGL>(path);
340     mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode);
341 
342     ASSERT(mFunctions->getError() == GL_NO_ERROR);
343 }
344 
stencilThenCoverFillPath(const gl::State & state,const gl::Path * path,GLenum fillMode,GLuint mask,GLenum coverMode)345 void RendererGL::stencilThenCoverFillPath(const gl::State &state,
346                                           const gl::Path *path,
347                                           GLenum fillMode,
348                                           GLuint mask,
349                                           GLenum coverMode)
350 {
351 
352     const auto *pathObj = GetImplAs<PathGL>(path);
353     mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode);
354 
355     ASSERT(mFunctions->getError() == GL_NO_ERROR);
356 }
357 
stencilThenCoverStrokePath(const gl::State & state,const gl::Path * path,GLint reference,GLuint mask,GLenum coverMode)358 void RendererGL::stencilThenCoverStrokePath(const gl::State &state,
359                                             const gl::Path *path,
360                                             GLint reference,
361                                             GLuint mask,
362                                             GLenum coverMode)
363 {
364 
365     const auto *pathObj = GetImplAs<PathGL>(path);
366     mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode);
367 
368     ASSERT(mFunctions->getError() == GL_NO_ERROR);
369 }
370 
coverFillPathInstanced(const gl::State & state,const std::vector<gl::Path * > & paths,GLenum coverMode,GLenum transformType,const GLfloat * transformValues)371 void RendererGL::coverFillPathInstanced(const gl::State &state,
372                                         const std::vector<gl::Path *> &paths,
373                                         GLenum coverMode,
374                                         GLenum transformType,
375                                         const GLfloat *transformValues)
376 {
377     const auto &pathObjs = GatherPaths(paths);
378 
379     mFunctions->coverFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
380                                          &pathObjs[0], 0, coverMode, transformType,
381                                          transformValues);
382 
383     ASSERT(mFunctions->getError() == GL_NO_ERROR);
384 }
coverStrokePathInstanced(const gl::State & state,const std::vector<gl::Path * > & paths,GLenum coverMode,GLenum transformType,const GLfloat * transformValues)385 void RendererGL::coverStrokePathInstanced(const gl::State &state,
386                                           const std::vector<gl::Path *> &paths,
387                                           GLenum coverMode,
388                                           GLenum transformType,
389                                           const GLfloat *transformValues)
390 {
391     const auto &pathObjs = GatherPaths(paths);
392 
393     mFunctions->coverStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
394                                            &pathObjs[0], 0, coverMode, transformType,
395                                            transformValues);
396 
397     ASSERT(mFunctions->getError() == GL_NO_ERROR);
398 }
stencilFillPathInstanced(const gl::State & state,const std::vector<gl::Path * > & paths,GLenum fillMode,GLuint mask,GLenum transformType,const GLfloat * transformValues)399 void RendererGL::stencilFillPathInstanced(const gl::State &state,
400                                           const std::vector<gl::Path *> &paths,
401                                           GLenum fillMode,
402                                           GLuint mask,
403                                           GLenum transformType,
404                                           const GLfloat *transformValues)
405 {
406     const auto &pathObjs = GatherPaths(paths);
407 
408     mFunctions->stencilFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
409                                            &pathObjs[0], 0, fillMode, mask, transformType,
410                                            transformValues);
411 
412     ASSERT(mFunctions->getError() == GL_NO_ERROR);
413 }
stencilStrokePathInstanced(const gl::State & state,const std::vector<gl::Path * > & paths,GLint reference,GLuint mask,GLenum transformType,const GLfloat * transformValues)414 void RendererGL::stencilStrokePathInstanced(const gl::State &state,
415                                             const std::vector<gl::Path *> &paths,
416                                             GLint reference,
417                                             GLuint mask,
418                                             GLenum transformType,
419                                             const GLfloat *transformValues)
420 {
421     const auto &pathObjs = GatherPaths(paths);
422 
423     mFunctions->stencilStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
424                                              &pathObjs[0], 0, reference, mask, transformType,
425                                              transformValues);
426 
427     ASSERT(mFunctions->getError() == GL_NO_ERROR);
428 }
429 
stencilThenCoverFillPathInstanced(const gl::State & state,const std::vector<gl::Path * > & paths,GLenum coverMode,GLenum fillMode,GLuint mask,GLenum transformType,const GLfloat * transformValues)430 void RendererGL::stencilThenCoverFillPathInstanced(const gl::State &state,
431                                                    const std::vector<gl::Path *> &paths,
432                                                    GLenum coverMode,
433                                                    GLenum fillMode,
434                                                    GLuint mask,
435                                                    GLenum transformType,
436                                                    const GLfloat *transformValues)
437 {
438     const auto &pathObjs = GatherPaths(paths);
439 
440     mFunctions->stencilThenCoverFillPathInstancedNV(
441         static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, fillMode, mask,
442         coverMode, transformType, transformValues);
443 
444     ASSERT(mFunctions->getError() == GL_NO_ERROR);
445 }
stencilThenCoverStrokePathInstanced(const gl::State & state,const std::vector<gl::Path * > & paths,GLenum coverMode,GLint reference,GLuint mask,GLenum transformType,const GLfloat * transformValues)446 void RendererGL::stencilThenCoverStrokePathInstanced(const gl::State &state,
447                                                      const std::vector<gl::Path *> &paths,
448                                                      GLenum coverMode,
449                                                      GLint reference,
450                                                      GLuint mask,
451                                                      GLenum transformType,
452                                                      const GLfloat *transformValues)
453 {
454     const auto &pathObjs = GatherPaths(paths);
455 
456     mFunctions->stencilThenCoverStrokePathInstancedNV(
457         static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, reference, mask,
458         coverMode, transformType, transformValues);
459 
460     ASSERT(mFunctions->getError() == GL_NO_ERROR);
461 }
462 
getResetStatus()463 gl::GraphicsResetStatus RendererGL::getResetStatus()
464 {
465     return gl::FromGLenum<gl::GraphicsResetStatus>(mFunctions->getGraphicsResetStatus());
466 }
467 
insertEventMarker(GLsizei length,const char * marker)468 void RendererGL::insertEventMarker(GLsizei length, const char *marker) {}
469 
pushGroupMarker(GLsizei length,const char * marker)470 void RendererGL::pushGroupMarker(GLsizei length, const char *marker) {}
471 
popGroupMarker()472 void RendererGL::popGroupMarker() {}
473 
pushDebugGroup(GLenum source,GLuint id,const std::string & message)474 void RendererGL::pushDebugGroup(GLenum source, GLuint id, const std::string &message) {}
475 
popDebugGroup()476 void RendererGL::popDebugGroup() {}
477 
getVendorString() const478 std::string RendererGL::getVendorString() const
479 {
480     return std::string(reinterpret_cast<const char *>(mFunctions->getString(GL_VENDOR)));
481 }
482 
getRendererDescription() const483 std::string RendererGL::getRendererDescription() const
484 {
485     std::string nativeVendorString(
486         reinterpret_cast<const char *>(mFunctions->getString(GL_VENDOR)));
487     std::string nativeRendererString(
488         reinterpret_cast<const char *>(mFunctions->getString(GL_RENDERER)));
489 
490     std::ostringstream rendererString;
491     rendererString << nativeVendorString << ", " << nativeRendererString << ", OpenGL";
492     if (mFunctions->standard == STANDARD_GL_ES)
493     {
494         rendererString << " ES";
495     }
496     rendererString << " " << mFunctions->version.major << "." << mFunctions->version.minor;
497     if (mFunctions->standard == STANDARD_GL_DESKTOP)
498     {
499         // Some drivers (NVIDIA) use a profile mask of 0 when in compatibility profile.
500         if ((mFunctions->profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0 ||
501             (mFunctions->isAtLeastGL(gl::Version(3, 2)) && mFunctions->profile == 0))
502         {
503             rendererString << " compatibility";
504         }
505         else if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
506         {
507             rendererString << " core";
508         }
509     }
510 
511     return rendererString.str();
512 }
513 
getMaxSupportedESVersion() const514 const gl::Version &RendererGL::getMaxSupportedESVersion() const
515 {
516     // Force generation of caps
517     getNativeCaps();
518 
519     return mMaxSupportedESVersion;
520 }
521 
generateCaps(gl::Caps * outCaps,gl::TextureCapsMap * outTextureCaps,gl::Extensions * outExtensions,gl::Limitations *) const522 void RendererGL::generateCaps(gl::Caps *outCaps,
523                               gl::TextureCapsMap *outTextureCaps,
524                               gl::Extensions *outExtensions,
525                               gl::Limitations * /* outLimitations */) const
526 {
527     nativegl_gl::GenerateCaps(mFunctions.get(), mFeatures, outCaps, outTextureCaps, outExtensions,
528                               &mMaxSupportedESVersion, &mMultiviewImplementationType);
529 }
530 
getGPUDisjoint()531 GLint RendererGL::getGPUDisjoint()
532 {
533     // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
534     return 0;
535 }
536 
getTimestamp()537 GLint64 RendererGL::getTimestamp()
538 {
539     GLint64 result = 0;
540     mFunctions->getInteger64v(GL_TIMESTAMP, &result);
541     return result;
542 }
543 
ensureCapsInitialized() const544 void RendererGL::ensureCapsInitialized() const
545 {
546     if (!mCapsInitialized)
547     {
548         generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
549         mCapsInitialized = true;
550     }
551 }
552 
getNativeCaps() const553 const gl::Caps &RendererGL::getNativeCaps() const
554 {
555     ensureCapsInitialized();
556     return mNativeCaps;
557 }
558 
getNativeTextureCaps() const559 const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
560 {
561     ensureCapsInitialized();
562     return mNativeTextureCaps;
563 }
564 
getNativeExtensions() const565 const gl::Extensions &RendererGL::getNativeExtensions() const
566 {
567     ensureCapsInitialized();
568     return mNativeExtensions;
569 }
570 
getNativeLimitations() const571 const gl::Limitations &RendererGL::getNativeLimitations() const
572 {
573     ensureCapsInitialized();
574     return mNativeLimitations;
575 }
576 
getMultiviewImplementationType() const577 MultiviewImplementationTypeGL RendererGL::getMultiviewImplementationType() const
578 {
579     ensureCapsInitialized();
580     return mMultiviewImplementationType;
581 }
582 
initializeFrontendFeatures(angle::FrontendFeatures * features) const583 void RendererGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
584 {
585     ensureCapsInitialized();
586     nativegl_gl::InitializeFrontendFeatures(mFunctions.get(), features);
587 }
588 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)589 angle::Result RendererGL::dispatchCompute(const gl::Context *context,
590                                           GLuint numGroupsX,
591                                           GLuint numGroupsY,
592                                           GLuint numGroupsZ)
593 {
594     mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
595     return angle::Result::Continue;
596 }
597 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)598 angle::Result RendererGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
599 {
600     mFunctions->dispatchComputeIndirect(indirect);
601     return angle::Result::Continue;
602 }
603 
memoryBarrier(GLbitfield barriers)604 angle::Result RendererGL::memoryBarrier(GLbitfield barriers)
605 {
606     mFunctions->memoryBarrier(barriers);
607     return angle::Result::Continue;
608 }
memoryBarrierByRegion(GLbitfield barriers)609 angle::Result RendererGL::memoryBarrierByRegion(GLbitfield barriers)
610 {
611     mFunctions->memoryBarrierByRegion(barriers);
612     return angle::Result::Continue;
613 }
614 
bindWorkerContext(std::string * infoLog)615 bool RendererGL::bindWorkerContext(std::string *infoLog)
616 {
617     if (mFeatures.disableWorkerContexts.enabled)
618     {
619         return false;
620     }
621 
622     std::thread::id threadID = std::this_thread::get_id();
623     std::lock_guard<std::mutex> lock(mWorkerMutex);
624     std::unique_ptr<WorkerContext> workerContext;
625     if (!mWorkerContextPool.empty())
626     {
627         auto it       = mWorkerContextPool.begin();
628         workerContext = std::move(*it);
629         mWorkerContextPool.erase(it);
630     }
631     else
632     {
633         WorkerContext *newContext = createWorkerContext(infoLog);
634         if (newContext == nullptr)
635         {
636             return false;
637         }
638         workerContext.reset(newContext);
639     }
640 
641     if (!workerContext->makeCurrent())
642     {
643         mWorkerContextPool.push_back(std::move(workerContext));
644         return false;
645     }
646     mCurrentWorkerContexts[threadID] = std::move(workerContext);
647     return true;
648 }
649 
unbindWorkerContext()650 void RendererGL::unbindWorkerContext()
651 {
652     std::thread::id threadID = std::this_thread::get_id();
653     std::lock_guard<std::mutex> lock(mWorkerMutex);
654 
655     auto it = mCurrentWorkerContexts.find(threadID);
656     ASSERT(it != mCurrentWorkerContexts.end());
657     (*it).second->unmakeCurrent();
658     mWorkerContextPool.push_back(std::move((*it).second));
659     mCurrentWorkerContexts.erase(it);
660 }
661 
getMaxWorkerContexts()662 unsigned int RendererGL::getMaxWorkerContexts()
663 {
664     // No more than 16 worker contexts.
665     return std::min(16u, std::thread::hardware_concurrency());
666 }
667 
hasNativeParallelCompile()668 bool RendererGL::hasNativeParallelCompile()
669 {
670     return mFunctions->maxShaderCompilerThreadsKHR != nullptr ||
671            mFunctions->maxShaderCompilerThreadsARB != nullptr;
672 }
673 
setMaxShaderCompilerThreads(GLuint count)674 void RendererGL::setMaxShaderCompilerThreads(GLuint count)
675 {
676     if (hasNativeParallelCompile())
677     {
678         SetMaxShaderCompilerThreads(mFunctions.get(), count);
679     }
680 }
681 
ScopedWorkerContextGL(RendererGL * renderer,std::string * infoLog)682 ScopedWorkerContextGL::ScopedWorkerContextGL(RendererGL *renderer, std::string *infoLog)
683     : mRenderer(renderer)
684 {
685     mValid = mRenderer->bindWorkerContext(infoLog);
686 }
687 
~ScopedWorkerContextGL()688 ScopedWorkerContextGL::~ScopedWorkerContextGL()
689 {
690     if (mValid)
691     {
692         mRenderer->unbindWorkerContext();
693     }
694 }
695 
operator ()() const696 bool ScopedWorkerContextGL::operator()() const
697 {
698     return mValid;
699 }
700 
701 }  // namespace rx
702