• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 // Copyright 2019 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 // FrameCapture.h:
7 //   ANGLE Frame capture inteface.
8 //
9 
10 #ifndef LIBANGLE_FRAME_CAPTURE_H_
11 #define LIBANGLE_FRAME_CAPTURE_H_
12 
13 #include "common/PackedEnums.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/angletypes.h"
16 #include "libANGLE/capture/frame_capture_utils_autogen.h"
17 #include "libANGLE/entry_points_utils.h"
18 
19 namespace gl
20 {
21 enum class GLenumGroup;
22 }
23 
24 namespace angle
25 {
26 
27 using ParamData = std::vector<std::vector<uint8_t>>;
28 struct ParamCapture : angle::NonCopyable
29 {
30     ParamCapture();
31     ParamCapture(const char *nameIn, ParamType typeIn);
32     ~ParamCapture();
33 
34     ParamCapture(ParamCapture &&other);
35     ParamCapture &operator=(ParamCapture &&other);
36 
37     std::string name;
38     ParamType type;
39     ParamValue value;
40     gl::GLenumGroup enumGroup;  // only used for param type GLenum, GLboolean and GLbitfield
41     ParamData data;
42     int dataNElements           = 0;
43     int arrayClientPointerIndex = -1;
44     size_t readBufferSizeBytes  = 0;
45 };
46 
47 class ParamBuffer final : angle::NonCopyable
48 {
49   public:
50     ParamBuffer();
51     ~ParamBuffer();
52 
53     ParamBuffer(ParamBuffer &&other);
54     ParamBuffer &operator=(ParamBuffer &&other);
55 
56     template <typename T>
57     void addValueParam(const char *paramName, ParamType paramType, T paramValue);
58     template <typename T>
59     void setValueParamAtIndex(const char *paramName, ParamType paramType, T paramValue, int index);
60     template <typename T>
61     void addEnumParam(const char *paramName,
62                       gl::GLenumGroup enumGroup,
63                       ParamType paramType,
64                       T paramValue);
65 
66     ParamCapture &getParam(const char *paramName, ParamType paramType, int index);
67     const ParamCapture &getParam(const char *paramName, ParamType paramType, int index) const;
68     ParamCapture &getParamFlexName(const char *paramName1,
69                                    const char *paramName2,
70                                    ParamType paramType,
71                                    int index);
72     const ParamCapture &getParamFlexName(const char *paramName1,
73                                          const char *paramName2,
74                                          ParamType paramType,
75                                          int index) const;
getReturnValue()76     const ParamCapture &getReturnValue() const { return mReturnValueCapture; }
77 
78     void addParam(ParamCapture &&param);
79     void addReturnValue(ParamCapture &&returnValue);
hasClientArrayData()80     bool hasClientArrayData() const { return mClientArrayDataParam != -1; }
81     ParamCapture &getClientArrayPointerParameter();
getReadBufferSize()82     size_t getReadBufferSize() const { return mReadBufferSize; }
83 
getParamCaptures()84     const std::vector<ParamCapture> &getParamCaptures() const { return mParamCaptures; }
85 
86     // These helpers allow us to track the ID of the buffer that was active when
87     // MapBufferRange was called.  We'll use it during replay to track the
88     // buffer's contents, as they can be modified by the host.
setMappedBufferID(gl::BufferID bufferID)89     void setMappedBufferID(gl::BufferID bufferID) { mMappedBufferID = bufferID; }
getMappedBufferID()90     gl::BufferID getMappedBufferID() const { return mMappedBufferID; }
91 
92   private:
93     std::vector<ParamCapture> mParamCaptures;
94     ParamCapture mReturnValueCapture;
95     int mClientArrayDataParam = -1;
96     size_t mReadBufferSize    = 0;
97     gl::BufferID mMappedBufferID;
98 };
99 
100 struct CallCapture
101 {
102     CallCapture(EntryPoint entryPointIn, ParamBuffer &&paramsIn);
103     CallCapture(const std::string &customFunctionNameIn, ParamBuffer &&paramsIn);
104     ~CallCapture();
105 
106     CallCapture(CallCapture &&other);
107     CallCapture &operator=(CallCapture &&other);
108 
109     const char *name() const;
110 
111     EntryPoint entryPoint;
112     std::string customFunctionName;
113     ParamBuffer params;
114 };
115 
116 class ReplayContext
117 {
118   public:
119     ReplayContext(size_t readBufferSizebytes, const gl::AttribArray<size_t> &clientArraysSizebytes);
120     ~ReplayContext();
121 
122     template <typename T>
getReadBufferPointer(const ParamCapture & param)123     T getReadBufferPointer(const ParamCapture &param)
124     {
125         ASSERT(param.readBufferSizeBytes > 0);
126         ASSERT(mReadBuffer.size() >= param.readBufferSizeBytes);
127         return reinterpret_cast<T>(mReadBuffer.data());
128     }
129     template <typename T>
getAsConstPointer(const ParamCapture & param)130     T getAsConstPointer(const ParamCapture &param)
131     {
132         if (param.arrayClientPointerIndex != -1)
133         {
134             return reinterpret_cast<T>(mClientArraysBuffer[param.arrayClientPointerIndex].data());
135         }
136 
137         if (!param.data.empty())
138         {
139             ASSERT(param.data.size() == 1);
140             return reinterpret_cast<T>(param.data[0].data());
141         }
142 
143         return nullptr;
144     }
145 
146     template <typename T>
getAsPointerConstPointer(const ParamCapture & param)147     T getAsPointerConstPointer(const ParamCapture &param)
148     {
149         static_assert(sizeof(typename std::remove_pointer<T>::type) == sizeof(uint8_t *),
150                       "pointer size not match!");
151 
152         ASSERT(!param.data.empty());
153         mPointersBuffer.clear();
154         mPointersBuffer.reserve(param.data.size());
155         for (const std::vector<uint8_t> &data : param.data)
156         {
157             mPointersBuffer.emplace_back(data.data());
158         }
159         return reinterpret_cast<T>(mPointersBuffer.data());
160     }
161 
getClientArraysBuffer()162     gl::AttribArray<std::vector<uint8_t>> &getClientArraysBuffer() { return mClientArraysBuffer; }
163 
164   private:
165     std::vector<uint8_t> mReadBuffer;
166     std::vector<const uint8_t *> mPointersBuffer;
167     gl::AttribArray<std::vector<uint8_t>> mClientArraysBuffer;
168 };
169 
170 // Helper to use unique IDs for each local data variable.
171 class DataCounters final : angle::NonCopyable
172 {
173   public:
174     DataCounters();
175     ~DataCounters();
176 
177     int getAndIncrement(EntryPoint entryPoint, const std::string &paramName);
178 
179   private:
180     // <CallName, ParamName>
181     using Counter = std::pair<EntryPoint, std::string>;
182     std::map<Counter, int> mData;
183 };
184 
185 constexpr int kStringsNotFound = -1;
186 class StringCounters final : angle::NonCopyable
187 {
188   public:
189     StringCounters();
190     ~StringCounters();
191 
192     int getStringCounter(std::vector<std::string> &str);
193     void setStringCounter(std::vector<std::string> &str, int &counter);
194 
195   private:
196     std::map<std::vector<std::string>, int> mStringCounterMap;
197 };
198 
199 class DataTracker final : angle::NonCopyable
200 {
201   public:
202     DataTracker();
203     ~DataTracker();
204 
getCounters()205     DataCounters &getCounters() { return mCounters; }
getStringCounters()206     StringCounters &getStringCounters() { return mStringCounters; }
207 
208   private:
209     DataCounters mCounters;
210     StringCounters mStringCounters;
211 };
212 
213 using BufferSet   = std::set<gl::BufferID>;
214 using BufferCalls = std::map<gl::BufferID, std::vector<CallCapture>>;
215 
216 // true means mapped, false means unmapped
217 using BufferMapStatusMap = std::map<gl::BufferID, bool>;
218 
219 using FenceSyncSet   = std::set<GLsync>;
220 using FenceSyncCalls = std::map<GLsync, std::vector<CallCapture>>;
221 
222 using ProgramSet = std::set<gl::ShaderProgramID>;
223 
224 // Helper to track resource changes during the capture
225 class ResourceTracker final : angle::NonCopyable
226 {
227   public:
228     ResourceTracker();
229     ~ResourceTracker();
230 
getBufferRegenCalls()231     BufferCalls &getBufferRegenCalls() { return mBufferRegenCalls; }
getBufferRestoreCalls()232     BufferCalls &getBufferRestoreCalls() { return mBufferRestoreCalls; }
getBufferMapCalls()233     BufferCalls &getBufferMapCalls() { return mBufferMapCalls; }
getBufferUnmapCalls()234     BufferCalls &getBufferUnmapCalls() { return mBufferUnmapCalls; }
235 
getBufferBindingCalls()236     std::vector<CallCapture> &getBufferBindingCalls() { return mBufferBindingCalls; }
237 
getStartingBuffers()238     BufferSet &getStartingBuffers() { return mStartingBuffers; }
getNewBuffers()239     BufferSet &getNewBuffers() { return mNewBuffers; }
getBuffersToRegen()240     BufferSet &getBuffersToRegen() { return mBuffersToRegen; }
getBuffersToRestore()241     BufferSet &getBuffersToRestore() { return mBuffersToRestore; }
242 
243     void setGennedBuffer(gl::BufferID id);
244     void setDeletedBuffer(gl::BufferID id);
245     void setBufferModified(gl::BufferID id);
246     void setBufferMapped(gl::BufferID id);
247     void setBufferUnmapped(gl::BufferID id);
248 
getStartingBuffersMappedCurrent(gl::BufferID id)249     const bool &getStartingBuffersMappedCurrent(gl::BufferID id)
250     {
251         return mStartingBuffersMappedCurrent[id];
252     }
getStartingBuffersMappedInitial(gl::BufferID id)253     const bool &getStartingBuffersMappedInitial(gl::BufferID id)
254     {
255         return mStartingBuffersMappedInitial[id];
256     }
setStartingBufferMapped(gl::BufferID id,bool mapped)257     void setStartingBufferMapped(gl::BufferID id, bool mapped)
258     {
259         // Track the current state (which will change throughout the trace)
260         mStartingBuffersMappedCurrent[id] = mapped;
261 
262         // And the initial state, to compare during frame loop reset
263         mStartingBuffersMappedInitial[id] = mapped;
264     }
265 
266     void onShaderProgramAccess(gl::ShaderProgramID shaderProgramID);
getMaxShaderPrograms()267     uint32_t getMaxShaderPrograms() const { return mMaxShaderPrograms; }
268 
getStartingFenceSyncs()269     FenceSyncSet &getStartingFenceSyncs() { return mStartingFenceSyncs; }
getFenceSyncRegenCalls()270     FenceSyncCalls &getFenceSyncRegenCalls() { return mFenceSyncRegenCalls; }
getFenceSyncsToRegen()271     FenceSyncSet &getFenceSyncsToRegen() { return mFenceSyncsToRegen; }
272     void setDeletedFenceSync(GLsync sync);
273 
getStartingPrograms()274     ProgramSet &getStartingPrograms() { return mStartingPrograms; }
getNewPrograms()275     ProgramSet &getNewPrograms() { return mNewPrograms; }
getProgramsToRegen()276     ProgramSet &getProgramsToRegen() { return mProgramsToRegen; }
277 
278     void setCreatedProgram(gl::ShaderProgramID id);
279     void setDeletedProgram(gl::ShaderProgramID id);
280 
281   private:
282     // Buffer regen calls will delete and gen a buffer
283     BufferCalls mBufferRegenCalls;
284     // Buffer restore calls will restore the contents of a buffer
285     BufferCalls mBufferRestoreCalls;
286     // Buffer map calls will map a buffer with correct offset, length, and access flags
287     BufferCalls mBufferMapCalls;
288     // Buffer unmap calls will bind and unmap a given buffer
289     BufferCalls mBufferUnmapCalls;
290 
291     // Buffer binding calls to restore bindings recorded during MEC
292     std::vector<CallCapture> mBufferBindingCalls;
293 
294     // Starting buffers include all the buffers created during setup for MEC
295     BufferSet mStartingBuffers;
296     // New buffers are those generated while capturing
297     BufferSet mNewBuffers;
298     // Buffers to regen are a list of starting buffers that need to be deleted and genned
299     BufferSet mBuffersToRegen;
300     // Buffers to restore include any starting buffers with contents modified during the run
301     BufferSet mBuffersToRestore;
302 
303     // Whether a given buffer was mapped at the start of the trace
304     BufferMapStatusMap mStartingBuffersMappedInitial;
305     // The status of buffer mapping throughout the trace, modified with each Map/Unmap call
306     BufferMapStatusMap mStartingBuffersMappedCurrent;
307 
308     // Maximum accessed shader program ID.
309     uint32_t mMaxShaderPrograms = 0;
310 
311     // Programs created during startup
312     ProgramSet mStartingPrograms;
313     // Programs created during the run that need to be deleted
314     ProgramSet mNewPrograms;
315     // Programs deleted during the run that need to be recreated
316     ProgramSet mProgramsToRegen;
317 
318     // Fence sync objects created during MEC setup
319     FenceSyncSet mStartingFenceSyncs;
320     // Fence sync regen calls will create a fence sync objects
321     FenceSyncCalls mFenceSyncRegenCalls;
322     // Fence syncs to regen are a list of starting fence sync objects that were deleted and need to
323     // be regen'ed.
324     FenceSyncSet mFenceSyncsToRegen;
325 };
326 
327 // Used by the CPP replay to filter out unnecessary code.
328 using HasResourceTypeMap = angle::PackedEnumBitSet<ResourceIDType>;
329 
330 // Map of buffer ID to offset and size used when mapped
331 using BufferDataMap = std::map<gl::BufferID, std::pair<GLintptr, GLsizeiptr>>;
332 
333 // A dictionary of sources indexed by shader type.
334 using ProgramSources = gl::ShaderMap<std::string>;
335 
336 // Maps from IDs to sources.
337 using ShaderSourceMap  = std::map<gl::ShaderProgramID, std::string>;
338 using ProgramSourceMap = std::map<gl::ShaderProgramID, ProgramSources>;
339 
340 // Map from textureID to level and data
341 using TextureLevels       = std::map<GLint, std::vector<uint8_t>>;
342 using TextureLevelDataMap = std::map<gl::TextureID, TextureLevels>;
343 
344 // Map from ContextID to surface dimensions
345 using SurfaceDimensions = std::map<gl::ContextID, gl::Extents>;
346 
347 class FrameCapture final : angle::NonCopyable
348 {
349   public:
350     FrameCapture();
351     ~FrameCapture();
352 
getSetupCalls()353     std::vector<CallCapture> &getSetupCalls() { return mSetupCalls; }
clearSetupCalls()354     void clearSetupCalls() { mSetupCalls.clear(); }
355 
356     void reset();
357 
358   private:
359     std::vector<CallCapture> mSetupCalls;
360 };
361 
362 // Shared class for any items that need to be tracked by FrameCapture across shared contexts
363 class FrameCaptureShared final : angle::NonCopyable
364 {
365   public:
366     FrameCaptureShared();
367     ~FrameCaptureShared();
368 
369     void captureCall(const gl::Context *context, CallCapture &&call, bool isCallValid);
370     void checkForCaptureTrigger();
371     void setupSharedAndAuxReplay(const gl::Context *context, bool isMidExecutionCapture);
372     void onEndFrame(const gl::Context *context);
373     void onDestroyContext(const gl::Context *context);
374     void onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface);
enabled()375     bool enabled() const { return mEnabled; }
376 
377     bool isCapturing() const;
378     void replay(gl::Context *context);
379     uint32_t getFrameCount() const;
380 
381     // Returns a frame index starting from "1" as the first frame.
382     uint32_t getReplayFrameIndex() const;
383 
getResourceTracker()384     ResourceTracker &getResourceTracker() { return mResourceTracker; }
385 
386     void trackBufferMapping(CallCapture *call,
387                             gl::BufferID id,
388                             GLintptr offset,
389                             GLsizeiptr length,
390                             bool writable);
391 
392     const std::string &getShaderSource(gl::ShaderProgramID id) const;
393     void setShaderSource(gl::ShaderProgramID id, std::string sources);
394 
395     const ProgramSources &getProgramSources(gl::ShaderProgramID id) const;
396     void setProgramSources(gl::ShaderProgramID id, ProgramSources sources);
397 
398     // Load data from a previously stored texture level
399     const std::vector<uint8_t> &retrieveCachedTextureLevel(gl::TextureID id,
400                                                            gl::TextureTarget target,
401                                                            GLint level);
402 
403     // Create new texture level data and copy the source into it
404     void copyCachedTextureLevel(const gl::Context *context,
405                                 gl::TextureID srcID,
406                                 GLint srcLevel,
407                                 gl::TextureID dstID,
408                                 GLint dstLevel,
409                                 const CallCapture &call);
410 
411     // Create the location that should be used to cache texture level data
412     std::vector<uint8_t> &getCachedTextureLevelData(gl::Texture *texture,
413                                                     gl::TextureTarget target,
414                                                     GLint level,
415                                                     EntryPoint entryPoint);
416 
417     // Remove any cached texture levels on deletion
418     void deleteCachedTextureLevelData(gl::TextureID id);
419 
eraseBufferDataMapEntry(const gl::BufferID bufferId)420     void eraseBufferDataMapEntry(const gl::BufferID bufferId)
421     {
422         const auto &bufferDataInfo = mBufferDataMap.find(bufferId);
423         if (bufferDataInfo != mBufferDataMap.end())
424         {
425             mBufferDataMap.erase(bufferDataInfo);
426         }
427     }
428 
hasBufferData(gl::BufferID bufferID)429     bool hasBufferData(gl::BufferID bufferID)
430     {
431         const auto &bufferDataInfo = mBufferDataMap.find(bufferID);
432         if (bufferDataInfo != mBufferDataMap.end())
433         {
434             return true;
435         }
436         return false;
437     }
438 
getBufferDataOffsetAndLength(gl::BufferID bufferID)439     std::pair<GLintptr, GLsizeiptr> getBufferDataOffsetAndLength(gl::BufferID bufferID)
440     {
441         const auto &bufferDataInfo = mBufferDataMap.find(bufferID);
442         ASSERT(bufferDataInfo != mBufferDataMap.end());
443         return bufferDataInfo->second;
444     }
445 
setCaptureActive()446     void setCaptureActive() { mCaptureActive = true; }
setCaptureInactive()447     void setCaptureInactive() { mCaptureActive = false; }
isCaptureActive()448     bool isCaptureActive() { return mCaptureActive; }
449 
getWindowSurfaceContextID()450     gl::ContextID getWindowSurfaceContextID() const { return mWindowSurfaceContextID; }
451 
updateReadBufferSize(size_t readBufferSize)452     void updateReadBufferSize(size_t readBufferSize)
453     {
454         mReadBufferSize = std::max(mReadBufferSize, readBufferSize);
455     }
456 
457   private:
458     void writeCppReplayIndexFiles(const gl::Context *, bool writeResetContextCall);
459 
460     void captureClientArraySnapshot(const gl::Context *context,
461                                     size_t vertexCount,
462                                     size_t instanceCount);
463     void captureMappedBufferSnapshot(const gl::Context *context, const CallCapture &call);
464 
465     void copyCompressedTextureData(const gl::Context *context, const CallCapture &call);
466     void captureCompressedTextureData(const gl::Context *context, const CallCapture &call);
467 
468     void reset();
469     void maybeOverrideEntryPoint(const gl::Context *context, CallCapture &call);
470     void maybeCapturePreCallUpdates(const gl::Context *context, CallCapture &call);
471     void maybeCapturePostCallUpdates(const gl::Context *context);
472     void maybeCaptureDrawArraysClientData(const gl::Context *context,
473                                           CallCapture &call,
474                                           size_t instanceCount);
475     void maybeCaptureDrawElementsClientData(const gl::Context *context,
476                                             CallCapture &call,
477                                             size_t instanceCount);
478     void updateCopyImageSubData(CallCapture &call);
479 
480     static void ReplayCall(gl::Context *context,
481                            ReplayContext *replayContext,
482                            const CallCapture &call);
483 
getSetupCalls()484     std::vector<CallCapture> &getSetupCalls() { return mSetupCalls; }
clearSetupCalls()485     void clearSetupCalls() { mSetupCalls.clear(); }
486 
487     std::vector<CallCapture> mSetupCalls;
488     std::vector<CallCapture> mFrameCalls;
489 
490     // We save one large buffer of binary data for the whole CPP replay.
491     // This simplifies a lot of file management.
492     std::vector<uint8_t> mBinaryData;
493 
494     bool mEnabled = false;
495     bool mSerializeStateEnabled;
496     std::string mOutDirectory;
497     std::string mCaptureLabel;
498     bool mCompression;
499     gl::AttribArray<int> mClientVertexArrayMap;
500     uint32_t mFrameIndex;
501     uint32_t mCaptureStartFrame;
502     uint32_t mCaptureEndFrame;
503     bool mIsFirstFrame   = true;
504     bool mWroteIndexFile = false;
505     SurfaceDimensions mDrawSurfaceDimensions;
506     gl::AttribArray<size_t> mClientArraySizes;
507     size_t mReadBufferSize;
508     HasResourceTypeMap mHasResourceType;
509     BufferDataMap mBufferDataMap;
510 
511     ResourceTracker mResourceTracker;
512 
513     // If you don't know which frame you want to start capturing at, use the capture trigger.
514     // Initialize it to the number of frames you want to capture, and then clear the value to 0 when
515     // you reach the content you want to capture. Currently only available on Android.
516     uint32_t mCaptureTrigger;
517 
518     bool mCaptureActive = false;
519     std::vector<uint32_t> mActiveFrameIndices;
520 
521     // Cache most recently compiled and linked sources.
522     ShaderSourceMap mCachedShaderSource;
523     ProgramSourceMap mCachedProgramSources;
524 
525     // Cache a shadow copy of texture level data
526     TextureLevels mCachedTextureLevels;
527     TextureLevelDataMap mCachedTextureLevelData;
528 
529     gl::ContextID mWindowSurfaceContextID;
530 };
531 
532 template <typename CaptureFuncT, typename... ArgsT>
CaptureCallToFrameCapture(CaptureFuncT captureFunc,bool isCallValid,gl::Context * context,ArgsT...captureParams)533 void CaptureCallToFrameCapture(CaptureFuncT captureFunc,
534                                bool isCallValid,
535                                gl::Context *context,
536                                ArgsT... captureParams)
537 {
538     FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
539     if (!frameCaptureShared->isCapturing())
540     {
541         return;
542     }
543 
544     CallCapture call = captureFunc(context->getState(), isCallValid, captureParams...);
545 
546     frameCaptureShared->captureCall(context, std::move(call), isCallValid);
547 }
548 
549 template <typename T>
addValueParam(const char * paramName,ParamType paramType,T paramValue)550 void ParamBuffer::addValueParam(const char *paramName, ParamType paramType, T paramValue)
551 {
552     ParamCapture capture(paramName, paramType);
553     InitParamValue(paramType, paramValue, &capture.value);
554     mParamCaptures.emplace_back(std::move(capture));
555 }
556 
557 template <typename T>
setValueParamAtIndex(const char * paramName,ParamType paramType,T paramValue,int index)558 void ParamBuffer::setValueParamAtIndex(const char *paramName,
559                                        ParamType paramType,
560                                        T paramValue,
561                                        int index)
562 {
563     ASSERT(mParamCaptures.size() > static_cast<size_t>(index));
564 
565     ParamCapture capture(paramName, paramType);
566     InitParamValue(paramType, paramValue, &capture.value);
567     mParamCaptures[index] = std::move(capture);
568 }
569 
570 template <typename T>
addEnumParam(const char * paramName,gl::GLenumGroup enumGroup,ParamType paramType,T paramValue)571 void ParamBuffer::addEnumParam(const char *paramName,
572                                gl::GLenumGroup enumGroup,
573                                ParamType paramType,
574                                T paramValue)
575 {
576     ParamCapture capture(paramName, paramType);
577     InitParamValue(paramType, paramValue, &capture.value);
578     capture.enumGroup = enumGroup;
579     mParamCaptures.emplace_back(std::move(capture));
580 }
581 
582 std::ostream &operator<<(std::ostream &os, const ParamCapture &capture);
583 
584 // Pointer capture helpers.
585 void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture);
586 void CaptureString(const GLchar *str, ParamCapture *paramCapture);
587 void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture);
588 void CaptureVertexPointerGLES1(const gl::State &glState,
589                                gl::ClientVertexArrayType type,
590                                const void *pointer,
591                                ParamCapture *paramCapture);
592 
593 gl::Program *GetProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle);
594 
595 // For GetIntegerv, GetFloatv, etc.
596 void CaptureGetParameter(const gl::State &glState,
597                          GLenum pname,
598                          size_t typeSize,
599                          ParamCapture *paramCapture);
600 
601 void CaptureGetActiveUniformBlockivParameters(const gl::State &glState,
602                                               gl::ShaderProgramID handle,
603                                               gl::UniformBlockIndex uniformBlockIndex,
604                                               GLenum pname,
605                                               ParamCapture *paramCapture);
606 
607 template <typename T>
CaptureClearBufferValue(GLenum buffer,const T * value,ParamCapture * paramCapture)608 void CaptureClearBufferValue(GLenum buffer, const T *value, ParamCapture *paramCapture)
609 {
610     // Per the spec, color buffers have a vec4, the rest a single value
611     uint32_t valueSize = (buffer == GL_COLOR) ? 4 : 1;
612     CaptureMemory(value, valueSize * sizeof(T), paramCapture);
613 }
614 
615 void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCapture);
616 
617 template <typename T>
CaptureGenHandles(GLsizei n,T * handles,ParamCapture * paramCapture)618 void CaptureGenHandles(GLsizei n, T *handles, ParamCapture *paramCapture)
619 {
620     paramCapture->dataNElements = n;
621     CaptureGenHandlesImpl(n, reinterpret_cast<GLuint *>(handles), paramCapture);
622 }
623 
624 template <typename T>
CaptureArray(T * elements,GLsizei n,ParamCapture * paramCapture)625 void CaptureArray(T *elements, GLsizei n, ParamCapture *paramCapture)
626 {
627     paramCapture->dataNElements = n;
628     CaptureMemory(elements, n * sizeof(T), paramCapture);
629 }
630 
631 void CaptureShaderStrings(GLsizei count,
632                           const GLchar *const *strings,
633                           const GLint *length,
634                           ParamCapture *paramCapture);
635 
636 template <ParamType ParamT, typename T>
637 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value);
638 
639 template <>
640 void WriteParamValueReplay<ParamType::TGLboolean>(std::ostream &os,
641                                                   const CallCapture &call,
642                                                   GLboolean value);
643 
644 template <>
645 void WriteParamValueReplay<ParamType::TvoidConstPointer>(std::ostream &os,
646                                                          const CallCapture &call,
647                                                          const void *value);
648 
649 template <>
650 void WriteParamValueReplay<ParamType::TGLfloatConstPointer>(std::ostream &os,
651                                                             const CallCapture &call,
652                                                             const GLfloat *value);
653 
654 template <>
655 void WriteParamValueReplay<ParamType::TGLuintConstPointer>(std::ostream &os,
656                                                            const CallCapture &call,
657                                                            const GLuint *value);
658 
659 template <>
660 void WriteParamValueReplay<ParamType::TGLDEBUGPROCKHR>(std::ostream &os,
661                                                        const CallCapture &call,
662                                                        GLDEBUGPROCKHR value);
663 
664 template <>
665 void WriteParamValueReplay<ParamType::TGLDEBUGPROC>(std::ostream &os,
666                                                     const CallCapture &call,
667                                                     GLDEBUGPROC value);
668 
669 template <>
670 void WriteParamValueReplay<ParamType::TBufferID>(std::ostream &os,
671                                                  const CallCapture &call,
672                                                  gl::BufferID value);
673 
674 template <>
675 void WriteParamValueReplay<ParamType::TFenceNVID>(std::ostream &os,
676                                                   const CallCapture &call,
677                                                   gl::FenceNVID value);
678 
679 template <>
680 void WriteParamValueReplay<ParamType::TFramebufferID>(std::ostream &os,
681                                                       const CallCapture &call,
682                                                       gl::FramebufferID value);
683 
684 template <>
685 void WriteParamValueReplay<ParamType::TMemoryObjectID>(std::ostream &os,
686                                                        const CallCapture &call,
687                                                        gl::MemoryObjectID value);
688 
689 template <>
690 void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
691                                                           const CallCapture &call,
692                                                           gl::ProgramPipelineID value);
693 
694 template <>
695 void WriteParamValueReplay<ParamType::TQueryID>(std::ostream &os,
696                                                 const CallCapture &call,
697                                                 gl::QueryID value);
698 
699 template <>
700 void WriteParamValueReplay<ParamType::TRenderbufferID>(std::ostream &os,
701                                                        const CallCapture &call,
702                                                        gl::RenderbufferID value);
703 
704 template <>
705 void WriteParamValueReplay<ParamType::TSamplerID>(std::ostream &os,
706                                                   const CallCapture &call,
707                                                   gl::SamplerID value);
708 
709 template <>
710 void WriteParamValueReplay<ParamType::TSemaphoreID>(std::ostream &os,
711                                                     const CallCapture &call,
712                                                     gl::SemaphoreID value);
713 
714 template <>
715 void WriteParamValueReplay<ParamType::TShaderProgramID>(std::ostream &os,
716                                                         const CallCapture &call,
717                                                         gl::ShaderProgramID value);
718 
719 template <>
720 void WriteParamValueReplay<ParamType::TTextureID>(std::ostream &os,
721                                                   const CallCapture &call,
722                                                   gl::TextureID value);
723 
724 template <>
725 void WriteParamValueReplay<ParamType::TTransformFeedbackID>(std::ostream &os,
726                                                             const CallCapture &call,
727                                                             gl::TransformFeedbackID value);
728 
729 template <>
730 void WriteParamValueReplay<ParamType::TVertexArrayID>(std::ostream &os,
731                                                       const CallCapture &call,
732                                                       gl::VertexArrayID value);
733 
734 template <>
735 void WriteParamValueReplay<ParamType::TUniformLocation>(std::ostream &os,
736                                                         const CallCapture &call,
737                                                         gl::UniformLocation value);
738 
739 template <>
740 void WriteParamValueReplay<ParamType::TUniformBlockIndex>(std::ostream &os,
741                                                           const CallCapture &call,
742                                                           gl::UniformBlockIndex value);
743 
744 template <>
745 void WriteParamValueReplay<ParamType::TGLsync>(std::ostream &os,
746                                                const CallCapture &call,
747                                                GLsync value);
748 
749 template <>
750 void WriteParamValueReplay<ParamType::TGLeglImageOES>(std::ostream &os,
751                                                       const CallCapture &call,
752                                                       GLeglImageOES value);
753 
754 template <>
755 void WriteParamValueReplay<ParamType::TGLubyte>(std::ostream &os,
756                                                 const CallCapture &call,
757                                                 GLubyte value);
758 
759 // General fallback for any unspecific type.
760 template <ParamType ParamT, typename T>
WriteParamValueReplay(std::ostream & os,const CallCapture & call,T value)761 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value)
762 {
763     os << value;
764 }
765 }  // namespace angle
766 
767 template <typename T>
CaptureTextureAndSamplerParameter_params(GLenum pname,const T * param,angle::ParamCapture * paramCapture)768 void CaptureTextureAndSamplerParameter_params(GLenum pname,
769                                               const T *param,
770                                               angle::ParamCapture *paramCapture)
771 {
772     if (pname == GL_TEXTURE_BORDER_COLOR || pname == GL_TEXTURE_CROP_RECT_OES)
773     {
774         CaptureMemory(param, sizeof(T) * 4, paramCapture);
775     }
776     else
777     {
778         CaptureMemory(param, sizeof(T), paramCapture);
779     }
780 }
781 
782 #endif  // LIBANGLE_FRAME_CAPTURE_H_
783