Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions entry/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,13 @@ if(RDP_BUILD_TESTS)
test/rdp_certificate_policy_test.cpp
test/rdp_auth_identity_policy_test.cpp
test/rdp_performance_policy_test.cpp
test/rdp_h264_capability_gate_test.cpp
test/transfer_runtime_status_test.cpp
test/rdp_input_queue_test.cpp
test/gl_surface_lifecycle_policy_test.cpp
test/native_image_context_policy_test.cpp
test/decoder_recovery_policy_test.cpp
test/decoder_lifecycle_gate_test.cpp
test/safe_log_test.cpp
common/safe_log.cpp
rdp/rdp_audio_policy.cpp
Expand Down
7 changes: 7 additions & 0 deletions entry/src/main/cpp/extensions/extension_loader_napi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,13 @@ napi_value NapiGetRdpRenderStats(napi_env env, napi_callback_info info) {
SetObjectInt64(env, result, "inputDroppedMouseMoves", stats.inputDroppedMouseMoves);
SetObjectInt64(env, result, "inputNonDisposableOverflow", stats.inputNonDisposableOverflow);
SetObjectString(env, result, "graphicsMode", stats.graphicsMode);
SetObjectBool(env, result, "h264Avc420Enabled", stats.h264Avc420Enabled);
SetObjectBool(env, result, "h264Avc444Enabled", stats.h264Avc444Enabled);
SetObjectBool(env, result, "h264DirectTextureEnabled", stats.h264DirectTextureEnabled);
SetObjectInt32(env, result, "h264PerformanceGainPermille", stats.h264PerformanceGainPermille);
SetObjectString(env, result, "h264Avc420Reason", stats.h264Avc420Reason);
SetObjectString(env, result, "h264Avc444Reason", stats.h264Avc444Reason);
SetObjectString(env, result, "h264DirectTextureReason", stats.h264DirectTextureReason);
return result;
}

Expand Down
7 changes: 7 additions & 0 deletions entry/src/main/cpp/extensions/protocol_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ struct RdpRenderStats {
int64_t inputDroppedMouseMoves = 0;
int64_t inputNonDisposableOverflow = 0;
std::string graphicsMode;
bool h264Avc420Enabled = false;
bool h264Avc444Enabled = false;
bool h264DirectTextureEnabled = false;
int h264PerformanceGainPermille = 0;
std::string h264Avc420Reason;
std::string h264Avc444Reason;
std::string h264DirectTextureReason;
};

