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