1 STATIC
void fatal(u8
*fmt
, ...)
8 va_end(ap
); /* unreachable */
10 STATIC
void warning(u8
*fmt
, ...)
16 npv_vwarning(fmt
, ap
);
19 STATIC
void fatalff(u8
*fmt
, ...)
26 va_end(ap
); /* unreachable */
28 STATIC
void poutff(u8
*fmt
, ...)
37 STATIC
void fatalvk(u8
*fmt
, ...)
43 npv_vk_vfatal(fmt
, ap
);
44 va_end(ap
); /* unreachable */
46 STATIC
void warningvk(u8
*fmt
, ...)
52 npv_vk_vwarning(fmt
, ap
);
56 STATIC
void init_once_local(void)
61 memset(&tmp_mem_rqmts_l
, 0, sizeof(tmp_mem_rqmts_l
));
64 if (i
== npv_vk_swpchn_imgs_n_max
)
66 blit_l
[i
].vp
.width
= -1;
67 blit_l
[i
].vp
.height
= -1;
68 blit_l
[i
].vp
.top_left
.x
= -1;
69 blit_l
[i
].vp
.top_left
.y
= -1;
70 blit_l
[i
].vp
.top_left
.z
= -1;
71 blit_l
[i
].vp
.bottom_right
.x
= -1;
72 blit_l
[i
].vp
.bottom_right
.y
= -1;
73 blit_l
[i
].vp
.bottom_right
.z
= -1;
74 blit_l
[i
].update_requested
= true;
77 receive_fr_l
= avutil_video_fr_ref_alloc();
78 is_swpchn_sem_fence_submitted_l
= false;
79 drop_l
.prev_now
= AV_NOPTS_VALUE
;
80 drop_l
.until_resync
= false;
83 STATIC
void scaler_img_create(avutil_video_fr_ref_t
*fr
)
85 struct vk_img_create_info_t info
;
88 memset(&info
, 0, sizeof(info
));
89 info
.type
= vk_struct_type_img_create_info
;
90 info
.img_type
= vk_img_type_2d
;
91 info
.texel_mem_blk_fmt
= vk_texel_mem_blk_fmt_b8g8r8a8_srgb
;
92 info
.extent
.width
= (u32
)fr
->width
;
93 info
.extent
.height
= (u32
)fr
->height
;
94 info
.extent
.depth
= 1;
96 info
.samples_n
= vk_samples_n_1_bit
;
97 info
.array_layers_n
= 1;
98 info
.img_tiling
= vk_img_tiling_linear
;
99 info
.usage
= vk_img_usage_transfer_src_bit
;
100 info
.initial_layout
= vk_img_layout_undefined
;
101 vk_create_img(&info
, &scaler_p
.img
.vk
);
102 IF_FATALVVK("%d:device:%p:unable to create scaler frame image\n", r
, npv_vk_surf_p
.dev
.vk
);
104 STATIC
void img_mem_barrier_run_once(struct vk_img_mem_barrier_t
*b
)
107 struct vk_cb_begin_info_t begin_info
;
108 struct vk_submit_info_t submit_info
;
110 memset(&begin_info
, 0, sizeof(begin_info
));
111 begin_info
.type
= vk_struct_type_cb_begin_info
;
112 begin_info
.flags
= vk_cb_usage_one_time_submit_bit
;
113 /* we use the first cb which will be used for the swpchn */
114 vk_begin_cb(npv_vk_surf_p
.dev
.cbs
[0], &begin_info
);
115 IF_FATALVVK("%d:unable to begin recording the initial layout transition command buffer\n", r
, npv_vk_surf_p
.dev
.cbs
[0]);
116 /*--------------------------------------------------------------------*/
117 vk_cmd_pl_barrier(npv_vk_surf_p
.dev
.cbs
[0], b
);
118 /*--------------------------------------------------------------------*/
119 vk_end_cb(npv_vk_surf_p
.dev
.cbs
[0]);
120 IF_FATALVVK("%d:unable to end recording of the initial layout transition command buffer\n", r
, npv_vk_surf_p
.dev
.cbs
[0]);
121 /*--------------------------------------------------------------------*/
122 memset(&submit_info
, 0, sizeof(submit_info
));
123 submit_info
.type
= vk_struct_type_submit_info
;
124 submit_info
.cbs_n
= 1;
125 submit_info
.cbs
= &npv_vk_surf_p
.dev
.cbs
[0];
126 vk_q_submit(&submit_info
, 0);
127 IF_FATALVVK("%d:queue:%p:unable to submit the initial layout transition command buffer\n", r
, npv_vk_surf_p
.dev
.q
);
128 /*--------------------------------------------------------------------*/
130 IF_FATALVVK("%d:queue:%p:unable to wait for idle or completion of initial layout transition command buffer\n", r
, npv_vk_surf_p
.dev
.q
);
131 /*--------------------------------------------------------------------*/
133 * since it is tagged to run once its state_p is invalid, we need to
134 * reset it to the initial state_p
136 vk_reset_cb(npv_vk_surf_p
.dev
.cbs
[0]);
137 IF_FATALVVK("%d:command buffer:%p:unable to reset the initial layout transition command buffer\n", r
, npv_vk_surf_p
.dev
.cbs
[0]);
139 /* once in general layout, the dev sees the img */
140 STATIC
void scaler_img_layout_to_general(void)
142 struct vk_img_mem_barrier_t b
;
143 struct vk_img_subrsrc_range_t
*r
;
145 memset(&b
, 0, sizeof(b
));
146 b
.type
= vk_struct_type_img_mem_barrier
;
147 b
.old_layout
= vk_img_layout_undefined
;
148 b
.new_layout
= vk_img_layout_general
;
149 b
.src_q_fam
= vk_q_fam_ignored
;
150 b
.dst_q_fam
= vk_q_fam_ignored
;
151 b
.img
= scaler_p
.img
.vk
;
152 r
= &b
.subrsrc_range
;
153 r
->aspect
= vk_img_aspect_color_bit
;
155 r
->array_layers_n
= 1;
156 img_mem_barrier_run_once(&b
);
158 STATIC
void scaler_img_subrsrc_layout_get(void)
160 struct vk_img_subrsrc_t s
;
162 memset(&s
, 0, sizeof(s
));
163 /* 1 subrsrc = uniq color plane of mip lvl 0 and array 0 */
164 s
.aspect
= vk_img_aspect_color_bit
;
165 vk_get_img_subrsrc_layout(scaler_p
.img
.vk
, &s
, &scaler_p
.img
.layout
);
167 STATIC
void tmp_scaler_img_mem_rqmts_get(void)
169 struct vk_img_mem_rqmts_info_t info
;
170 struct vk_mem_rqmts_t
*rqmts
;
173 memset(&info
, 0, sizeof(info
));
174 info
.type
= vk_struct_type_img_mem_rqmts_info
;
175 info
.img
= scaler_p
.img
.vk
;
176 rqmts
= &tmp_mem_rqmts_l
;
177 memset(rqmts
, 0, sizeof(*rqmts
));
178 rqmts
->type
= vk_struct_type_mem_rqmts
;
179 vk_get_img_mem_rqmts(&info
, rqmts
);
180 IF_FATALVVK("%d:device:%p:unable to get memory requirements for scaler image\n", r
, npv_vk_surf_p
.dev
.vk
);
182 #define WANTED_MEM_PROPS (vk_mem_prop_host_visible_bit \
183 | vk_mem_prop_host_cached_bit)
184 #define IS_DEV_LOCAL(x) (((x)->prop_flags & vk_mem_prop_dev_local_bit) != 0)
185 STATIC
bool match_mem_type(u8 mem_type_idx
,
186 struct vk_mem_rqmts_t
*img_rqmts
, bool ignore_gpu_is_discret
)
188 struct vk_mem_type_t
*mem_type
;
190 /* first check this mem type is in our img rqmts */
191 if (((1 << mem_type_idx
) & img_rqmts
->core
.mem_type_bits
) == 0)
193 mem_type
= &npv_vk_surf_p
.dev
.phydev
.mem_types
[mem_type_idx
];
194 if (!ignore_gpu_is_discret
)
195 if (npv_vk_surf_p
.dev
.phydev
.is_discret_gpu
196 && IS_DEV_LOCAL(mem_type
))
198 if ((mem_type
->prop_flags
& WANTED_MEM_PROPS
) == WANTED_MEM_PROPS
)
202 #undef WANTED_MEM_PROPS
204 STATIC
bool try_alloc_scaler_img_dev_mem(struct vk_mem_rqmts_t
*img_rqmts
,
207 struct vk_mem_alloc_info_t info
;
210 memset(&info
, 0, sizeof(info
));
211 info
.type
= vk_struct_type_mem_alloc_info
;
212 info
.sz
= img_rqmts
->core
.sz
;
213 info
.mem_type_idx
= mem_type_idx
;
214 vk_alloc_mem(&info
, &scaler_p
.img
.dev_mem
);
216 warningvk("%d:device:%p:unable to allocate %lu bytes from physical dev %p memory type %u\n", r
, npv_vk_surf_p
.dev
.vk
, img_rqmts
->core
.sz
, npv_vk_surf_p
.dev
.phydev
.vk
, mem_type_idx
);
222 * we are looking for host visible and host cached mem. on discret gpu we would
223 * like non dev local mem that in order to avoid wasting video ram. if we have
224 * a discret gpu but could not find a mem type without dev local mem, let's
225 * retry with only host visible and host cached mem.
227 #define IGNORE_GPU_IS_DISCRET true
228 STATIC
void scaler_img_dev_mem_alloc(void)
230 struct vk_mem_rqmts_t
*img_rqmts
;
233 img_rqmts
= &tmp_mem_rqmts_l
;
236 if (mem_type
== npv_vk_surf_p
.dev
.phydev
.mem_types_n
)
238 if (match_mem_type(mem_type
, img_rqmts
, !IGNORE_GPU_IS_DISCRET
))
239 if (try_alloc_scaler_img_dev_mem(img_rqmts
, mem_type
))
243 if (!npv_vk_surf_p
.dev
.phydev
.is_discret_gpu
)
244 fatalvk("physical device:%p:scaler image:unable to find proper memory type or to allocate memory\n", npv_vk_surf_p
.dev
.phydev
.vk
);
246 * lookup again, but relax the match based on discret gpu constraint for
251 if (mem_type
== npv_vk_surf_p
.dev
.phydev
.mem_types_n
)
253 if (match_mem_type(mem_type
, img_rqmts
, IGNORE_GPU_IS_DISCRET
)
254 && try_alloc_scaler_img_dev_mem(img_rqmts
, mem_type
))
258 fatalvk("physical device:%p:unable to find proper memory type or to allocate memory\n", npv_vk_surf_p
.dev
.phydev
.vk
);
260 #undef IGNORE_GPU_IS_DISCRET
261 STATIC
void scaler_img_dev_mem_bind(void)
263 struct vk_bind_img_mem_info_t info
;
266 memset(&info
, 0, sizeof(info
) * 1);
267 info
.type
= vk_struct_type_bind_img_mem_info
;
268 info
.img
= scaler_p
.img
.vk
;
269 info
.mem
= scaler_p
.img
.dev_mem
;
271 * TODO: switch to vkBindImageMemory2 if extension in vk 1.1 for
274 vk_bind_img_mem(&info
);
275 IF_FATALVVK("%d:device:%p:scaler image:unable to bind device memory to image\n", r
, npv_vk_surf_p
.dev
.vk
);
277 STATIC
void scaler_img_dev_mem_map(void)
281 vk_map_mem(scaler_p
.img
.dev_mem
, &scaler_p
.img
.data
);
282 IF_FATALVVK("%d:device:%p:scaler image:unable to map image memory\n", r
, npv_vk_surf_p
.dev
.vk
);
284 STATIC
void dec_a_grow(void)
288 new_idx
= dec_frs_p
.n_max
;
289 dec_frs_p
.a
= realloc(dec_frs_p
.a
, sizeof(*dec_frs_p
.a
)
290 * (dec_frs_p
.n_max
+ 1));
291 if (dec_frs_p
.a
== 0)
292 fatal("unable to allocate memory for an additional pointer on a decoded frame reference\n");
293 dec_frs_p
.priv_a
= realloc(dec_frs_p
.priv_a
,
294 sizeof(*dec_frs_p
.priv_a
) * (dec_frs_p
.n_max
+ 1));
295 if (dec_frs_p
.priv_a
== 0)
296 fatal("unable to allocate memory for an additional pointer on private data for decoded frames\n");
298 dec_frs_p
.a
[new_idx
] = avutil_video_fr_ref_alloc();
299 if (dec_frs_p
.a
[new_idx
] == 0)
300 fatal("ffmpeg:unable to allocate a decoded frame reference\n");
301 dec_frs_p
.priv_a
[new_idx
] = calloc(1, sizeof(**dec_frs_p
.priv_a
));
302 if (dec_frs_p
.priv_a
[new_idx
] == 0)
303 fatal("unable to allocate decoded frame private data\n");
308 /* extract a fr ref, shift the a, push it back at the e, and unref its bufs */
309 STATIC
void fr_drop(u16 fr
)
311 struct dec_fr_priv_t
*priv_save
;
312 avutil_video_fr_ref_t
*save
;
314 priv_save
= dec_frs_p
.priv_a
[fr
];
315 if (!priv_save
->was_qed_to_pe
)
316 warning("dropping undisplayed frame\n");
317 save
= dec_frs_p
.a
[fr
];
318 avutil_video_fr_unref(save
);
319 memset(priv_save
, 0, sizeof(*priv_save
));
320 if (dec_frs_p
.n
> 1) {
324 memmove(&dec_frs_p
.a
[fr
], &dec_frs_p
.a
[fr
+ 1],
325 sizeof(*dec_frs_p
.a
) * (e
- (fr
+ 1)));
326 dec_frs_p
.a
[e
- 1] = save
;
328 memmove(&dec_frs_p
.priv_a
[fr
], &dec_frs_p
.priv_a
[fr
+ 1],
329 sizeof(*dec_frs_p
.priv_a
) * (e
- (fr
+ 1)));
330 dec_frs_p
.priv_a
[e
- 1] = priv_save
;
336 STATIC
void frs_drop(s64 now
, avutil_video_fr_ref_t
*selected_fr
)
343 if (selected_fr
== NO_FR
)
345 /* backward discont detected */
346 if (drop_l
.prev_now
!= AV_NOPTS_VALUE
&& now
< drop_l
.prev_now
)
347 drop_l
.until_resync
= true;
348 /*====================================================================*/
350 * since the frs are supposed inorder, first drop as many of as possible
351 * frs received before the selected one
355 if (dec_frs_p
.a
[fr
] == selected_fr
)
357 /* don't touch the scaler fr */
358 if (dec_frs_p
.a
[fr
] != scaler_p
.img
.fr
) {
359 if (dec_frs_p
.a
[fr
] == last_fr_sent_to_pe_l
)
360 last_fr_sent_to_pe_l
= NO_FR
;
361 fr_drop(fr
); /* do not advance */
365 /*====================================================================*/
367 * here, we detected a backward discont, we are looking for a
368 * resynchronizing fr based on a time win. we must drop, inorder,
369 * frs which are out of the time win in order to avoid the dec frs a
370 * being full and locked
372 if (!drop_l
.until_resync
)
374 resync
= (DISCONT_BACKWARD_RESYNC_MS
* st_p
.tb
.den
) / (st_p
.tb
.num
380 if (fr
== dec_frs_p
.n
)
382 /* don't touch the scaler fr or selected fr */
383 if (dec_frs_p
.a
[fr
] != scaler_p
.img
.fr
384 && dec_frs_p
.a
[fr
] != selected_fr
) {
385 if (dec_frs_p
.a
[fr
]->pts
< lo
386 || hi
< dec_frs_p
.a
[fr
]->pts
) {
387 if (dec_frs_p
.a
[fr
] == last_fr_sent_to_pe_l
)
388 last_fr_sent_to_pe_l
= NO_FR
;
389 fr_drop(fr
); /* do not advance */
390 } else { /* found a resynchronizing fr */
391 drop_l
.until_resync
= false;
398 drop_l
.prev_now
= now
;
403 STATIC
void select_fr(s64 now
, avutil_video_fr_ref_t
**selected_fr
,
404 struct dec_fr_priv_t
**selected_fr_priv
)
408 u64 selected_fr_delta
;
411 *selected_fr
= NO_FR
;
412 selected_fr_delta
= S64_MAX
;
415 npv_perr("DEBUG:%s:scanning %u(max=%u) frames, now=%ld\n", __func__
, dec_frs_p
.n
, dec_frs_p
.n_max
, now
);
420 if (fr_idx
== dec_frs_p
.n
)
422 delta
= s64_abs(now
- (s64
)dec_frs_p
.a
[fr_idx
]->pts
);
425 npv_perr("DEBUG:%s:frame %u pts=%ld delta=%lu/%lu ms\n", __func__
, fr_idx
, (s64
)dec_frs_p
.a
[fr_idx
]->pts
, delta
, (delta
* (u64
)st_p
.tb
.num
* 1000) / (u64
)st_p
.tb
.den
);
427 if (delta
< selected_fr_delta
) {
428 *selected_fr
= dec_frs_p
.a
[fr_idx
];
429 *selected_fr_priv
= dec_frs_p
.priv_a
[fr_idx
];
430 selected_fr_idx
= fr_idx
;
431 selected_fr_delta
= delta
;
437 STATIC
void frs_reset(void)
443 if (fr
== dec_frs_p
.n
)
445 avutil_video_fr_unref(dec_frs_p
.a
[fr
]);
446 memset(dec_frs_p
.priv_a
[fr
], 0, sizeof(**dec_frs_p
.priv_a
));
451 STATIC
void scaler_img_destroy(void)
453 vk_destroy_img(scaler_p
.img
.vk
);
455 vk_unmap_mem(scaler_p
.img
.dev_mem
);
456 scaler_p
.img
.data
= 0;
457 vk_free_mem(scaler_p
.img
.dev_mem
);
458 scaler_p
.img
.dev_mem
= 0;
460 STATIC
void blit_compute_offsets(u8 swpchn_img
,
461 struct vk_extent_2d_t
*new_vp
)
463 struct blit_vp_t
*vp
;
467 vp
= &blit_l
[swpchn_img
].vp
;
469 * XXX: THE BOUNDS OF THE BLIT ARE NOT PIXEL OFFSETS! THOSE ARE
470 * INTEGER BOUNDS FOR TEXELS COORDS WHICH ARE TAKEN AT THE CENTER OF
471 * EACH PIXEL: NAMELY LAST TEXEL INTEGER BOUND = LAST PIXEL OFFSET + 1.
473 want_width
= new_vp
->height
* aspect_ratio
.width
/ aspect_ratio
.height
;
474 want_height
= new_vp
->width
* aspect_ratio
.height
/ aspect_ratio
.width
;
475 if (want_width
< new_vp
->width
) {
479 vp
->bottom_right
.y
= new_vp
->height
;
481 gap
= new_vp
->width
- want_width
;
482 vp
->top_left
.x
= gap
/ 2;
483 vp
->bottom_right
.x
= new_vp
->width
- gap
/ 2;
484 } else if (want_height
< new_vp
->height
) {
488 vp
->bottom_right
.x
= new_vp
->width
;
490 gap
= new_vp
->height
- want_height
;
491 vp
->top_left
.y
= gap
/ 2;
492 vp
->bottom_right
.y
= new_vp
->height
- gap
/ 2;
496 vp
->bottom_right
.x
= new_vp
->width
;
497 vp
->bottom_right
.y
= new_vp
->height
;
499 /* keep track in order to detect change */
500 vp
->width
= new_vp
->width
;
501 vp
->height
= new_vp
->height
;
503 STATIC
void blit_setup(u8 swpchn_img
)
506 struct vk_cb_begin_info_t begin_info
;
507 struct vk_img_mem_barrier_t b
;
508 struct vk_img_blit_t region
;
509 struct vk_extent_2d_t
*current
;
510 union vk_clr_color_val_t clr_color_val
;
511 struct vk_img_subrsrc_range_t range
;
512 struct npv_vk_texel_mem_blk_fmt_t
*b8g8r8a8_srgb
;
515 current
= &npv_vk_surf_p
.dev
.phydev
.surf_caps
.core
.current_extent
;
517 if (!blit_l
[swpchn_img
].update_requested
518 && blit_l
[swpchn_img
].vp
.width
== current
->width
519 && blit_l
[swpchn_img
].vp
.height
== current
->height
)
522 blit_compute_offsets(swpchn_img
, current
);
524 /* sync: may be in pending state? */
525 vk_reset_cb(npv_vk_surf_p
.dev
.cbs
[swpchn_img
]);
526 IF_FATALVVK("%d:swapchain img:%u:command buffer:%p:unable reset\n", r
, swpchn_img
, npv_vk_surf_p
.dev
.cbs
[swpchn_img
]);
527 /*--------------------------------------------------------------------*/
528 memset(&begin_info
, 0, sizeof(begin_info
));
529 begin_info
.type
= vk_struct_type_cb_begin_info
;
530 vk_begin_cb(npv_vk_surf_p
.dev
.cbs
[swpchn_img
], &begin_info
);
531 IF_FATALVVK("%d:swapchain img:%u:command buffer:%p:unable to begin recording\n", r
, swpchn_img
, npv_vk_surf_p
.dev
.cbs
[swpchn_img
]);
532 /*--------------------------------------------------------------------*/
533 /* acquired img (undefined layout) to presentation layout */
534 memset(&b
, 0, sizeof(b
));
535 b
.type
= vk_struct_type_img_mem_barrier
;
536 b
.old_layout
= vk_img_layout_undefined
;
537 b
.new_layout
= vk_img_layout_present
;
538 b
.src_q_fam
= vk_q_fam_ignored
;
539 b
.dst_q_fam
= vk_q_fam_ignored
;
540 b
.img
= npv_vk_surf_p
.dev
.swpchn
.imgs
[swpchn_img
];
541 b
.subrsrc_range
.aspect
= vk_img_aspect_color_bit
;
542 b
.subrsrc_range
.lvls_n
= 1;
543 b
.subrsrc_range
.array_layers_n
= 1;
544 vk_cmd_pl_barrier(npv_vk_surf_p
.dev
.cbs
[swpchn_img
], &b
);
545 /*--------------------------------------------------------------------*/
546 /* clear the viewport with integer black pixels since we work in sRGB */
547 memset(&clr_color_val
, 0, sizeof(clr_color_val
));
548 memset(&range
, 0, sizeof(range
));
549 range
.aspect
= vk_img_aspect_color_bit
;
551 range
.array_layers_n
= 1;
552 vk_cmd_clr_color_img(npv_vk_surf_p
.dev
.cbs
[swpchn_img
],
553 npv_vk_surf_p
.dev
.swpchn
.imgs
[swpchn_img
],
554 vk_img_layout_present
, &clr_color_val
, 1,
556 /*--------------------------------------------------------------------*/
557 /* blit from cpu img to pe img */
558 memset(®ion
, 0, sizeof(region
));
559 region
.src_subrsrc
.aspect
= vk_img_aspect_color_bit
;
560 region
.src_subrsrc
.array_layers_n
= 1;
562 region
.src_offsets
[1].x
= scaler_p
.ctx
->cfg
.width
;
563 region
.src_offsets
[1].y
= scaler_p
.ctx
->cfg
.height
;
564 region
.src_offsets
[1].z
= 1; /* see vk specs */
565 region
.dst_subrsrc
.aspect
= vk_img_aspect_color_bit
;
566 region
.dst_subrsrc
.array_layers_n
= 1;
568 memcpy(®ion
.dst_offsets
[0], &blit_l
[swpchn_img
].vp
.top_left
,
569 sizeof(region
.dst_offsets
[0]));
570 region
.dst_offsets
[0].z
= 0; /* see vk specs */
571 memcpy(®ion
.dst_offsets
[1], &blit_l
[swpchn_img
].vp
.bottom_right
,
572 sizeof(region
.dst_offsets
[1]));
573 region
.dst_offsets
[1].z
= 1; /* see vk specs */
574 /* linear filtering */
575 b8g8r8a8_srgb
= &npv_vk_surf_p
.dev
.phydev
.b8g8r8a8_srgb
;
576 if (b8g8r8a8_srgb
->linear_tiling_has_linear_filt
)
577 filt
= vk_filt_linear
;
579 filt
= vk_filt_nearest
;
580 vk_cmd_blit_img(npv_vk_surf_p
.dev
.cbs
[swpchn_img
], scaler_p
.img
.vk
,
581 npv_vk_surf_p
.dev
.swpchn
.imgs
[swpchn_img
], ®ion
, filt
);
582 /*--------------------------------------------------------------------*/
583 vk_end_cb(npv_vk_surf_p
.dev
.cbs
[swpchn_img
]);
584 IF_FATALVVK("%d:swapchain img:%u:command buffer:%p:unable to end recording\n", r
, swpchn_img
, npv_vk_surf_p
.dev
.cbs
[swpchn_img
]);
585 blit_l
[swpchn_img
].update_requested
= false;
587 STATIC
void blits_request_update(void)
593 if (i
== npv_vk_surf_p
.dev
.swpchn
.imgs_n
)
595 blit_l
[i
].update_requested
= true;
599 STATIC
bool is_swpchn_sem_consistent(void)
603 /* nothing submitted then nothing to check */
604 if (!is_swpchn_sem_fence_submitted_l
)
606 /* coarse synchronization (we could use a pool of semaphores/fences) */
607 vk_get_fence_status();
608 if (r
== vk_not_ready
)
610 else if (r
!= vk_success
)
611 npv_vk_fatal("%d:device:%p:unable to get fence %p status\n", r
, npv_vk_surf_p
.dev
.vk
, npv_vk_surf_p
.dev
.fence
);
614 IF_FATALVVK("%d:device:%p:unable to reset the fence\n", r
, npv_vk_surf_p
.dev
.vk
, npv_vk_surf_p
.dev
.fence
);
615 is_swpchn_sem_fence_submitted_l
= false;
620 STATIC u8
swpchn_next_img(u32
*swpchn_img
) { loop
622 struct vk_acquire_next_img_info_t info
;
625 memset(&info
, 0, sizeof(info
));
626 info
.type
= vk_struct_type_acquire_next_img_info
;
627 info
.swpchn
= npv_vk_surf_p
.dev
.swpchn
.vk
;
629 info
.devs
= 0x00000001; /* no device group then 1 */
630 info
.sem
= npv_vk_surf_p
.dev
.sems
[npv_vk_sem_acquire_img_done
];
632 * XXX: for this vk func, the wait sem _MUST_ be unsignaled _AND_ have
633 * all its "wait" operations completed. state we secure with our usage
636 vk_acquire_next_img(&info
, swpchn_img
);
639 * should _NOT_ return vk_timeout for timeout == 0
641 * src/vulkan/wsi/wsi_common_x11.c:x11_acquire_next_image_from_queue
642 * this func does not return vk_not_ready on timeout == 0
644 if (r
== vk_not_ready
|| r
== vk_timeout
)
646 else if (r
== vk_out_of_date
|| r
== vk_suboptimal
) {
647 vk_q_wait_idle(); /* very violent, hopefully not too long */
648 IF_FATALVVK("%d:queue:%p:unable to wait for idle or completion to prepare for a swpchn update\n", r
, npv_vk_surf_p
.dev
.q
);
649 npv_vk_swpchn_update();
650 blits_request_update();
654 npv_vk_fatal("%d:device:%p:unable to acquire next image from swapchain %p\n", r
, npv_vk_surf_p
.dev
.vk
, npv_vk_surf_p
.dev
.swpchn
.vk
);
659 #define SWPCHN_UPDATED 1
660 STATIC u8
send_to_pe(u32 swpchn_img
)
662 struct vk_submit_info_t submit_info
;
663 struct vk_present_info_t present_info
;
667 /* run the command buffer and do present queue */
668 /*--------------------------------------------------------------------*/
669 memset(&submit_info
, 0, sizeof(submit_info
));
670 submit_info
.type
= vk_struct_type_submit_info
;
671 submit_info
.wait_sems_n
= 1;
673 * the "semaphore wait operation" will unsignal this semaphore once the
676 submit_info
.wait_sems
=
677 &npv_vk_surf_p
.dev
.sems
[npv_vk_sem_acquire_img_done
];
678 wait_dst_stage
= vk_pl_stage_bottom_of_pipe_bit
;
679 submit_info
.wait_dst_stages
= &wait_dst_stage
;
680 submit_info
.cbs_n
= 1;
681 submit_info
.cbs
= &npv_vk_surf_p
.dev
.cbs
[swpchn_img
];
682 submit_info
.signal_sems_n
= 1;
683 submit_info
.signal_sems
= &npv_vk_surf_p
.dev
.sems
[npv_vk_sem_blit_done
];
684 /* XXX: coarse synchronization happens here */
685 vk_q_submit(&submit_info
, npv_vk_surf_p
.dev
.fence
);
686 IF_FATALVVK("%d:queue:%p:unable to submit the image pre-recorded command buffer\n", r
, npv_vk_surf_p
.dev
.q
);
687 is_swpchn_sem_fence_submitted_l
= true;
688 /*--------------------------------------------------------------------*/
689 idxs
[0] = swpchn_img
;
690 memset(&present_info
, 0, sizeof(present_info
));
691 present_info
.type
= vk_struct_type_present_info
;
693 * the "semaphore wait operation" will unsignal this semaphore once the
696 present_info
.wait_sems_n
= 1;
697 present_info
.wait_sems
= &npv_vk_surf_p
.dev
.sems
[npv_vk_sem_blit_done
];
698 present_info
.swpchns_n
= 1;
699 present_info
.swpchns
= &npv_vk_surf_p
.dev
.swpchn
.vk
;
700 present_info
.idxs
= idxs
;
701 present_info
.results
= 0;
702 vk_q_present(&present_info
);
703 if (r
== vk_out_of_date
|| r
== vk_suboptimal
) {
704 vk_q_wait_idle(); /* very violent, hopefully not too long */
705 IF_FATALVVK("%d:queue:%p:unable to wait for idle or completion to prepare for a swpchn update\n", r
, npv_vk_surf_p
.dev
.q
);
706 npv_vk_swpchn_update();
707 blits_request_update();
708 return SWPCHN_UPDATED
;
710 IF_FATALVVK("%d:queue:%p:unable to submit the image %u to the presentation engine\n", r
, npv_vk_surf_p
.dev
.q
, swpchn_img
);
714 #undef SWPCHN_UPDATED
715 STATIC
void start_scaling(avutil_video_fr_ref_t
*fr
,
716 struct dec_fr_priv_t
*fr_priv
)
719 if (scaler_p
.ctx
->cfg
.width
!= fr
->width
720 || scaler_p
.ctx
->cfg
.height
!= fr
->height
) {
723 if (scaler_p
.img
.vk
!= 0)
724 scaler_img_destroy();
725 scaler_img_create(fr
);
726 scaler_img_layout_to_general();
727 scaler_img_subrsrc_layout_get();
728 tmp_scaler_img_mem_rqmts_get();
729 scaler_img_dev_mem_alloc();
730 scaler_img_dev_mem_bind();
731 scaler_img_dev_mem_map();
733 blits_request_update();
734 scaler_p
.ctx
->cfg
.width
= fr
->width
;
735 scaler_p
.ctx
->cfg
.height
= fr
->height
;
736 npv_video_osd_update_dimensions(scaler_p
.img
.data
,
737 (u16
)fr
->width
, (u16
)fr
->height
,
738 (u32
)scaler_p
.img
.layout
.row_pitch
);
740 scaler_p
.ctx
->cfg
.src_fmt
= fr
->fmt
;
741 scaler_p
.ctx
->cfg
.dst_fmt
= AVUTIL_PIX_FMT_RGB32
;
742 scaler_p
.ctx
->cfg
.flags
= SWS_POINT
; /* | SWS_PRINT_INFO */
744 scaler_p
.ctx
->scale
.src_slices
= fr
->data
;
745 scaler_p
.ctx
->scale
.src_strides
= fr
->linesize
;
746 scaler_p
.ctx
->scale
.dst_slice
= scaler_p
.img
.data
;
747 scaler_p
.ctx
->scale
.dst_stride
= (u32
)scaler_p
.img
.layout
.row_pitch
;
748 npv_thdsws_run(scaler_p
.ctx
);
749 scaler_p
.img
.fr
= fr
;
751 * saved pixs for restoration are now irrelevant since we did
752 * overwrite everything
754 npv_video_osd_clear_dirty();
756 STATIC
void timer_ack(void)
762 r
= read(timer_fd_p
, &exps_n
, sizeof(exps_n
));
764 warning("unable to read the number of timer expirations\n");