/** SFTP 远端文件条目 */
Expand Down
47 changes: 40 additions & 7 deletions entry/src/main/cpp/rdp/freerdp_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "rdp_certificate_policy.h"
#include "rdp_frame_pump.h"
#include "rdp_graphics_lifecycle.h"
#include "rdp_h264_capability_gate.h"
#include "rdp_keymap.h"
#include "rdp_performance_policy.h"
#include "rdp_input_queue.h"
Expand Down Expand Up @@ -569,6 +570,7 @@ struct FreeRdpAdapter::Impl {
int lastFrameHeight = 0;
bool forceNextFullFrame = false;
std::string graphicsMode = "gdi";
RdpH264CapabilitySnapshot h264Capabilities;

void beginShutdownTrace() {
shutdownStartedUs.store(steadyNowUs(), std::memory_order_release);
Expand Down Expand Up @@ -798,19 +800,27 @@ static bool rdpGfxResetPathSafe() {
}

static bool rdpGfxH264PathSafe() {
// Keep H.264 disabled until decoder lifecycle, visual, and stress gates pass.
return false;
RdpH264CapabilityEvidence evidence;
evidence.gfxResetMatrixPassed = rdpGfxResetPathSafe();
return EvaluateRdpH264Capabilities(evidence).avc420Enabled;
}

static RdpPerformancePolicy::GraphicsMode applyRdpPerformanceSettings(rdpSettings* settings) {
static RdpPerformancePolicy::GraphicsMode applyRdpPerformanceSettings(
rdpSettings* settings, RdpH264CapabilitySnapshot* h264Capabilities) {
const bool compiledGfx = compiledWithRdpGfx();
const bool compiledH264 = compiledWithGfxH264();
const bool fallbackForThisConnection = g_nextConnectionGfxFallback.consume();
const bool gfxAvailable = compiledGfx && !fallbackForThisConnection;
const bool h264Available = compiledH264;
const bool gfxConsumerAvailable = rdpGfxPipelineConsumerAvailable();
const bool gfxResetSafe = rdpGfxResetPathSafe();
const bool h264PathSafe = rdpGfxH264PathSafe();
RdpH264CapabilityEvidence h264Evidence;
h264Evidence.gfxResetMatrixPassed = gfxResetSafe;
const RdpH264CapabilitySnapshot h264Gate = EvaluateRdpH264Capabilities(h264Evidence);
const bool h264PathSafe = h264Gate.avc420Enabled && rdpGfxH264PathSafe();
if (h264Capabilities) {
*h264Capabilities = h264Gate;
}
const RdpPerformancePolicy::Settings perf =
RdpPerformancePolicy::RecommendedLanSettings(gfxAvailable,
h264Available,
Expand Down Expand Up @@ -846,13 +856,18 @@ static RdpPerformancePolicy::GraphicsMode applyRdpPerformanceSettings(rdpSetting
freerdp_settings_set_uint32(settings, FreeRDP_FrameAcknowledge, perf.frameAcknowledge);

OH_LOG_INFO(LOG_APP,
"[RDP] performance settings: mode=%{public}s compiledGfx=%{public}s compiledH264=%{public}s gfxConsumer=%{public}s gfxResetSafe=%{public}s h264PathSafe=%{public}s nextFallback=%{public}s networkAuto=%{public}s connectionType=%{public}u gfx=%{public}s h264=%{public}s rfx=%{public}s frameAck=%{public}u",
"[RDP] performance settings: mode=%{public}s compiledGfx=%{public}s compiledH264=%{public}s gfxConsumer=%{public}s gfxResetSafe=%{public}s h264PathSafe=%{public}s h264Reason=%{public}s avc444=%{public}s avc444Reason=%{public}s directTexture=%{public}s directTextureReason=%{public}s nextFallback=%{public}s networkAuto=%{public}s connectionType=%{public}u gfx=%{public}s h264=%{public}s rfx=%{public}s frameAck=%{public}u",
RdpPerformancePolicy::GraphicsModeName(mode),
compiledGfx ? "true" : "false",
compiledH264 ? "true" : "false",
gfxConsumerAvailable ? "true" : "false",
gfxResetSafe ? "true" : "false",
h264PathSafe ? "true" : "false",
RdpH264GateReasonName(h264Gate.avc420Reason),
h264Gate.avc444Enabled ? "true" : "false",
RdpH264GateReasonName(h264Gate.avc444Reason),
h264Gate.directTextureEnabled ? "true" : "false",
RdpH264GateReasonName(h264Gate.directTextureReason),
fallbackForThisConnection ? "true" : "false",
freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect) ? "true" : "false",
freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType),
Expand Down Expand Up @@ -1535,7 +1550,14 @@ BOOL FreeRdpAdapter::cbDesktopResize(rdpContext* context) {
}

const bool success = resized && pumpStarted;
adapter->impl_->graphicsLifecycle.completeResize(ticket.epoch, success);
const bool committed =
adapter->impl_->graphicsLifecycle.completeResize(ticket.epoch, success);
if (!committed) {
OH_LOG_WARN(LOG_APP,
"[RDP-RESIZE] stale completion ignored epoch=%{public}llu [E-RDP-RESIZE-STALE]",
static_cast<unsigned long long>(ticket.epoch));
return FALSE;
}
adapter->impl_->presentationEnabled.store(success, std::memory_order_release);
if (!success) {
const RdpGraphicsLifecycleSnapshot lifecycle =
Expand Down Expand Up @@ -1936,10 +1958,13 @@ void FreeRdpAdapter::connectThreadFunc() {
freerdp_settings_set_bool(s, FreeRDP_RestrictedAdminModeRequired, FALSE);
freerdp_settings_set_bool(s, FreeRDP_RestrictedAdminModeSupported, FALSE);
freerdp_settings_set_bool(s, FreeRDP_SupportErrorInfoPdu, TRUE);
const RdpPerformancePolicy::GraphicsMode graphicsMode = applyRdpPerformanceSettings(s);
RdpH264CapabilitySnapshot h264Capabilities;
const RdpPerformancePolicy::GraphicsMode graphicsMode =
applyRdpPerformanceSettings(s, &h264Capabilities);
{
std::lock_guard<std::mutex> renderLock(impl_->renderMutex);
impl_->graphicsMode = RdpPerformancePolicy::GraphicsModeName(graphicsMode);
impl_->h264Capabilities = h264Capabilities;
}
impl_->graphicsLifecycle.reset(
static_cast<int>(freerdp_settings_get_uint32(s, FreeRDP_DesktopWidth)),
Expand Down Expand Up @@ -2307,6 +2332,14 @@ RdpRenderStats FreeRdpAdapter::getRdpRenderStats() {
stats.desktopResizeFailures = graphics.resizeFailures;
stats.gfxChannelConnected = graphics.gfxInitialized;
stats.graphicsMode = impl_->graphicsMode;
stats.h264Avc420Enabled = impl_->h264Capabilities.avc420Enabled;
stats.h264Avc444Enabled = impl_->h264Capabilities.avc444Enabled;
stats.h264DirectTextureEnabled = impl_->h264Capabilities.directTextureEnabled;
stats.h264PerformanceGainPermille = impl_->h264Capabilities.performanceGainPermille;
stats.h264Avc420Reason = RdpH264GateReasonName(impl_->h264Capabilities.avc420Reason);
stats.h264Avc444Reason = RdpH264GateReasonName(impl_->h264Capabilities.avc444Reason);
stats.h264DirectTextureReason =
RdpH264GateReasonName(impl_->h264Capabilities.directTextureReason);
{
std::lock_guard<std::mutex> inputLock(impl_->inputQueueMutex);
stats.inputQueueDepth = static_cast<int>(impl_->inputQueue.depth());
Expand Down
11 changes: 8 additions & 3 deletions entry/src/main/cpp/rdp/rdp_graphics_lifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ RdpResizeTicket RdpGraphicsLifecycle::beginResize(int width, int height) {
}
snapshot_.resizeInProgress = true;
snapshot_.presentationAllowed = false;
++snapshot_.epoch;
++nextResizeEpoch_;
if (nextResizeEpoch_ == 0) {
++nextResizeEpoch_;
}
snapshot_.epoch = nextResizeEpoch_;
pendingWidth_ = width;
pendingHeight_ = height;
ticket.accepted = true;
Expand All @@ -37,10 +41,10 @@ RdpResizeTicket RdpGraphicsLifecycle::beginResize(int width, int height) {
return ticket;
}

void RdpGraphicsLifecycle::completeResize(uint64_t epoch, bool success) {
bool RdpGraphicsLifecycle::completeResize(uint64_t epoch, bool success) {
std::lock_guard<std::mutex> lock(mutex_);
if (!snapshot_.resizeInProgress || epoch == 0 || epoch != snapshot_.epoch) {
return;
return false;
}
snapshot_.resizeInProgress = false;
if (success) {
Expand All @@ -54,6 +58,7 @@ void RdpGraphicsLifecycle::completeResize(uint64_t epoch, bool success) {
}
pendingWidth_ = 0;
pendingHeight_ = 0;
return true;
}

RdpGfxChannelAction RdpGraphicsLifecycle::onChannelConnected(uintptr_t context) {
Expand Down
3 changes: 2 additions & 1 deletion entry/src/main/cpp/rdp/rdp_graphics_lifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class RdpGraphicsLifecycle {

void reset(int width, int height, bool gfxRequested);
RdpResizeTicket beginResize(int width, int height);
void completeResize(uint64_t epoch, bool success);
bool completeResize(uint64_t epoch, bool success);

RdpGfxChannelAction onChannelConnected(uintptr_t context);
void completeChannelInitialization(uintptr_t context, bool success);
Expand All @@ -53,6 +53,7 @@ class RdpGraphicsLifecycle {
RdpGraphicsLifecycleSnapshot snapshot_;
int pendingWidth_ = 0;
int pendingHeight_ = 0;
uint64_t nextResizeEpoch_ = 0;
bool channelInitializing_ = false;
};

Expand Down
117 changes: 117 additions & 0 deletions entry/src/main/cpp/rdp/rdp_h264_capability_gate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#ifndef RDP_H264_CAPABILITY_GATE_H
#define RDP_H264_CAPABILITY_GATE_H

#include <cstdint>

enum class RdpH264GateReason {
Ready = 0,
GfxResetMatrixPending,
Avc420LifecyclePending,
Avc420CompositionPending,
DeviceProfileUnsupported,
PerformanceEvidenceMissing,
PerformanceGainInsufficient,
StabilityMatrixPending,
Avc444LifecyclePending,
Avc444CompositionPending,
DirectTextureLifecyclePending,
CrossSurfaceZeroCopyPending,
};

struct RdpH264CapabilityEvidence {
bool gfxResetMatrixPassed = false;
bool avc420LifecyclePassed = false;
bool avc420CompositionSupported = false;
bool deviceProfileSupported = false;
int64_t gdiDamageP95Us = 0;
int64_t hardwareP95Us = 0;
bool stabilityMatrixPassed = false;
bool avc444LifecyclePassed = false;
bool avc444CompositionSupported = false;
bool directTextureLifecyclePassed = false;
bool crossSurfaceZeroCopyPassed = false;
};

struct RdpH264CapabilitySnapshot {
bool avc420Enabled = false;
bool avc444Enabled = false;
bool directTextureEnabled = false;
int performanceGainPermille = 0;
RdpH264GateReason avc420Reason = RdpH264GateReason::GfxResetMatrixPending;
RdpH264GateReason avc444Reason = RdpH264GateReason::Avc420LifecyclePending;
RdpH264GateReason directTextureReason = RdpH264GateReason::Avc420LifecyclePending;
};

inline int RdpH264PerformanceGainPermille(int64_t baselineP95Us, int64_t candidateP95Us) {
if (baselineP95Us <= 0 || candidateP95Us < 0 || candidateP95Us >= baselineP95Us) {
return 0;
}
return static_cast<int>(((baselineP95Us - candidateP95Us) * 1000) / baselineP95Us);
}

inline RdpH264GateReason EvaluateAvc420Reason(const RdpH264CapabilityEvidence& evidence) {
if (!evidence.gfxResetMatrixPassed) return RdpH264GateReason::GfxResetMatrixPending;
if (!evidence.avc420LifecyclePassed) return RdpH264GateReason::Avc420LifecyclePending;
if (!evidence.avc420CompositionSupported) return RdpH264GateReason::Avc420CompositionPending;
if (!evidence.deviceProfileSupported) return RdpH264GateReason::DeviceProfileUnsupported;
if (evidence.gdiDamageP95Us <= 0 || evidence.hardwareP95Us <= 0) {
return RdpH264GateReason::PerformanceEvidenceMissing;
}
if (RdpH264PerformanceGainPermille(evidence.gdiDamageP95Us, evidence.hardwareP95Us) < 300) {
return RdpH264GateReason::PerformanceGainInsufficient;
}
if (!evidence.stabilityMatrixPassed) return RdpH264GateReason::StabilityMatrixPending;
return RdpH264GateReason::Ready;
}

inline RdpH264CapabilitySnapshot EvaluateRdpH264Capabilities(
const RdpH264CapabilityEvidence& evidence) {
RdpH264CapabilitySnapshot snapshot;
snapshot.performanceGainPermille =
RdpH264PerformanceGainPermille(evidence.gdiDamageP95Us, evidence.hardwareP95Us);
snapshot.avc420Reason = EvaluateAvc420Reason(evidence);
snapshot.avc420Enabled = snapshot.avc420Reason == RdpH264GateReason::Ready;

if (!snapshot.avc420Enabled) {
snapshot.avc444Reason = snapshot.avc420Reason;
snapshot.directTextureReason = snapshot.avc420Reason;
return snapshot;
}
if (!evidence.avc444LifecyclePassed) {
snapshot.avc444Reason = RdpH264GateReason::Avc444LifecyclePending;
} else if (!evidence.avc444CompositionSupported) {
snapshot.avc444Reason = RdpH264GateReason::Avc444CompositionPending;
} else {
snapshot.avc444Reason = RdpH264GateReason::Ready;
snapshot.avc444Enabled = true;
}
if (!evidence.directTextureLifecyclePassed) {
snapshot.directTextureReason = RdpH264GateReason::DirectTextureLifecyclePending;
} else if (!evidence.crossSurfaceZeroCopyPassed) {
snapshot.directTextureReason = RdpH264GateReason::CrossSurfaceZeroCopyPending;
} else {
snapshot.directTextureReason = RdpH264GateReason::Ready;
snapshot.directTextureEnabled = true;
}
return snapshot;
}

inline const char* RdpH264GateReasonName(RdpH264GateReason reason) {
switch (reason) {
case RdpH264GateReason::Ready: return "ready";
case RdpH264GateReason::GfxResetMatrixPending: return "gfx-reset-matrix-pending";
case RdpH264GateReason::Avc420LifecyclePending: return "avc420-lifecycle-pending";
case RdpH264GateReason::Avc420CompositionPending: return "avc420-composition-pending";
case RdpH264GateReason::DeviceProfileUnsupported: return "device-profile-unsupported";
case RdpH264GateReason::PerformanceEvidenceMissing: return "performance-evidence-missing";
case RdpH264GateReason::PerformanceGainInsufficient: return "performance-gain-insufficient";
case RdpH264GateReason::StabilityMatrixPending: return "stability-matrix-pending";
case RdpH264GateReason::Avc444LifecyclePending: return "avc444-lifecycle-pending";
case RdpH264GateReason::Avc444CompositionPending: return "avc444-composition-pending";
case RdpH264GateReason::DirectTextureLifecyclePending: return "direct-texture-lifecycle-pending";
case RdpH264GateReason::CrossSurfaceZeroCopyPending: return "cross-surface-zero-copy-pending";
default: return "unknown";
}
}

#endif
Loading
Loading