@@ -53,6 +53,10 @@ static wl_cursor_t *wlcursor = NULL;
5353static uint8_t gl_device_uuid [16 ];
5454void (* p_glGetUnsignedBytei_vEXT )(unsigned int target , unsigned int index , unsigned char * data ) = NULL ;
5555
56+ #define VK_COLOR_SPACE_SRGB_NONLINEAR_KHR 0
57+ #define VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT 1000104002
58+ #define VK_COLOR_SPACE_HDR10_ST2084_EXT 1000104008
59+
5660enum vkcapture_import_attempt {
5761 IMPORT_DEFAULT = 0 ,
5862 IMPORT_NO_MODIFIERS = 1 ,
@@ -562,23 +566,105 @@ static void vkcapture_source_render(void *data, gs_effect_t *effect)
562566 ioctl (fd , DMA_BUF_IOCTL_SYNC , & sync );
563567 }
564568
565- const enum gs_color_space color_space = gs_get_color_space ();
566- const bool linear_srgb = gs_get_linear_srgb ();
567- const char * tech_name = linear_srgb ? "DrawSrgbDecompress" : "Draw" ;
569+ enum gs_color_space source_space = GS_CS_SRGB ;
570+ const bool is_pq = ctx -> tdata .color_space == VK_COLOR_SPACE_HDR10_ST2084_EXT ;
571+ if (is_pq )
572+ source_space = GS_CS_709_EXTENDED ;
573+ else if (ctx -> tdata .color_space == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT )
574+ source_space = GS_CS_709_SCRGB ;
575+
576+ const enum gs_color_space current_space = gs_get_color_space ();
577+ bool linear_sample = !gs_get_linear_srgb ();
578+ const char * tech_name = "Draw" ;
568579 float multiplier = 1.f ;
569580
570- if (color_space == GS_CS_709_EXTENDED ) {
571- tech_name = "DrawPQ" ;
572- multiplier = 10000.f / obs_get_video_sdr_white_level ();
581+ switch (source_space ) {
582+ case GS_CS_SRGB :
583+ switch (current_space ) {
584+ case GS_CS_SRGB :
585+ if (ctx -> allow_transparency && !linear_sample )
586+ tech_name = "DrawSrgbDecompress" ;
587+ break ;
588+ case GS_CS_SRGB_16F :
589+ case GS_CS_709_EXTENDED :
590+ if (!linear_sample )
591+ tech_name = "DrawSrgbDecompress" ;
592+ break ;
593+ case GS_CS_709_SCRGB :
594+ if (linear_sample )
595+ tech_name = "DrawMultiply" ;
596+ else
597+ tech_name = "DrawSrgbDecompressMultiply" ;
598+ multiplier = obs_get_video_sdr_white_level () / 80.f ;
599+ }
600+ break ;
601+ case GS_CS_SRGB_16F :
602+ linear_sample = true;
603+ switch (current_space ) {
604+ case GS_CS_SRGB :
605+ case GS_CS_SRGB_16F :
606+ case GS_CS_709_EXTENDED :
607+ tech_name = is_pq ? "DrawSrgbDecompress" : "Draw" ;
608+ break ;
609+ case GS_CS_709_SCRGB :
610+ tech_name = is_pq ? "DrawSrgbDecompressMultiply" : "DrawMultiply" ;
611+ multiplier = obs_get_video_sdr_white_level () / 80.f ;
612+ }
613+ break ;
614+ case GS_CS_709_EXTENDED :
615+ linear_sample = true;
616+ if (is_pq ) {
617+ switch (current_space ) {
618+ case GS_CS_SRGB :
619+ case GS_CS_SRGB_16F :
620+ tech_name = "DrawTonemapPQ" ;
621+ multiplier = 10000.f / obs_get_video_sdr_white_level ();
622+ break ;
623+ case GS_CS_709_EXTENDED :
624+ tech_name = "DrawPQ" ;
625+ multiplier = 10000.f / obs_get_video_sdr_white_level ();
626+ break ;
627+ case GS_CS_709_SCRGB :
628+ tech_name = "DrawPQ" ;
629+ multiplier = 10000.f / 80.f ;
630+ }
631+ } else {
632+ switch (current_space ) {
633+ case GS_CS_SRGB :
634+ case GS_CS_SRGB_16F :
635+ tech_name = "DrawTonemap" ;
636+ break ;
637+ case GS_CS_709_SCRGB :
638+ tech_name = "DrawMultiply" ;
639+ multiplier = obs_get_video_sdr_white_level () / 80.f ;
640+ default :
641+ break ;
642+ }
643+ }
644+ break ;
645+ case GS_CS_709_SCRGB :
646+ linear_sample = true;
647+ switch (current_space ) {
648+ case GS_CS_SRGB :
649+ case GS_CS_SRGB_16F :
650+ tech_name = "DrawMultiplyTonemap" ;
651+ multiplier = 80.f / obs_get_video_sdr_white_level ();
652+ break ;
653+ case GS_CS_709_EXTENDED :
654+ tech_name = "DrawMultiply" ;
655+ multiplier = 80.f / obs_get_video_sdr_white_level ();
656+ default :
657+ break ;
658+ }
573659 }
574660
575661 effect = obs_get_base_effect (ctx -> allow_transparency ? OBS_EFFECT_DEFAULT : OBS_EFFECT_OPAQUE );
576662
577663 const bool previous = gs_framebuffer_srgb_enabled ();
578- gs_enable_framebuffer_srgb (linear_srgb );
664+ gs_enable_framebuffer_srgb (ctx -> allow_transparency || linear_sample );
579665
580666 gs_eparam_t * image = gs_effect_get_param_by_name (effect , "image" );
581- if (linear_srgb )
667+ if (linear_sample )
582668 gs_effect_set_texture_srgb (image , ctx -> texture );
583669 else
584670 gs_effect_set_texture (image , ctx -> texture );
@@ -591,21 +677,23 @@ static void vkcapture_source_render(void *data, gs_effect_t *effect)
591677 }
592678 }
593679
680+ gs_enable_framebuffer_srgb (previous );
681+
594682 if (!ctx -> allow_transparency && ctx -> show_cursor ) {
595683 effect = obs_get_base_effect (OBS_EFFECT_DEFAULT );
596684 tech_name = "Draw" ;
597685 multiplier = 1.f ;
598- if (color_space == GS_CS_709_SCRGB ) {
686+ if (current_space == GS_CS_709_SCRGB ) {
599687 tech_name = "DrawMultiply" ;
600688 multiplier = obs_get_video_sdr_white_level () / 80.f ;
601689 }
602690 while (gs_effect_loop (effect , tech_name )) {
603691 gs_effect_set_float (gs_effect_get_param_by_name (effect , "multiplier" ), multiplier );
604692 cursor_render (ctx );
605693 }
606- }
607694
608- gs_enable_framebuffer_srgb (previous );
695+ gs_set_linear_srgb (previous );
696+ }
609697}
610698
611699static const char * vkcapture_source_get_name (void * data )
@@ -695,15 +783,29 @@ enum gs_color_space vkcapture_get_color_space(void *data, size_t count, const en
695783{
696784 vkcapture_source_t * ctx = data ;
697785
698- enum gs_color_space color_space = ctx -> tdata .color_space ;
786+ enum gs_color_space capture_space = GS_CS_SRGB ;
787+ uint32_t color_space = ctx -> tdata .color_space ;
699788
700- if (ctx -> force_hdr ) {
701- color_space = GS_CS_709_EXTENDED ;
789+ if (color_space == VK_COLOR_SPACE_HDR10_ST2084_EXT || color_space == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT ) {
790+ for (size_t i = 0 ; i < count ; ++ i ) {
791+ if (preferred_spaces [i ] == GS_CS_709_SCRGB ) {
792+ return GS_CS_709_SCRGB ;
793+ }
794+ }
795+ capture_space = GS_CS_709_EXTENDED ;
702796 }
703-
704- UNUSED_PARAMETER (count );
705- UNUSED_PARAMETER (preferred_spaces );
706- return color_space ;
797+ // TODO: Maybe handle GS_CS_SRGB_16F? SDR for >8 bit format
798+
799+ // Same as win-capture/game-capture.c
800+ enum gs_color_space space = capture_space ;
801+ for (size_t i = 0 ; i < count ; ++ i ) {
802+ const enum gs_color_space preferred_space = preferred_spaces [i ];
803+ space = preferred_space ;
804+ if (preferred_space == capture_space ) {
805+ break ;
806+ }
807+ }
808+ return space ;
707809}
708810
709811static struct obs_source_info vkcapture_input = {
0 commit comments