1 //
2 // Copyright 2020 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_test_utils:
7 // Helper functions for capture and replay of traces.
8 //
9
10 #ifndef UTIL_FRAME_CAPTURE_TEST_UTILS_H_
11 #define UTIL_FRAME_CAPTURE_TEST_UTILS_H_
12
13 #include <iostream>
14 #include <memory>
15 #include <sstream>
16 #include <type_traits>
17 #include <vector>
18
19 #include "common/angleutils.h"
20 #include "common/system_utils.h"
21
22 #define USE_SYSTEM_ZLIB
23 #include "compression_utils_portable.h"
24
25 #define ANGLE_MACRO_STRINGIZE_AUX(a) #a
26 #define ANGLE_MACRO_STRINGIZE(a) ANGLE_MACRO_STRINGIZE_AUX(a)
27 #define ANGLE_MACRO_CONCAT_AUX(a, b) a##b
28 #define ANGLE_MACRO_CONCAT(a, b) ANGLE_MACRO_CONCAT_AUX(a, b)
29
30 namespace angle
31 {
32
DecompressBinaryData(const std::vector<uint8_t> & compressedData)33 inline uint8_t *DecompressBinaryData(const std::vector<uint8_t> &compressedData)
34 {
35 uint32_t uncompressedSize =
36 zlib_internal::GetGzipUncompressedSize(compressedData.data(), compressedData.size());
37
38 std::unique_ptr<uint8_t[]> uncompressedData(new uint8_t[uncompressedSize]);
39 uLong destLen = uncompressedSize;
40 int zResult =
41 zlib_internal::GzipUncompressHelper(uncompressedData.get(), &destLen, compressedData.data(),
42 static_cast<uLong>(compressedData.size()));
43
44 if (zResult != Z_OK)
45 {
46 std::cerr << "Failure to decompressed binary data: " << zResult << "\n";
47 return nullptr;
48 }
49
50 return uncompressedData.release();
51 }
52
53 using DecompressCallback = uint8_t *(*)(const std::vector<uint8_t> &);
54
55 using SetBinaryDataDecompressCallbackFunc = void (*)(DecompressCallback);
56 using SetBinaryDataDirFunc = void (*)(const char *);
57 using SetupReplayFunc = void (*)();
58 using ReplayFrameFunc = void (*)(uint32_t);
59 using ResetReplayFunc = void (*)();
60 using FinishReplayFunc = void (*)();
61 using GetSerializedContextStateFunc = const char *(*)(uint32_t);
62
63 class TraceLibrary
64 {
65 public:
TraceLibrary(const char * traceNameIn)66 TraceLibrary(const char *traceNameIn)
67 {
68 std::stringstream traceNameStr;
69 #if !defined(ANGLE_PLATFORM_WINDOWS)
70 traceNameStr << "lib";
71 #endif // !defined(ANGLE_PLATFORM_WINDOWS)
72 traceNameStr << traceNameIn;
73 #if defined(ANGLE_PLATFORM_ANDROID) && defined(COMPONENT_BUILD)
74 // Added to shared library names in Android component builds in
75 // https://chromium.googlesource.com/chromium/src/+/9bacc8c4868cc802f69e1e858eea6757217a508f/build/toolchain/toolchain.gni#56
76 traceNameStr << ".cr";
77 #endif // defined(ANGLE_PLATFORM_ANDROID) && defined(COMPONENT_BUILD)
78 std::string traceName = traceNameStr.str();
79 mTraceLibrary.reset(OpenSharedLibrary(traceName.c_str(), SearchType::ModuleDir));
80 }
81
valid()82 bool valid() const { return mTraceLibrary != nullptr; }
83
setBinaryDataDir(const char * dataDir)84 void setBinaryDataDir(const char *dataDir)
85 {
86 callFunc<SetBinaryDataDirFunc>("SetBinaryDataDir", dataDir);
87 }
88
setBinaryDataDecompressCallback(DecompressCallback callback)89 void setBinaryDataDecompressCallback(DecompressCallback callback)
90 {
91 callFunc<SetBinaryDataDecompressCallbackFunc>("SetBinaryDataDecompressCallback", callback);
92 }
93
replayFrame(uint32_t frameIndex)94 void replayFrame(uint32_t frameIndex) { callFunc<ReplayFrameFunc>("ReplayFrame", frameIndex); }
95
setupReplay()96 void setupReplay() { callFunc<SetupReplayFunc>("SetupReplay"); }
97
resetReplay()98 void resetReplay() { callFunc<ResetReplayFunc>("ResetReplay"); }
99
finishReplay()100 void finishReplay() { callFunc<FinishReplayFunc>("FinishReplay"); }
101
getSerializedContextState(uint32_t frameIndex)102 const char *getSerializedContextState(uint32_t frameIndex)
103 {
104 return callFunc<GetSerializedContextStateFunc>("GetSerializedContextState", frameIndex);
105 }
106
107 private:
108 template <typename FuncT, typename... ArgsT>
callFunc(const char * funcName,ArgsT...args)109 typename std::result_of<FuncT(ArgsT...)>::type callFunc(const char *funcName, ArgsT... args)
110 {
111 void *untypedFunc = mTraceLibrary->getSymbol(funcName);
112 if (!untypedFunc)
113 {
114 fprintf(stderr, "Error loading function: %s\n", funcName);
115 ASSERT(untypedFunc);
116 }
117 auto typedFunc = reinterpret_cast<FuncT>(untypedFunc);
118 return typedFunc(args...);
119 }
120
121 std::unique_ptr<Library> mTraceLibrary;
122 };
123
124 } // namespace angle
125
126 #endif // UTIL_FRAME_CAPTURE_TEST_UTILS_H_
127