DF-3943 / interlace_sim.c
/* * interlace_sim.c - userland simulation of the INTERLACE dst.height * mutation in resource_build_scaling_params() * (sys/dev/drm/amd/display/dc/core/dc_resource.c:1118-1189) * * Reproduces, in plain C, the exact control flow: * entry: if (INTERLACE) stream->dst.height *= 2; [:1118-1119] * ... calculate_scaling_ratios(); calculate_viewport(); * fail: if (viewport.h < 16 || viewport.w < 16) return false; [:1125-1126] * ... (success path) ... * exit: if (INTERLACE) stream->dst.height /= 2; [:1188-1189] * * The kernel executes this against the SHARED, refcounted * struct dc_stream_state that outlives the failed validation. * Each failed validation attempt leaves dst.height doubled. * * Build: cc -O2 -o interlace_sim interlace_sim.c * Run: ./interlace_sim */ #include <stdio.h> #include <stdbool.h> struct rect { int x, y, width, height; }; struct stream_state { struct rect dst; bool interlace; int viewport_h, viewport_w; }; /* verbatim control flow of resource_build_scaling_params() */ static bool resource_build_scaling_params(struct stream_state *stream) { if (stream->interlace) stream->dst.height *= 2; /* dc_resource.c:1118-1119 */ /* calculate_scaling_ratios()/calculate_viewport() results summarized * by stream->viewport_{h,w}; a small plane (src_rect < 16px after * scaling into the viewport) yields viewport < 16 => validation fail */ if (stream->viewport_h < 16 || stream->viewport_w < 16) return false; /* dc_resource.c:1125-1126 -- /=2 SKIPPED */ /* ... taps, inits ... success path ... */ if (stream->interlace) stream->dst.height /= 2; /* dc_resource.c:1188-1189 */ return true; } int main(void) { struct stream_state s = { .dst = { 0, 0, 1920, 1080 }, .interlace = true, .viewport_h = 8, .viewport_w = 8 }; int i; printf("persistent dc_stream_state.dst.height over repeated FAILED " "interlaced validations (1080p interlaced + tiny plane):\n"); printf("attempt 0: dst.height=%d\n", s.dst.height); for (i = 1; i <= 23; i++) { bool ok = resource_build_scaling_params(&s); printf("attempt %d: %s dst.height=%d (0x%x)\n", i, ok ? "OK " : "FAIL", s.dst.height, s.dst.height); } printf("\nEvery failed attempt leaves the doubling unbalanced " "(early return at :1125 skips the /=2 at :1188).\n"); printf("dst.height overflows signed int after 21 doublings " "(1080 * 2^21 > INT_MAX) -> negative heights feed " "calculate_recout()/calculate_scaling_ratios().\n"); return 0; } |