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 &¶m);
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 &¶msIn);
103 CallCapture(const std::string &customFunctionNameIn, ParamBuffer &¶msIn);
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 ¶m)
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 ¶m)
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 ¶m)
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 ¶mName);
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