xref: /aosp_15_r20/external/angle/src/common/frame_capture_utils.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2022 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 // frame_capture_utils.cpp:
7 //   ANGLE Frame capture common classes.
8 //
9 
10 #include "common/frame_capture_utils.h"
11 
12 namespace angle
13 {
14 namespace
15 {
16 // Keep the simplest nullptr string for easy C parsing.
17 constexpr char kNullPointerString[] = "0";
18 }  // anonymous namespace
19 
ParamCapture()20 ParamCapture::ParamCapture() : type(ParamType::TGLenum), enumGroup(gl::GLESEnum::AllEnums) {}
21 
ParamCapture(const char * nameIn,ParamType typeIn)22 ParamCapture::ParamCapture(const char *nameIn, ParamType typeIn)
23     : name(nameIn),
24       type(typeIn),
25       enumGroup(gl::GLESEnum::AllEnums),
26       bigGLEnum(gl::BigGLEnum::AllEnums)
27 {}
28 
29 ParamCapture::~ParamCapture() = default;
30 
ParamCapture(ParamCapture && other)31 ParamCapture::ParamCapture(ParamCapture &&other)
32     : type(ParamType::TGLenum),
33       enumGroup(gl::GLESEnum::AllEnums),
34       bigGLEnum(gl::BigGLEnum::AllEnums)
35 {
36     *this = std::move(other);
37 }
38 
operator =(ParamCapture && other)39 ParamCapture &ParamCapture::operator=(ParamCapture &&other)
40 {
41     std::swap(name, other.name);
42     std::swap(type, other.type);
43     std::swap(value, other.value);
44     std::swap(enumGroup, other.enumGroup);
45     std::swap(bigGLEnum, other.bigGLEnum);
46     std::swap(data, other.data);
47     std::swap(arrayClientPointerIndex, other.arrayClientPointerIndex);
48     std::swap(readBufferSizeBytes, other.readBufferSizeBytes);
49     std::swap(dataNElements, other.dataNElements);
50     return *this;
51 }
52 
ParamBuffer()53 ParamBuffer::ParamBuffer() {}
54 
55 ParamBuffer::~ParamBuffer() = default;
56 
ParamBuffer(ParamBuffer && other)57 ParamBuffer::ParamBuffer(ParamBuffer &&other)
58 {
59     *this = std::move(other);
60 }
61 
operator =(ParamBuffer && other)62 ParamBuffer &ParamBuffer::operator=(ParamBuffer &&other)
63 {
64     std::swap(mParamCaptures, other.mParamCaptures);
65     std::swap(mClientArrayDataParam, other.mClientArrayDataParam);
66     std::swap(mReadBufferSize, other.mReadBufferSize);
67     std::swap(mReturnValueCapture, other.mReturnValueCapture);
68     return *this;
69 }
70 
getParam(const char * paramName,ParamType paramType,int index)71 ParamCapture &ParamBuffer::getParam(const char *paramName, ParamType paramType, int index)
72 {
73     ParamCapture &capture = mParamCaptures[index];
74     ASSERT(capture.name == paramName);
75     ASSERT(capture.type == paramType);
76     return capture;
77 }
78 
getParam(const char * paramName,ParamType paramType,int index) const79 const ParamCapture &ParamBuffer::getParam(const char *paramName,
80                                           ParamType paramType,
81                                           int index) const
82 {
83     return const_cast<ParamBuffer *>(this)->getParam(paramName, paramType, index);
84 }
85 
getParamFlexName(const char * paramName1,const char * paramName2,ParamType paramType,int index)86 ParamCapture &ParamBuffer::getParamFlexName(const char *paramName1,
87                                             const char *paramName2,
88                                             ParamType paramType,
89                                             int index)
90 {
91     ParamCapture &capture = mParamCaptures[index];
92     ASSERT(capture.name == paramName1 || capture.name == paramName2);
93     ASSERT(capture.type == paramType);
94     return capture;
95 }
96 
getParamFlexName(const char * paramName1,const char * paramName2,ParamType paramType,int index) const97 const ParamCapture &ParamBuffer::getParamFlexName(const char *paramName1,
98                                                   const char *paramName2,
99                                                   ParamType paramType,
100                                                   int index) const
101 {
102     return const_cast<ParamBuffer *>(this)->getParamFlexName(paramName1, paramName2, paramType,
103                                                              index);
104 }
105 
addParam(ParamCapture && param)106 void ParamBuffer::addParam(ParamCapture &&param)
107 {
108     if (param.arrayClientPointerIndex != -1)
109     {
110         ASSERT(mClientArrayDataParam == -1);
111         mClientArrayDataParam = static_cast<int>(mParamCaptures.size());
112     }
113 
114     mReadBufferSize = std::max(param.readBufferSizeBytes, mReadBufferSize);
115     mParamCaptures.emplace_back(std::move(param));
116 }
117 
addReturnValue(ParamCapture && returnValue)118 void ParamBuffer::addReturnValue(ParamCapture &&returnValue)
119 {
120     mReturnValueCapture = std::move(returnValue);
121 }
122 
getNextParamName()123 const char *ParamBuffer::getNextParamName()
124 {
125     static const char *kParamNames[] = {"p0",  "p1",  "p2",  "p3",  "p4",  "p5",  "p6",  "p7",
126                                         "p8",  "p9",  "p10", "p11", "p12", "p13", "p14", "p15",
127                                         "p16", "p17", "p18", "p19", "p20", "p21", "p22"};
128     ASSERT(mParamCaptures.size() < ArraySize(kParamNames));
129     return kParamNames[mParamCaptures.size()];
130 }
131 
getClientArrayPointerParameter()132 ParamCapture &ParamBuffer::getClientArrayPointerParameter()
133 {
134     ASSERT(hasClientArrayData());
135     return mParamCaptures[mClientArrayDataParam];
136 }
137 
CallCapture(EntryPoint entryPointIn,ParamBuffer && paramsIn)138 CallCapture::CallCapture(EntryPoint entryPointIn, ParamBuffer &&paramsIn)
139     : entryPoint(entryPointIn), params(std::move(paramsIn))
140 {}
141 
CallCapture(const std::string & customFunctionNameIn,ParamBuffer && paramsIn)142 CallCapture::CallCapture(const std::string &customFunctionNameIn, ParamBuffer &&paramsIn)
143     : entryPoint(EntryPoint::Invalid),
144       customFunctionName(customFunctionNameIn),
145       params(std::move(paramsIn))
146 {}
147 
148 CallCapture::~CallCapture() = default;
149 
CallCapture(CallCapture && other)150 CallCapture::CallCapture(CallCapture &&other)
151 {
152     *this = std::move(other);
153 }
154 
operator =(CallCapture && other)155 CallCapture &CallCapture::operator=(CallCapture &&other)
156 {
157     std::swap(entryPoint, other.entryPoint);
158     std::swap(customFunctionName, other.customFunctionName);
159     std::swap(params, other.params);
160     std::swap(isActive, other.isActive);
161     std::swap(contextID, other.contextID);
162     std::swap(isSyncPoint, other.isSyncPoint);
163     return *this;
164 }
165 
name() const166 const char *CallCapture::name() const
167 {
168     if (customFunctionName.empty())
169     {
170         ASSERT(entryPoint != EntryPoint::Invalid);
171         return angle::GetEntryPointName(entryPoint);
172     }
173     else
174     {
175         return customFunctionName.c_str();
176     }
177 }
178 
179 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLboolean value)180 void WriteParamValueReplay<ParamType::TGLboolean>(std::ostream &os,
181                                                   const CallCapture &call,
182                                                   GLboolean value)
183 {
184     switch (value)
185     {
186         case GL_TRUE:
187             os << "GL_TRUE";
188             break;
189         case GL_FALSE:
190             os << "GL_FALSE";
191             break;
192         default:
193             os << "0x" << std::hex << std::uppercase << GLint(value);
194     }
195 }
196 
197 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLboolean * value)198 void WriteParamValueReplay<ParamType::TGLbooleanPointer>(std::ostream &os,
199                                                          const CallCapture &call,
200                                                          GLboolean *value)
201 {
202     if (value == 0)
203     {
204         os << kNullPointerString;
205     }
206     else
207     {
208         os << "(GLboolean *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
209     }
210 }
211 
212 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,const void * value)213 void WriteParamValueReplay<ParamType::TvoidConstPointer>(std::ostream &os,
214                                                          const CallCapture &call,
215                                                          const void *value)
216 {
217     if (value == 0)
218     {
219         os << kNullPointerString;
220     }
221     else
222     {
223         os << "(const void *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
224     }
225 }
226 
227 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,void * value)228 void WriteParamValueReplay<ParamType::TvoidPointer>(std::ostream &os,
229                                                     const CallCapture &call,
230                                                     void *value)
231 {
232     if (value == 0)
233     {
234         os << kNullPointerString;
235     }
236     else
237     {
238         os << "(void *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
239     }
240 }
241 
242 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,const GLfloat * value)243 void WriteParamValueReplay<ParamType::TGLfloatConstPointer>(std::ostream &os,
244                                                             const CallCapture &call,
245                                                             const GLfloat *value)
246 {
247     if (value == 0)
248     {
249         os << kNullPointerString;
250     }
251     else
252     {
253         os << "(const GLfloat *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
254     }
255 }
256 
257 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,const GLint * value)258 void WriteParamValueReplay<ParamType::TGLintConstPointer>(std::ostream &os,
259                                                           const CallCapture &call,
260                                                           const GLint *value)
261 {
262     if (value == 0)
263     {
264         os << kNullPointerString;
265     }
266     else
267     {
268         os << "(const GLint *)" << static_cast<int>(reinterpret_cast<intptr_t>(value));
269     }
270 }
271 
272 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLsizei * value)273 void WriteParamValueReplay<ParamType::TGLsizeiPointer>(std::ostream &os,
274                                                        const CallCapture &call,
275                                                        GLsizei *value)
276 {
277     if (value == 0)
278     {
279         os << kNullPointerString;
280     }
281     else
282     {
283         os << "(GLsizei *)" << static_cast<int>(reinterpret_cast<intptr_t>(value));
284     }
285 }
286 
287 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLuint * value)288 void WriteParamValueReplay<ParamType::TGLuintPointer>(std::ostream &os,
289                                                       const CallCapture &call,
290                                                       GLuint *value)
291 {
292     if (value == 0)
293     {
294         os << kNullPointerString;
295     }
296     else
297     {
298         os << "(GLuint *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
299     }
300 }
301 
302 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,const GLuint * value)303 void WriteParamValueReplay<ParamType::TGLuintConstPointer>(std::ostream &os,
304                                                            const CallCapture &call,
305                                                            const GLuint *value)
306 {
307     if (value == 0)
308     {
309         os << kNullPointerString;
310     }
311     else
312     {
313         os << "(const GLuint *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
314     }
315 }
316 
317 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLDEBUGPROCKHR value)318 void WriteParamValueReplay<ParamType::TGLDEBUGPROCKHR>(std::ostream &os,
319                                                        const CallCapture &call,
320                                                        GLDEBUGPROCKHR value)
321 {}
322 
323 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLDEBUGPROC value)324 void WriteParamValueReplay<ParamType::TGLDEBUGPROC>(std::ostream &os,
325                                                     const CallCapture &call,
326                                                     GLDEBUGPROC value)
327 {}
328 
329 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::BufferID value)330 void WriteParamValueReplay<ParamType::TBufferID>(std::ostream &os,
331                                                  const CallCapture &call,
332                                                  gl::BufferID value)
333 {
334     os << "gBufferMap[" << value.value << "]";
335 }
336 
337 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::FenceNVID value)338 void WriteParamValueReplay<ParamType::TFenceNVID>(std::ostream &os,
339                                                   const CallCapture &call,
340                                                   gl::FenceNVID value)
341 {
342     os << "gFenceNVMap[" << value.value << "]";
343 }
344 
345 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::FramebufferID value)346 void WriteParamValueReplay<ParamType::TFramebufferID>(std::ostream &os,
347                                                       const CallCapture &call,
348                                                       gl::FramebufferID value)
349 {
350     os << "gFramebufferMapPerContext[" << call.contextID.value << "][" << value.value << "]";
351 }
352 
353 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::MemoryObjectID value)354 void WriteParamValueReplay<ParamType::TMemoryObjectID>(std::ostream &os,
355                                                        const CallCapture &call,
356                                                        gl::MemoryObjectID value)
357 {
358     os << "gMemoryObjectMap[" << value.value << "]";
359 }
360 
361 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::ProgramPipelineID value)362 void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
363                                                           const CallCapture &call,
364                                                           gl::ProgramPipelineID value)
365 {
366     os << "gProgramPipelineMap[" << value.value << "]";
367 }
368 
369 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::QueryID value)370 void WriteParamValueReplay<ParamType::TQueryID>(std::ostream &os,
371                                                 const CallCapture &call,
372                                                 gl::QueryID value)
373 {
374     os << "gQueryMap[" << value.value << "]";
375 }
376 
377 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::RenderbufferID value)378 void WriteParamValueReplay<ParamType::TRenderbufferID>(std::ostream &os,
379                                                        const CallCapture &call,
380                                                        gl::RenderbufferID value)
381 {
382     os << "gRenderbufferMap[" << value.value << "]";
383 }
384 
385 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::SamplerID value)386 void WriteParamValueReplay<ParamType::TSamplerID>(std::ostream &os,
387                                                   const CallCapture &call,
388                                                   gl::SamplerID value)
389 {
390     os << "gSamplerMap[" << value.value << "]";
391 }
392 
393 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::SemaphoreID value)394 void WriteParamValueReplay<ParamType::TSemaphoreID>(std::ostream &os,
395                                                     const CallCapture &call,
396                                                     gl::SemaphoreID value)
397 {
398     os << "gSemaphoreMap[" << value.value << "]";
399 }
400 
401 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::ShaderProgramID value)402 void WriteParamValueReplay<ParamType::TShaderProgramID>(std::ostream &os,
403                                                         const CallCapture &call,
404                                                         gl::ShaderProgramID value)
405 {
406     os << "gShaderProgramMap[" << value.value << "]";
407 }
408 
409 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::SyncID value)410 void WriteParamValueReplay<ParamType::TSyncID>(std::ostream &os,
411                                                const CallCapture &call,
412                                                gl::SyncID value)
413 {
414     os << "gSyncMap2[" << value.value << "]";
415 }
416 
417 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::TextureID value)418 void WriteParamValueReplay<ParamType::TTextureID>(std::ostream &os,
419                                                   const CallCapture &call,
420                                                   gl::TextureID value)
421 {
422     os << "gTextureMap[" << value.value << "]";
423 }
424 
425 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::TransformFeedbackID value)426 void WriteParamValueReplay<ParamType::TTransformFeedbackID>(std::ostream &os,
427                                                             const CallCapture &call,
428                                                             gl::TransformFeedbackID value)
429 {
430     os << "gTransformFeedbackMap[" << value.value << "]";
431 }
432 
433 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::VertexArrayID value)434 void WriteParamValueReplay<ParamType::TVertexArrayID>(std::ostream &os,
435                                                       const CallCapture &call,
436                                                       gl::VertexArrayID value)
437 {
438     os << "gVertexArrayMap[" << value.value << "]";
439 }
440 
441 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::UniformLocation value)442 void WriteParamValueReplay<ParamType::TUniformLocation>(std::ostream &os,
443                                                         const CallCapture &call,
444                                                         gl::UniformLocation value)
445 {
446     if (value.value == -1)
447     {
448         os << "-1";
449         return;
450     }
451 
452     os << "gUniformLocations[";
453 
454     // Find the program from the call parameters.
455     std::vector<gl::ShaderProgramID> shaderProgramIDs;
456     if (FindResourceIDsInCall<gl::ShaderProgramID>(call, shaderProgramIDs))
457     {
458         ASSERT(shaderProgramIDs.size() == 1);
459         os << shaderProgramIDs[0].value;
460     }
461     else
462     {
463         os << "gCurrentProgram";
464     }
465 
466     os << "][" << value.value << "]";
467 }
468 
469 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::UniformBlockIndex value)470 void WriteParamValueReplay<ParamType::TUniformBlockIndex>(std::ostream &os,
471                                                           const CallCapture &call,
472                                                           gl::UniformBlockIndex value)
473 {
474     // We do not support directly using uniform block indexes due to their multiple indirections.
475     // Use CaptureCustomUniformBlockBinding if you end up hitting this assertion.
476     UNREACHABLE();
477 }
478 
479 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLubyte value)480 void WriteParamValueReplay<ParamType::TGLubyte>(std::ostream &os,
481                                                 const CallCapture &call,
482                                                 GLubyte value)
483 {
484     const int v = value;
485     os << v;
486 }
487 
488 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLDEBUGPROCKHR value)489 void WriteParamValueReplay<ParamType::TEGLDEBUGPROCKHR>(std::ostream &os,
490                                                         const CallCapture &call,
491                                                         EGLDEBUGPROCKHR value)
492 {
493     // It's not necessary to implement correct capture for these types.
494     os << "0";
495 }
496 
497 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLGetBlobFuncANDROID value)498 void WriteParamValueReplay<ParamType::TEGLGetBlobFuncANDROID>(std::ostream &os,
499                                                               const CallCapture &call,
500                                                               EGLGetBlobFuncANDROID value)
501 {
502     // It's not necessary to implement correct capture for these types.
503     os << "0";
504 }
505 
506 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLSetBlobFuncANDROID value)507 void WriteParamValueReplay<ParamType::TEGLSetBlobFuncANDROID>(std::ostream &os,
508                                                               const CallCapture &call,
509                                                               EGLSetBlobFuncANDROID value)
510 {
511     // It's not necessary to implement correct capture for these types.
512     os << "0";
513 }
514 
515 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,egl::Config * value)516 void WriteParamValueReplay<ParamType::Tegl_ConfigPointer>(std::ostream &os,
517                                                           const CallCapture &call,
518                                                           egl::Config *value)
519 {
520     os << "EGL_NO_CONFIG_KHR";
521 }
522 
523 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,egl::SurfaceID value)524 void WriteParamValueReplay<ParamType::TSurfaceID>(std::ostream &os,
525                                                   const CallCapture &call,
526                                                   egl::SurfaceID value)
527 {
528     os << "gSurfaceMap2[" << value.value << "]";
529 }
530 
531 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,gl::ContextID value)532 void WriteParamValueReplay<ParamType::TContextID>(std::ostream &os,
533                                                   const CallCapture &call,
534                                                   gl::ContextID value)
535 {
536     os << "gContextMap2[" << value.value << "]";
537 }
538 
539 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,egl::Display * value)540 void WriteParamValueReplay<ParamType::Tegl_DisplayPointer>(std::ostream &os,
541                                                            const CallCapture &call,
542                                                            egl::Display *value)
543 {
544     os << "gEGLDisplay";
545 }
546 
547 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,egl::ImageID value)548 void WriteParamValueReplay<ParamType::TImageID>(std::ostream &os,
549                                                 const CallCapture &call,
550                                                 egl::ImageID value)
551 {
552     os << "gEGLImageMap2[" << value.value << "]";
553 }
554 
555 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLClientBuffer value)556 void WriteParamValueReplay<ParamType::TEGLClientBuffer>(std::ostream &os,
557                                                         const CallCapture &call,
558                                                         EGLClientBuffer value)
559 {
560     os << value;
561 }
562 
563 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,egl::SyncID value)564 void WriteParamValueReplay<ParamType::Tegl_SyncID>(std::ostream &os,
565                                                    const CallCapture &call,
566                                                    egl::SyncID value)
567 {
568     os << "gEGLSyncMap[" << value.value << "]";
569 }
570 
571 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLAttrib * value)572 void WriteParamValueReplay<ParamType::TEGLAttribPointer>(std::ostream &os,
573                                                          const CallCapture &call,
574                                                          EGLAttrib *value)
575 {
576     if (value == 0)
577     {
578         os << kNullPointerString;
579     }
580     else
581     {
582         os << "(EGLAttrib *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
583     }
584 }
585 
586 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,const EGLAttrib * value)587 void WriteParamValueReplay<ParamType::TEGLAttribConstPointer>(std::ostream &os,
588                                                               const CallCapture &call,
589                                                               const EGLAttrib *value)
590 {
591     if (value == 0)
592     {
593         os << kNullPointerString;
594     }
595     else
596     {
597         os << "(const EGLAttrib *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
598     }
599 }
600 
601 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,const EGLint * value)602 void WriteParamValueReplay<ParamType::TEGLintConstPointer>(std::ostream &os,
603                                                            const CallCapture &call,
604                                                            const EGLint *value)
605 {
606     if (value == 0)
607     {
608         os << kNullPointerString;
609     }
610     else
611     {
612         os << "(const EGLint *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
613     }
614 }
615 
616 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLint * value)617 void WriteParamValueReplay<ParamType::TEGLintPointer>(std::ostream &os,
618                                                       const CallCapture &call,
619                                                       EGLint *value)
620 {
621     if (value == 0)
622     {
623         os << kNullPointerString;
624     }
625     else
626     {
627         os << "(const EGLint *)" << static_cast<int>(reinterpret_cast<uintptr_t>(value));
628     }
629 }
630 
631 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLTime value)632 void WriteParamValueReplay<ParamType::TEGLTime>(std::ostream &os,
633                                                 const CallCapture &call,
634                                                 EGLTime value)
635 {
636     os << value << "ul";
637 }
638 
639 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,EGLTimeKHR value)640 void WriteParamValueReplay<ParamType::TEGLTimeKHR>(std::ostream &os,
641                                                    const CallCapture &call,
642                                                    EGLTimeKHR value)
643 {
644     os << value << "ul";
645 }
646 
647 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLGETBLOBPROCANGLE value)648 void WriteParamValueReplay<ParamType::TGLGETBLOBPROCANGLE>(std::ostream &os,
649                                                            const CallCapture &call,
650                                                            GLGETBLOBPROCANGLE value)
651 {
652     // It's not necessary to implement correct capture for these types.
653     os << "0";
654 }
655 
656 template <>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,GLSETBLOBPROCANGLE value)657 void WriteParamValueReplay<ParamType::TGLSETBLOBPROCANGLE>(std::ostream &os,
658                                                            const CallCapture &call,
659                                                            GLSETBLOBPROCANGLE value)
660 {
661     // It's not necessary to implement correct capture for these types.
662     os << "0";
663 }
664 
665 template <typename ParamValueType>
FindResourceIDsInCall(const CallCapture & call,std::vector<ParamValueType> & idsOut)666 bool FindResourceIDsInCall(const CallCapture &call, std::vector<ParamValueType> &idsOut)
667 {
668     const ParamType paramType = ParamValueTrait<ParamValueType>::typeID;
669     for (const ParamCapture &param : call.params.getParamCaptures())
670     {
671         if (param.type == paramType)
672         {
673             const ParamValueType id = AccessParamValue<ParamValueType>(paramType, param.value);
674             idsOut.push_back(id);
675         }
676     }
677 
678     return !idsOut.empty();
679 }
680 
681 // Explicit instantiation
682 template bool FindResourceIDsInCall<gl::TextureID>(const CallCapture &call,
683                                                    std::vector<gl::TextureID> &idsOut);
684 template bool FindResourceIDsInCall<gl::ShaderProgramID>(const CallCapture &call,
685                                                          std::vector<gl::ShaderProgramID> &idsOut);
686 }  // namespace angle
687