@@ -727,24 +727,27 @@ fn gpu_circle_crop_with_zoom() {
727727fn gpu_should_use_gpu_heuristic ( ) {
728728 use super :: gpu:: should_use_gpu;
729729
730- // Single small layer → CPU.
730+ // Single small layer, RGBA output → CPU.
731731 let small_layer = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
732732 assert ! (
733- !should_use_gpu( 320 , 240 , & [ Some ( small_layer) ] , & [ ] , & [ ] ) ,
733+ !should_use_gpu( 320 , 240 , & [ Some ( small_layer) ] , & [ ] , & [ ] , None ) ,
734734 "Single small layer should prefer CPU"
735735 ) ;
736736
737737 // Two layers → GPU.
738738 let l1 = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
739739 let l2 = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
740740 assert ! (
741- should_use_gpu( 320 , 240 , & [ Some ( l1) , Some ( l2) ] , & [ ] , & [ ] ) ,
741+ should_use_gpu( 320 , 240 , & [ Some ( l1) , Some ( l2) ] , & [ ] , & [ ] , None ) ,
742742 "Two layers should prefer GPU"
743743 ) ;
744744
745745 // 1080p single layer → GPU (high pixel count).
746746 let big_layer = make_layer ( solid_rgba ( 1920 , 1080 , 0 , 0 , 0 , 255 ) , 1920 , 1080 , None ) ;
747- assert ! ( should_use_gpu( 1920 , 1080 , & [ Some ( big_layer) ] , & [ ] , & [ ] ) , "1080p should prefer GPU" ) ;
747+ assert ! (
748+ should_use_gpu( 1920 , 1080 , & [ Some ( big_layer) ] , & [ ] , & [ ] , None ) ,
749+ "1080p should prefer GPU"
750+ ) ;
748751
749752 // Single layer with rotation → GPU (effects).
750753 let rotated = make_layer_with_props (
@@ -761,9 +764,30 @@ fn gpu_should_use_gpu_heuristic() {
761764 CropShape :: Rect ,
762765 ) ;
763766 assert ! (
764- should_use_gpu( 320 , 240 , & [ Some ( rotated) ] , & [ ] , & [ ] ) ,
767+ should_use_gpu( 320 , 240 , & [ Some ( rotated) ] , & [ ] , & [ ] , None ) ,
765768 "Rotated layer should prefer GPU"
766769 ) ;
770+
771+ // Single small layer with NV12 output → GPU (YUV conversion offload).
772+ let nv12_layer = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
773+ assert ! (
774+ should_use_gpu( 320 , 240 , & [ Some ( nv12_layer) ] , & [ ] , & [ ] , Some ( PixelFormat :: Nv12 ) ) ,
775+ "NV12 output should prefer GPU even for single small layer"
776+ ) ;
777+
778+ // Single small layer with I420 output → GPU (YUV conversion offload).
779+ let i420_layer = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
780+ assert ! (
781+ should_use_gpu( 320 , 240 , & [ Some ( i420_layer) ] , & [ ] , & [ ] , Some ( PixelFormat :: I420 ) ) ,
782+ "I420 output should prefer GPU even for single small layer"
783+ ) ;
784+
785+ // Single small layer with RGBA8 output → CPU (no conversion needed).
786+ let rgba_layer = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
787+ assert ! (
788+ !should_use_gpu( 320 , 240 , & [ Some ( rgba_layer) ] , & [ ] , & [ ] , Some ( PixelFormat :: Rgba8 ) ) ,
789+ "RGBA8 output should prefer CPU for single small layer"
790+ ) ;
767791}
768792
769793// ── Phase 2 tests ───────────────────────────────────────────────────────────
@@ -908,12 +932,13 @@ fn gpu_hysteresis_stability() {
908932
909933 // First 4 frames voting GPU should NOT flip (hysteresis = 5).
910934 for _ in 0 ..4 {
911- let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene, & [ ] , & [ ] ) ;
935+ let result =
936+ gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene, & [ ] , & [ ] , None ) ;
912937 assert ! ( !result, "Should stay on CPU during hysteresis window" ) ;
913938 }
914939
915940 // 5th consecutive frame should flip to GPU.
916- let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene, & [ ] , & [ ] ) ;
941+ let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene, & [ ] , & [ ] , None ) ;
917942 assert ! ( result, "Should flip to GPU after 5 consecutive votes" ) ;
918943
919944 // Now on GPU. Build a scene that votes CPU.
@@ -922,13 +947,13 @@ fn gpu_hysteresis_stability() {
922947
923948 // Interleave: vote CPU, then vote GPU — should reset the counter.
924949 for _ in 0 ..3 {
925- gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & cpu_scene, & [ ] , & [ ] ) ;
950+ gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & cpu_scene, & [ ] , & [ ] , None ) ;
926951 }
927952 // Interrupt with a GPU vote (re-add two layers).
928953 let l3 = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
929954 let l4 = make_layer ( solid_rgba ( 320 , 240 , 0 , 0 , 0 , 255 ) , 320 , 240 , None ) ;
930955 let gpu_scene2: Vec < Option < LayerSnapshot > > = vec ! [ Some ( l3) , Some ( l4) ] ;
931- let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene2, & [ ] , & [ ] ) ;
956+ let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene2, & [ ] , & [ ] , None ) ;
932957 assert ! ( result, "Interruption should reset counter; stay on GPU" ) ;
933958}
934959
@@ -943,7 +968,7 @@ fn gpu_hysteresis_seeded_skips_warmup() {
943968 let gpu_scene: Vec < Option < LayerSnapshot > > = vec ! [ Some ( l1) , Some ( l2) ] ;
944969
945970 // First frame should immediately use GPU — no warm-up.
946- let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene, & [ ] , & [ ] ) ;
971+ let result = gpu:: should_use_gpu_with_state ( & mut state, 320 , 240 , & gpu_scene, & [ ] , & [ ] , None ) ;
947972 assert ! ( result, "Seeded state should use GPU on the very first frame" ) ;
948973}
949974
0 commit comments