// // Copyright 2021 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // frame_capture_test_utils: // Helper functions for capture and replay of traces. // #include "frame_capture_test_utils.h" #include "common/frame_capture_utils.h" #include "common/string_utils.h" #include #include #include namespace angle { namespace { bool LoadJSONFromFile(const std::string &fileName, rapidjson::Document *doc) { std::ifstream ifs(fileName); if (!ifs.is_open()) { return false; } rapidjson::IStreamWrapper inWrapper(ifs); doc->ParseStream(inWrapper); return !doc->HasParseError(); } } // namespace bool LoadTraceNamesFromJSON(const std::string jsonFilePath, std::vector *namesOut) { rapidjson::Document doc; if (!LoadJSONFromFile(jsonFilePath, &doc)) { return false; } if (!doc.IsObject() || !doc.HasMember("traces") || !doc["traces"].IsArray()) { return false; } // Read trace json into a list of trace names. std::vector traces; rapidjson::Document::Array traceArray = doc["traces"].GetArray(); for (rapidjson::SizeType arrayIndex = 0; arrayIndex < traceArray.Size(); ++arrayIndex) { const rapidjson::Document::ValueType &arrayElement = traceArray[arrayIndex]; if (!arrayElement.IsString()) { return false; } std::vector traceAndVersion; angle::SplitStringAlongWhitespace(arrayElement.GetString(), &traceAndVersion); traces.push_back(traceAndVersion[0]); } *namesOut = std::move(traces); return true; } bool LoadTraceInfoFromJSON(const std::string &traceName, const std::string &traceJsonPath, TraceInfo *traceInfoOut) { rapidjson::Document doc; if (!LoadJSONFromFile(traceJsonPath, &doc)) { return false; } if (!doc.IsObject() || !doc.HasMember("TraceMetadata")) { return false; } const rapidjson::Document::Object &meta = doc["TraceMetadata"].GetObj(); strncpy(traceInfoOut->name, traceName.c_str(), kTraceInfoMaxNameLen); traceInfoOut->contextClientMajorVersion = meta["ContextClientMajorVersion"].GetInt(); traceInfoOut->contextClientMinorVersion = meta["ContextClientMinorVersion"].GetInt(); traceInfoOut->frameEnd = meta["FrameEnd"].GetInt(); traceInfoOut->frameStart = meta["FrameStart"].GetInt(); traceInfoOut->drawSurfaceHeight = meta["DrawSurfaceHeight"].GetInt(); traceInfoOut->drawSurfaceWidth = meta["DrawSurfaceWidth"].GetInt(); angle::HexStringToUInt(meta["DrawSurfaceColorSpace"].GetString(), &traceInfoOut->drawSurfaceColorSpace); angle::HexStringToUInt(meta["DisplayPlatformType"].GetString(), &traceInfoOut->displayPlatformType); angle::HexStringToUInt(meta["DisplayDeviceType"].GetString(), &traceInfoOut->displayDeviceType); traceInfoOut->configRedBits = meta["ConfigRedBits"].GetInt(); traceInfoOut->configGreenBits = meta["ConfigGreenBits"].GetInt(); traceInfoOut->configBlueBits = meta["ConfigBlueBits"].GetInt(); traceInfoOut->configAlphaBits = meta["ConfigAlphaBits"].GetInt(); traceInfoOut->configDepthBits = meta["ConfigDepthBits"].GetInt(); traceInfoOut->configStencilBits = meta["ConfigStencilBits"].GetInt(); traceInfoOut->isBinaryDataCompressed = meta["IsBinaryDataCompressed"].GetBool(); traceInfoOut->areClientArraysEnabled = meta["AreClientArraysEnabled"].GetBool(); traceInfoOut->isBindGeneratesResourcesEnabled = meta["IsBindGeneratesResourcesEnabled"].GetBool(); traceInfoOut->isWebGLCompatibilityEnabled = meta["IsWebGLCompatibilityEnabled"].GetBool(); traceInfoOut->isRobustResourceInitEnabled = meta["IsRobustResourceInitEnabled"].GetBool(); traceInfoOut->windowSurfaceContextId = doc["WindowSurfaceContextID"].GetInt(); if (doc.HasMember("RequiredExtensions")) { const rapidjson::Value &requiredExtensions = doc["RequiredExtensions"]; if (!requiredExtensions.IsArray()) { return false; } for (rapidjson::SizeType i = 0; i < requiredExtensions.Size(); i++) { std::string ext = std::string(requiredExtensions[i].GetString()); traceInfoOut->requiredExtensions.push_back(ext); } } if (meta.HasMember("KeyFrames")) { const rapidjson::Value &keyFrames = meta["KeyFrames"]; if (!keyFrames.IsArray()) { return false; } for (rapidjson::SizeType i = 0; i < keyFrames.Size(); i++) { int frame = keyFrames[i].GetInt(); traceInfoOut->keyFrames.push_back(frame); } } const rapidjson::Document::Array &traceFiles = doc["TraceFiles"].GetArray(); for (const rapidjson::Value &value : traceFiles) { traceInfoOut->traceFiles.push_back(value.GetString()); } traceInfoOut->initialized = true; return true; } TraceLibrary::TraceLibrary(const std::string &traceName, const TraceInfo &traceInfo) { std::stringstream libNameStr; #if !defined(ANGLE_PLATFORM_WINDOWS) libNameStr << "lib"; #endif // !defined(ANGLE_PLATFORM_WINDOWS) libNameStr << traceName; #if defined(ANGLE_PLATFORM_ANDROID) && defined(COMPONENT_BUILD) // Added to shared library names in Android component builds in // https://chromium.googlesource.com/chromium/src/+/9bacc8c4868cc802f69e1e858eea6757217a508f/build/toolchain/toolchain.gni#56 libNameStr << ".cr"; #endif // defined(ANGLE_PLATFORM_ANDROID) && defined(COMPONENT_BUILD) std::string libName = libNameStr.str(); mTraceLibrary.reset(OpenSharedLibrary(libName.c_str(), SearchType::ModuleDir)); callFunc("SetTraceInfo", traceInfo.traceFiles); } } // namespace angle