From 1ef584757959d096a953e055dd0fa199dd0c2a3b Mon Sep 17 00:00:00 2001 From: Eugene Mutavchi Date: Thu, 15 Jan 2026 16:13:02 +0000 Subject: [PATCH 1/4] Add 'signpost' implementation for ftrace system tracing --- Source/WTF/wtf/SystemTracing.h | 35 ++++++++++- Source/WTF/wtf/linux/SystemTracingFTrace.h | 60 ++++++++++++------- .../coordinated/CoordinatedBackingStore.cpp | 4 +- .../coordinated/CoordinatedGraphicsLayer.cpp | 4 +- 4 files changed, 75 insertions(+), 28 deletions(-) diff --git a/Source/WTF/wtf/SystemTracing.h b/Source/WTF/wtf/SystemTracing.h index e1ae482db0640..3fce23b82748c 100644 --- a/Source/WTF/wtf/SystemTracing.h +++ b/Source/WTF/wtf/SystemTracing.h @@ -211,7 +211,7 @@ inline void tracePoint(TracePointCode code, uint64_t data1 = 0, uint64_t data2 = UNUSED_PARAM(data3); UNUSED_PARAM(data4); #elif USE(LINUX_FTRACE) - SystemTracingFTrace::instance().tracePoint(code, data1); + SystemTracingFTrace::instance().tracePoint(code, data1, data2, data3, data4); UNUSED_PARAM(data2); UNUSED_PARAM(data3); UNUSED_PARAM(data4); @@ -420,6 +420,39 @@ enum WTFOSSignpostType { #define WTFBeginSignpostAlwaysWithTimeDelta(pointer, name, timeDelta, ...) WTFBeginSignpostWithTimeDelta((pointer), name, (timeDelta), ##__VA_ARGS__) #define WTFEndSignpostAlwaysWithTimeDelta(pointer, name, timeDelta, ...) WTFEndSignpostWithTimeDelta((pointer), name, (timeDelta), ##__VA_ARGS__) +#elif USE(LINUX_FTRACE) + +#define WTFEmitSignpostWithPhase(phase, pointer, name, format, ...) \ + do { \ + if (SystemTracingFTrace::isEnabled()) \ + SystemTracingFTrace::instance().addMark( \ + phase, std::span(_STRINGIFY(name)), \ + "p=%p" format, \ + reinterpret_cast(pointer) \ + __VA_OPT__(,) __VA_ARGS__); \ + } while (0) + +#define WTFEmitSignpost(pointer, name, ...) \ + WTFEmitSignpostWithPhase('I', pointer, name, __VA_OPT__(",") __VA_ARGS__) \ + +#define WTFBeginSignpost(pointer, name, ...) \ + WTFEmitSignpostWithPhase('B', pointer, name, __VA_OPT__(",") __VA_ARGS__) \ + +#define WTFEndSignpost(pointer, name, ...) \ + WTFEmitSignpostWithPhase('E', pointer, name, __VA_OPT__(",") __VA_ARGS__) \ + +#define WTFEmitSignpostAlways(pointer, name, ...) WTFEmitSignpost((pointer), name, ##__VA_ARGS__) +#define WTFBeginSignpostAlways(pointer, name, ...) WTFBeginSignpost((pointer), name, ##__VA_ARGS__) +#define WTFEndSignpostAlways(pointer, name, ...) WTFEndSignpost((pointer), name, ##__VA_ARGS__) + +#define WTFEmitSignpostWithTimeDelta(pointer, name, timeDelta, ...) WTFEmitSignpost((pointer), name, ##__VA_ARGS__) +#define WTFBeginSignpostWithTimeDelta(pointer, name, timeDelta, ...) WTFBeginSignpost((pointer), name, ##__VA_ARGS__) +#define WTFEndSignpostWithTimeDelta(pointer, name, timeDelta, ...) WTFEndSignpost((pointer), name, ##__VA_ARGS__) + +#define WTFEmitSignpostAlwaysWithTimeDelta(pointer, name, ...) WTFEmitSignpost((pointer), name, ##__VA_ARGS__) +#define WTFBeginSignpostAlwaysWithTimeDelta(pointer, name, ...) WTFBeginSignpost((pointer), name, ##__VA_ARGS__) +#define WTFEndSignpostAlwaysWithTimeDelta(pointer, name, ...) WTFEndSignpost((pointer), name, ##__VA_ARGS__) + #else #define WTFEmitSignpost(pointer, name, ...) do { } while (0) diff --git a/Source/WTF/wtf/linux/SystemTracingFTrace.h b/Source/WTF/wtf/linux/SystemTracingFTrace.h index 0e78056f36673..f91146f587ff9 100644 --- a/Source/WTF/wtf/linux/SystemTracingFTrace.h +++ b/Source/WTF/wtf/linux/SystemTracingFTrace.h @@ -41,7 +41,7 @@ class SystemTracingFTrace { return instance; } - inline void tracePoint(TracePointCode code, uint64_t cookie) { + inline void tracePoint(TracePointCode code, uint64_t data1 = 0, uint64_t data2 = 0, uint64_t data3 = 0, uint64_t data4 = 0) { // ftrace disabled in runtime if (m_traceMarkerFd < 0) return; @@ -103,7 +103,7 @@ class SystemTracingFTrace { case LayerFlushStart: case UpdateLayerContentBuffersStart: #endif - beginSyncMark(code); + beginSyncMark(code, data1, data2, data3, data4); return; case VMEntryScopeEnd: @@ -168,12 +168,12 @@ class SystemTracingFTrace { case MainResourceLoadDidStartProvisional: case SubresourceLoadWillStart: - beginAsyncMark(code, cookie); + beginAsyncMark(code, data1); return; case MainResourceLoadDidEnd: case SubresourceLoadDidEnd: - endAsyncMark(code, cookie); + endAsyncMark(code, data1); return; case DisplayRefreshDispatchingToMainThread: @@ -183,7 +183,7 @@ class SystemTracingFTrace { case SyntheticMomentumEvent: case RemoteLayerTreeScheduleRenderingUpdate: case DisplayLinkUpdate: - instantMark(code); + instantMark(code, data1, data2, data3, data4); return; case WTFRange: @@ -208,45 +208,57 @@ class SystemTracingFTrace { } } + static bool isEnabled() { + return !(instance().m_traceMarkerFd < 0); + } + private: - inline void beginSyncMark(TracePointCode code) { - // "B||" - std::string message = std::string("B|") + std::to_string(m_pid) + "|" + tracePointCodeName(code).characters(); - writeFTraceMarker(message.c_str()); + inline void beginSyncMark(TracePointCode code, uint64_t data1, uint64_t data2, uint64_t data3, uint64_t data4) { + // "B|||" + addMark('B', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); } inline void endSyncMark(TracePointCode code) { - UNUSED_PARAM(code); - // "E|" - std::string message = std::string("E|") + std::to_string(m_pid); - writeFTraceMarker(message.c_str()); + // "E||" + addMark('E', tracePointCodeName(code).spanIncludingNullTerminator()); } inline void beginAsyncMark(TracePointCode code, uint64_t cookie) { // "S|||" - std::string message = std::string("S|") + std::to_string(m_pid) + "|" + tracePointCodeName(code).characters() + "|" + std::to_string(cookie); - writeFTraceMarker(message.c_str()); + addMark('S', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64, cookie); } inline void endAsyncMark(TracePointCode code, uint64_t cookie) { // "F|||" - std::string message = std::string("F|") + std::to_string(m_pid) + "|" + tracePointCodeName(code).characters() + "|" + std::to_string(cookie); - writeFTraceMarker(message.c_str()); + addMark('F', tracePointCodeName(code).spanIncludingNullTerminator(),"%" PRIu64, cookie); } - inline void instantMark(TracePointCode code) { + inline void instantMark(TracePointCode code, uint64_t data1, uint64_t data2, uint64_t data3, uint64_t data4) { // "I||" - std::string message = std::string("I|") + std::to_string(m_pid) + "|" + tracePointCodeName(code).characters(); - writeFTraceMarker(message.c_str()); + addMark('I', tracePointCodeName(code).spanIncludingNullTerminator(),"%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); } - inline void writeFTraceMarker(const char* message) { + inline void writeFTraceMarker(const char* message, size_t len) { RELEASE_ASSERT(m_traceMarkerFd >= 0); + size_t offset = 0; + // make sure no other thread is writing at the same time std::lock_guard lock(m_mutex); - write(m_traceMarkerFd, message, strlen(message)); + while (len > 0) { + ssize_t ret; + + do { + ret = write(m_traceMarkerFd, message + offset, len); + } while (ret < 0 && errno == EINTR); + + if (ret <= 0) + break; + + len -= ret; + offset += ret; + } } SystemTracingFTrace() { @@ -490,4 +502,6 @@ class SystemTracingFTrace { } // namespace WTF -#endif // USE(LINUX_FTRACE) \ No newline at end of file +using WTF::SystemTracingFTrace; + +#endif // USE(LINUX_FTRACE) diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp index d780b2290bd37..c51d677f5f699 100644 --- a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp +++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp @@ -41,13 +41,13 @@ void CoordinatedBackingStoreTile::swapBuffers(TextureMapper& textureMapper) if (!updatesCount) return; - WTFBeginSignpost(this, CoordinatedSwapBuffers, "%lu updates", updatesCount); + WTFBeginSignpost(this, CoordinatedSwapBuffers, "%zu updates", updatesCount); for (unsigned updateIndex = 0; updateIndex < updates.size(); ++updateIndex) { auto& update = updates[updateIndex]; if (!update.buffer) continue; - WTFBeginSignpost(this, CoordinatedSwapBuffer, "%u/%lu, rect %ix%i+%i+%i", updateIndex + 1, updatesCount, update.tileRect.x(), update.tileRect.y(), update.tileRect.width(), update.tileRect.height()); + WTFBeginSignpost(this, CoordinatedSwapBuffer, "%u/%zu, rect %ix%i+%i+%i", updateIndex + 1, updatesCount, update.tileRect.x(), update.tileRect.y(), update.tileRect.width(), update.tileRect.height()); ASSERT(textureMapper.maxTextureSize().width() >= update.tileRect.size().width()); ASSERT(textureMapper.maxTextureSize().height() >= update.tileRect.size().height()); diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp index 94a60eb79a164..5311105912036 100644 --- a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp +++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp @@ -1245,13 +1245,13 @@ void CoordinatedGraphicsLayer::updateContentBuffers() auto dirtyTilesCount = dirtyTiles.size(); bool didUpdateTiles = false; - WTFBeginSignpost(this, UpdateTiles, "dirty tiles: %lu", dirtyTilesCount); + WTFBeginSignpost(this, UpdateTiles, "dirty tiles: %zu", dirtyTilesCount); for (unsigned dirtyTileIndex = 0; dirtyTileIndex < dirtyTilesCount; ++dirtyTileIndex) { auto& tile = dirtyTiles[dirtyTileIndex].get(); tile.ensureTileID(); - WTFBeginSignpost(this, UpdateTile, "%u/%lu, id: %d", dirtyTileIndex + 1, dirtyTilesCount, tile.tileID()); + WTFBeginSignpost(this, UpdateTile, "%u/%zu, id: %d", dirtyTileIndex + 1, dirtyTilesCount, tile.tileID()); auto& tileRect = tile.rect(); auto& dirtyRect = tile.dirtyRect(); From 102c3e0bf6bf22bfc9d907017b8eb1a9914eb556 Mon Sep 17 00:00:00 2001 From: Eugene Mutavchi Date: Thu, 15 Jan 2026 16:15:42 +0000 Subject: [PATCH 2/4] [ftrace] make sure subresource load-did-end is marked for main resource too The start trace point is added in SubresourceLoader::willSendRequestInternal --- Source/WebCore/loader/SubresourceLoader.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/WebCore/loader/SubresourceLoader.cpp b/Source/WebCore/loader/SubresourceLoader.cpp index 7a858ca4c5488..5d7a6908d9de3 100644 --- a/Source/WebCore/loader/SubresourceLoader.cpp +++ b/Source/WebCore/loader/SubresourceLoader.cpp @@ -768,7 +768,9 @@ void SubresourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMe reportResourceTiming(timing ? *timing : NetworkLoadMetrics::emptyMetrics()); } +#if !USE(LINUX_FTRACE) if (resource->type() != CachedResource::Type::MainResource) +#endif tracePoint(SubresourceLoadDidEnd, identifier().toUInt64()); m_state = Finishing; @@ -816,7 +818,9 @@ void SubresourceLoader::didFail(const ResourceError& error) Ref protectedThis { *this }; m_state = Finishing; +#if !USE(LINUX_FTRACE) if (resource->type() != CachedResource::Type::MainResource) +#endif tracePoint(SubresourceLoadDidEnd, identifier().toUInt64()); if (resource->resourceToRevalidate()) @@ -872,7 +876,9 @@ void SubresourceLoader::didCancel(LoadWillContinueInAnotherProcess loadWillConti CachedResourceHandle resource = m_resource.get(); ASSERT(resource); +#if !USE(LINUX_FTRACE) if (resource->type() != CachedResource::Type::MainResource) +#endif tracePoint(SubresourceLoadDidEnd, identifier().toUInt64()); resource->cancelLoad(loadWillContinueInAnotherProcess); From f329c071f7bf06dfbe85368f4d0908a8639871c0 Mon Sep 17 00:00:00 2001 From: Eugene Mutavchi Date: Thu, 15 Jan 2026 16:33:58 +0000 Subject: [PATCH 3/4] [ftrace] include tracing of skia, angle and libwebrtc --- Source/ThirdParty/ANGLE/CMakeLists.txt | 11 +- .../ThirdParty/ANGLE/include/CMakeLists.txt | 10 ++ Source/ThirdParty/skia/CMakeLists.txt | 12 +- Source/WTF/wtf/linux/SystemTracingFTrace.h | 115 ++++++++++++++++++ Source/WebCore/platform/Skia.cmake | 1 + .../graphics/angle/PlatformDisplayANGLE.cpp | 59 +++++++++ .../platform/graphics/skia/SkiaEventTracer.h | 104 ++++++++++++++++ .../libwebrtc/LibWebRTCProvider.cpp | 34 ++++++ .../WebProcess/wpe/WebProcessMainWPE.cpp | 9 +- 9 files changed, 351 insertions(+), 4 deletions(-) create mode 100644 Source/WebCore/platform/graphics/skia/SkiaEventTracer.h diff --git a/Source/ThirdParty/ANGLE/CMakeLists.txt b/Source/ThirdParty/ANGLE/CMakeLists.txt index d8eb1bc698cc2..cc5febb6f7fb2 100644 --- a/Source/ThirdParty/ANGLE/CMakeLists.txt +++ b/Source/ThirdParty/ANGLE/CMakeLists.txt @@ -90,6 +90,12 @@ set(ANGLE_SOURCES src/libANGLE/capture/serialize_mock.cpp ) +if (USE_LINUX_FTRACE) + list(APPEND ANGLE_DEFINITIONS + ANGLE_ENABLE_DEBUG_TRACE=1 + ) +endif() + if (WIN32) # FIXME: DX11 support will not compile if this preprocessor definition is set # DirectX Documentation is setting that version to 0x700 but there is no @@ -120,8 +126,8 @@ set(zlib_wrapper_sources ) set(angle_gl_enum_utils - "src/libANGLE/gl_enum_utils.cpp" - "src/libANGLE/gl_enum_utils_autogen.cpp" + "src/common/gl_enum_utils.cpp" + "src/common/gl_enum_utils_autogen.cpp" ) WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() @@ -140,6 +146,7 @@ if (USE_ANGLE_EGL OR ENABLE_WEBGL) ${libangle_image_util_headers} ${xxhash_sources} ${zlib_wrapper_sources} + ${angle_gl_enum_utils} ) target_include_directories(ANGLE PRIVATE ${ANGLE_PRIVATE_INCLUDE_DIRECTORIES}) target_compile_definitions(ANGLE PRIVATE diff --git a/Source/ThirdParty/ANGLE/include/CMakeLists.txt b/Source/ThirdParty/ANGLE/include/CMakeLists.txt index 853aef2a174e0..cf6a4dfa18613 100644 --- a/Source/ThirdParty/ANGLE/include/CMakeLists.txt +++ b/Source/ThirdParty/ANGLE/include/CMakeLists.txt @@ -47,6 +47,16 @@ if (ENABLE_WEBGL) ) endif () +if (USE_LINUX_FTRACE) + set(platform_headers ${includes}) + list(FILTER platform_headers INCLUDE REGEX "platform/PlatformMethods.h") + + WEBKIT_COPY_FILES(ANGLEPlatformHeaders + DESTINATION ${ANGLE_FRAMEWORK_HEADERS_DIR}/ANGLE + FILES ${platform_headers} + ) +endif() + # Cocoa expects headers in an ANGLE directory WEBKIT_COPY_FILES(GLSLANGHeaders DESTINATION ${ANGLE_FRAMEWORK_HEADERS_DIR}/ANGLE diff --git a/Source/ThirdParty/skia/CMakeLists.txt b/Source/ThirdParty/skia/CMakeLists.txt index ea5f4a577134c..862cf951de6e8 100644 --- a/Source/ThirdParty/skia/CMakeLists.txt +++ b/Source/ThirdParty/skia/CMakeLists.txt @@ -850,12 +850,14 @@ add_library(Skia STATIC src/sksl/transform/SkSLEliminateDeadLocalVariables.cpp src/sksl/transform/SkSLEliminateEmptyStatements.cpp src/sksl/transform/SkSLEliminateUnreachableCode.cpp + src/sksl/transform/SkSLEliminateUnnecessaryBraces.cpp src/sksl/transform/SkSLFindAndDeclareBuiltinFunctions.cpp src/sksl/transform/SkSLFindAndDeclareBuiltinStructs.cpp src/sksl/transform/SkSLFindAndDeclareBuiltinVariables.cpp src/sksl/transform/SkSLHoistSwitchVarDeclarationsAtTopLevel.cpp src/sksl/transform/SkSLRenamePrivateSymbols.cpp src/sksl/transform/SkSLReplaceConstVarsWithLiterals.cpp + src/sksl/transform/SkSLReplaceSplatCastsWithSwizzles.cpp src/sksl/transform/SkSLRewriteIndexedSwizzle.cpp src/utils/SkCharToGlyphCache.cpp @@ -871,6 +873,9 @@ add_library(Skia STATIC src/utils/SkShaderUtils.cpp src/utils/SkShadowTessellator.cpp src/utils/SkShadowUtils.cpp + src/utils/SkJSON.cpp + src/utils/SkParse.cpp + src/utils/SkEventTracer.cpp src/opts/SkOpts_hsw.cpp src/opts/SkOpts_skx.cpp @@ -962,7 +967,6 @@ target_compile_definitions(Skia PUBLIC SK_DISABLE_LEGACY_IMAGE_READBUFFER SK_DISABLE_LEGACY_INIT_DECODERS SK_DISABLE_LEGACY_PNG_WRITEBUFFER - SK_DISABLE_TRACING SK_DISABLE_WEBGL_INTERFACE SK_ENABLE_PRECOMPILE @@ -975,6 +979,12 @@ target_compile_definitions(Skia PUBLIC SK_RELEASE ) +if (NOT USE_LINUX_FTRACE) + target_compile_definitions(Skia PUBLIC + SK_DISABLE_TRACING + ) +endif() + # # This saves some reference churning and ctor/dtor calls in the # implementation of the sk_sp<> smart pointer template. It needs to diff --git a/Source/WTF/wtf/linux/SystemTracingFTrace.h b/Source/WTF/wtf/linux/SystemTracingFTrace.h index f91146f587ff9..737f51aa3959a 100644 --- a/Source/WTF/wtf/linux/SystemTracingFTrace.h +++ b/Source/WTF/wtf/linux/SystemTracingFTrace.h @@ -24,7 +24,11 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -208,6 +212,117 @@ class SystemTracingFTrace { } } + void addMark(const char phase, std::span name, const char* format, va_list args) WTF_ATTRIBUTE_PRINTF(4, 0) { + // "||[|]" + Vector buffer(1024); + + size_t len = 0; + int ret; + + ret = snprintf(buffer.data(), buffer.size(), "%c|%u|%.*s", phase, m_pid, name.size(), name.data()); + if (ret < 0) { + return; + } + len += ret; + + if (format && format[0] != '\0' && len < buffer.size()) { + buffer[len++] = (phase == 'I' ? ',' : '|'); // add args to the name so it is easier to see data in timeline + ret = vsnprintf(buffer.data() + len, buffer.size() - len, format, args); + if (ret < 0) { + return; + } + len += ret; + } + + writeFTraceMarker(buffer.data(), std::min(buffer.size() - 1, len)); + } + + void addMark(const char phase, std::span name, const char *format, ...) WTF_ATTRIBUTE_PRINTF(4, 5) { + va_list args; + va_start(args, format); + addMark(phase, WTFMove(name), format, args); + va_end(args); + } + + void addMark(const char phase, std::span name) { + addMark(phase, WTFMove(name), ""); + } + + void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + int numArgs, + const char** argNames, + const unsigned char* argTypes, + const unsigned long long* argValues, + unsigned char flags) { + UNUSED_PARAM(id); + UNUSED_PARAM(flags); + + // "||[|=,=...]" + StringBuilder builder; + + builder.append(phase, '|', String::number(m_pid), '|'); + builder.append(StringView::fromLatin1(reinterpret_cast(categoryEnabled)), ':', StringView::fromLatin1(name)); + + for (int i = 0; i < numArgs; ++i) { + union TraceArgValueUnion { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; + } arg; + + enum TraceArgValueType : int8_t { + Bool = 1, + Uint = 2, + Int = 3, + Double = 4, + Pointer = 5, + String = 6, + CopyString = 7 + }; + + const auto argName = StringView::fromLatin1(argNames[i]); + arg.as_uint = argValues[i]; + if (i == 0) + builder.append('|'); + else + builder.append(','); + builder.append(argName, '='); + + switch(argTypes[i]) { + case TraceArgValueType::String: + case TraceArgValueType::CopyString: + builder.append(StringView::fromLatin1(arg.as_string)); + break; + case TraceArgValueType::Bool: + builder.append(arg.as_bool ? "true"_s : "false"_s); + break; + case TraceArgValueType::Uint: + builder.append(String::number(arg.as_uint)); + break; + case TraceArgValueType::Int: + builder.append(String::number(arg.as_int)); + break; + case TraceArgValueType::Double: + builder.append(String::number(arg.as_double)); + break; + case TraceArgValueType::Pointer: + builder.append("0x"_s, hex(reinterpret_cast(arg.as_pointer))); + break; + default: + break; + } + } + + const auto buffer = spanReinterpretCast(builder.span()); + writeFTraceMarker(buffer.data(), buffer.size()); + } + static bool isEnabled() { return !(instance().m_traceMarkerFd < 0); } diff --git a/Source/WebCore/platform/Skia.cmake b/Source/WebCore/platform/Skia.cmake index c14a1b2e20cfc..4122193965955 100644 --- a/Source/WebCore/platform/Skia.cmake +++ b/Source/WebCore/platform/Skia.cmake @@ -16,6 +16,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS platform/graphics/skia/SkiaAcceleratedBufferPool.h platform/graphics/skia/SkiaHarfBuzzFont.h platform/graphics/skia/SkiaHarfBuzzFontCache.h + platform/graphics/skia/SkiaEventTracer.h ) list(APPEND WebCore_LIBRARIES diff --git a/Source/WebCore/platform/graphics/angle/PlatformDisplayANGLE.cpp b/Source/WebCore/platform/graphics/angle/PlatformDisplayANGLE.cpp index 0bc958c35fffa..e4a5348ec60b0 100644 --- a/Source/WebCore/platform/graphics/angle/PlatformDisplayANGLE.cpp +++ b/Source/WebCore/platform/graphics/angle/PlatformDisplayANGLE.cpp @@ -25,8 +25,51 @@ #include "GLContext.h" #include "Logging.h" +#if USE(LINUX_FTRACE) +#include +#include +#include +ALLOW_UNUSED_PARAMETERS_BEGIN +#include +ALLOW_UNUSED_PARAMETERS_END +#endif + namespace WebCore { +#if USE(LINUX_FTRACE) +static const unsigned char* ANGLE_getTraceCategoryEnabledFlag(angle::PlatformMethods* platform, + const char* categoryGroup) { + UNUSED_PARAM(platform); + return reinterpret_cast(categoryGroup); +} + +static angle::TraceEventHandle ANGLE_addTraceEvent(angle::PlatformMethods* platform, + char phase, + const unsigned char* categoryGroupEnabled, + const char* name, + unsigned long long id, + double timestamp, + int numArgs, + const char** argNames, + const unsigned char* argTypes, + const unsigned long long* argValues, + unsigned char flags) { + UNUSED_PARAM(platform); + UNUSED_PARAM(timestamp); + + SystemTracingFTrace::instance().addTraceEvent( + phase, categoryGroupEnabled, name, id, + numArgs, argNames, argTypes, argValues, flags); + + return static_cast(0); +} + +static double ANGLE_monotonicallyIncreasingTime(angle::PlatformMethods* platform) { + UNUSED_PARAM(platform); + return MonotonicTime::now().secondsSinceEpoch().value(); +} +#endif + EGLDisplay PlatformDisplay::angleEGLDisplay() const { #if PLATFORM(WIN) @@ -55,6 +98,22 @@ EGLDisplay PlatformDisplay::angleEGLDisplay() const if (angleDisplay == EGL_NO_DISPLAY) return EGL_NO_DISPLAY; +#if USE(LINUX_FTRACE) + if (SystemTracingFTrace::isEnabled()) { + angle::GetDisplayPlatformFunc getPlatform = reinterpret_cast( + EGL_GetProcAddress("ANGLEGetDisplayPlatform")); + if (getPlatform) { + angle::PlatformMethods* platformMethods = nullptr; + if (getPlatform(angleDisplay, angle::g_PlatformMethodNames, angle::g_NumPlatformMethods, + nullptr, &platformMethods)) { + platformMethods->addTraceEvent = ANGLE_addTraceEvent; + platformMethods->getTraceCategoryEnabledFlag = ANGLE_getTraceCategoryEnabledFlag; + platformMethods->monotonicallyIncreasingTime = ANGLE_monotonicallyIncreasingTime; + } + }; + } +#endif + EGLint majorVersion, minorVersion; if (EGL_Initialize(angleDisplay, &majorVersion, &minorVersion) == EGL_TRUE) { LOG(WebGL, "ANGLE initialised Major: %d Minor: %d", majorVersion, minorVersion); diff --git a/Source/WebCore/platform/graphics/skia/SkiaEventTracer.h b/Source/WebCore/platform/graphics/skia/SkiaEventTracer.h new file mode 100644 index 0000000000000..7e7fa0a03f67c --- /dev/null +++ b/Source/WebCore/platform/graphics/skia/SkiaEventTracer.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2026 RDK Management. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "config.h" + +#if USE(SKIA) +#include + +#include +#include + +namespace WebCore { + +class SkWebKitTrace final : public SkEventTracer { +public: + SkWebKitTrace() = default; + + SkEventTracer::Handle addTraceEvent( + char phase, + const uint8_t* categoryEnabledFlag, + const char* name, + uint64_t id, + int numArgs, + const char** argNames, + const uint8_t* argTypes, + const uint64_t* argValues, + uint8_t flags) override + { + UNUSED_PARAM(phase); + UNUSED_PARAM(categoryEnabledFlag); + UNUSED_PARAM(name); + UNUSED_PARAM(id); + UNUSED_PARAM(numArgs); + UNUSED_PARAM(argNames); + UNUSED_PARAM(argTypes); + UNUSED_PARAM(argValues); + UNUSED_PARAM(flags); +#if USE(LINUX_FTRACE) + if (TRACE_EVENT_PHASE_COMPLETE == phase) + phase = TRACE_EVENT_PHASE_BEGIN; + SystemTracingFTrace::instance().addTraceEvent( + phase, categoryEnabledFlag, name, id, + numArgs, argNames, argTypes, argValues, flags); +#endif + return static_cast(0); + } + + void updateTraceEventDuration(const uint8_t* categoryEnabledFlag, + const char* name, + SkEventTracer::Handle handle) override + { + UNUSED_PARAM(categoryEnabledFlag); + UNUSED_PARAM(name); + UNUSED_PARAM(handle); +#if USE(LINUX_FTRACE) + SystemTracingFTrace::instance().addTraceEvent( + TRACE_EVENT_PHASE_END, categoryEnabledFlag, name, 0, + 0, nullptr, nullptr, nullptr, 0x0); +#endif + } + + const uint8_t* getCategoryGroupEnabled(const char* name) override { + // Skip the default prefix that Skia uses for all trace events + const char* prefixPtr = "disabled-by-default-"; + const char* namePtr = name; + while (*prefixPtr == *namePtr && *prefixPtr != '\0') { + ++prefixPtr; + ++namePtr; + } + return reinterpret_cast(namePtr); + } + + const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) override { + UNUSED_PARAM(categoryEnabledFlag); + static const char* category = "skiaTrace"; + return category; + } +}; + +} +#endif diff --git a/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp b/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp index 504da10bc1e88..1892c67cbe969 100644 --- a/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp +++ b/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp @@ -51,14 +51,17 @@ ALLOW_COMMA_BEGIN #include #include #include +#include #include #include +#include ALLOW_UNUSED_PARAMETERS_END ALLOW_COMMA_END #include #include +#include #if PLATFORM(COCOA) #include "VP9UtilitiesCocoa.h" @@ -66,8 +69,39 @@ ALLOW_COMMA_END namespace WebCore { +#if USE(LINUX_FTRACE) +static const unsigned char* getCategoryEnabled(const char* name) { + const char* prefixPtr = TRACE_DISABLED_BY_DEFAULT(""); + const char* namePtr = name; + // Check whether name contains the default-disabled prefix. + while (*prefixPtr == *namePtr && *prefixPtr != '\0') { + ++prefixPtr; + ++namePtr; + } + return reinterpret_cast(*prefixPtr == '\0' ? "" : name); +} + +static void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + int numArgs, + const char** argNames, + const unsigned char* argTypes, + const unsigned long long* argValues, + unsigned char flags) { + SystemTracingFTrace::instance().addTraceEvent( + phase, categoryEnabled, name, id, + numArgs, argNames, argTypes, argValues, flags); +} +#endif + LibWebRTCProvider::LibWebRTCProvider() { +#if USE(LINUX_FTRACE) + if (SystemTracingFTrace::isEnabled()) + webrtc::SetupEventTracer(getCategoryEnabled, addTraceEvent); +#endif } LibWebRTCProvider::~LibWebRTCProvider() diff --git a/Source/WebKit/WebProcess/wpe/WebProcessMainWPE.cpp b/Source/WebKit/WebProcess/wpe/WebProcessMainWPE.cpp index 3d4a611d830a8..31088ef692795 100644 --- a/Source/WebKit/WebProcess/wpe/WebProcessMainWPE.cpp +++ b/Source/WebKit/WebProcess/wpe/WebProcessMainWPE.cpp @@ -43,8 +43,11 @@ #include #endif -#if USE(SYSPROF_CAPTURE) +#if USE(SYSPROF_CAPTURE) || USE(LINUX_FTRACE) #include +#if USE(SKIA) +#include +#endif #endif namespace WebKit { @@ -64,6 +67,10 @@ class WebProcessMainWPE final : public AuxiliaryProcessMainBase { #if USE(SKIA) SkGraphics::Init(); +#if USE(LINUX_FTRACE) + if (SystemTracingFTrace::isEnabled()) + SkEventTracer::SetInstance(new SkWebKitTrace(), true); +#endif #endif #if ENABLE(DEVELOPER_MODE) From 0cf5fcc663af4a1e1bcd7542f4a93f042e90d1e5 Mon Sep 17 00:00:00 2001 From: Eugene Mutavchi Date: Fri, 16 Jan 2026 10:55:10 -0500 Subject: [PATCH 4/4] [ftrace] write data provided to async markers too --- Source/WTF/wtf/linux/SystemTracingFTrace.h | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Source/WTF/wtf/linux/SystemTracingFTrace.h b/Source/WTF/wtf/linux/SystemTracingFTrace.h index 737f51aa3959a..b3b1a85bdf6c1 100644 --- a/Source/WTF/wtf/linux/SystemTracingFTrace.h +++ b/Source/WTF/wtf/linux/SystemTracingFTrace.h @@ -94,7 +94,6 @@ class SystemTracingFTrace { case TakeSnapshotStart: case SyntheticMomentumStart: case CommitLayerTreeStart: - case ProcessLaunchStart: case InitializeSandboxStart: case WebXRCPFrameWaitStart: case WebXRCPFrameStartSubmissionStart: @@ -154,7 +153,6 @@ class SystemTracingFTrace { case TakeSnapshotEnd: case SyntheticMomentumEnd: case CommitLayerTreeEnd: - case ProcessLaunchEnd: case InitializeSandboxEnd: case WebXRCPFrameWaitEnd: case WebXRCPFrameStartSubmissionEnd: @@ -167,17 +165,19 @@ class SystemTracingFTrace { case LayerFlushEnd: case UpdateLayerContentBuffersEnd: #endif - endSyncMark(code); + endSyncMark(code, data1, data2, data3, data4); return; + case ProcessLaunchStart: case MainResourceLoadDidStartProvisional: case SubresourceLoadWillStart: - beginAsyncMark(code, data1); + beginAsyncMark(code, data1, data2, data3, data4); return; + case ProcessLaunchEnd: case MainResourceLoadDidEnd: case SubresourceLoadDidEnd: - endAsyncMark(code, data1); + endAsyncMark(code, data1, data2, data3, data4); return; case DisplayRefreshDispatchingToMainThread: @@ -334,23 +334,23 @@ class SystemTracingFTrace { addMark('B', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); } - inline void endSyncMark(TracePointCode code) { - // "E||" - addMark('E', tracePointCodeName(code).spanIncludingNullTerminator()); + inline void endSyncMark(TracePointCode code, uint64_t data1, uint64_t data2, uint64_t data3, uint64_t data4) { + // "E|||" + addMark('E', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); } - inline void beginAsyncMark(TracePointCode code, uint64_t cookie) { - // "S|||" - addMark('S', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64, cookie); + inline void beginAsyncMark(TracePointCode code, uint64_t data1, uint64_t data2, uint64_t data3, uint64_t data4) { + // "S||||" + addMark('S', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64 "|%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); } - inline void endAsyncMark(TracePointCode code, uint64_t cookie) { - // "F|||" - addMark('F', tracePointCodeName(code).spanIncludingNullTerminator(),"%" PRIu64, cookie); + inline void endAsyncMark(TracePointCode code, uint64_t data1, uint64_t data2, uint64_t data3, uint64_t data4) { + // "F||||" + addMark('F', tracePointCodeName(code).spanIncludingNullTerminator(), "%" PRIu64 "|%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); } inline void instantMark(TracePointCode code, uint64_t data1, uint64_t data2, uint64_t data3, uint64_t data4) { - // "I||" + // "I||," addMark('I', tracePointCodeName(code).spanIncludingNullTerminator(),"%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64, data1, data2, data3, data4); }