@@ -950,6 +950,83 @@ class DebugWidget: public Widget {
950
950
}
951
951
};
952
952
953
+ class ExternalSurfaceWidget : public Widget {
954
+ public:
955
+ ExternalSurfaceWidget (int pos_x, int pos_y, std::string shm_name ): Widget(pos_x, pos_y), shm_name(shm_name) {};
956
+
957
+ virtual void init_shm (cairo_t *cr) {
958
+ SPDLOG_INFO (" creating shm region {}" , shm_name);
959
+
960
+ cairo_surface_t *target = cairo_get_target (cr);
961
+ int width = cairo_image_surface_get_width (target);
962
+ int height = cairo_image_surface_get_height (target);
963
+
964
+ // Calculate total shared memory size
965
+ shm_size = sizeof (SharedMemoryRegion) + (width * height * 4 ); // Metadata + Image data
966
+
967
+ // Create shared memory region
968
+ int shm_fd = shm_open (shm_name.c_str (), O_CREAT | O_RDWR, 0666 );
969
+ if (shm_fd == -1 ) {
970
+ perror (" Failed to create shared memory" );
971
+ return ;
972
+ }
973
+
974
+ if (ftruncate (shm_fd, shm_size) == -1 ) {
975
+ perror (" Failed to set shared memory size" );
976
+ shm_unlink (shm_name.c_str ());
977
+ return ;
978
+ }
979
+
980
+ // Map shared memory to process address space
981
+ auto *shm_region = static_cast <SharedMemoryRegion*>(
982
+ mmap (0 , shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0 )
983
+ );
984
+ if (shm_region == MAP_FAILED) {
985
+ perror (" Failed to map shared memory" );
986
+ shm_unlink (shm_name.c_str ());
987
+ return ;
988
+ }
989
+
990
+ // Write metadata
991
+ shm_region->width = width;
992
+ shm_region->height = height;
993
+
994
+ // Create Cairo surface for the image data
995
+ shm_surface = cairo_image_surface_create_for_data (
996
+ shm_region->data , CAIRO_FORMAT_ARGB32, width, height, width * 4
997
+ );
998
+
999
+ // Store pointer for cleanup
1000
+ shm_data = reinterpret_cast <unsigned char *>(shm_region);
1001
+ }
1002
+
1003
+
1004
+ virtual void draw (cairo_t *cr) {
1005
+
1006
+ if (! shm_surface)
1007
+ init_shm (cr);
1008
+ auto [x, y] = xy (cr);
1009
+ cairo_set_source_surface (cr, shm_surface, x, y); // Position at (0, 0)
1010
+ cairo_paint (cr); // Paint shm_surface onto base_surface
1011
+ }
1012
+
1013
+ ~ExternalSurfaceWidget () {
1014
+ SPDLOG_INFO (" bye, bye, shm region {}" , shm_name);
1015
+ if (shm_surface) {
1016
+ cairo_surface_destroy (shm_surface);
1017
+ }
1018
+ if (shm_data) {
1019
+ munmap (shm_data, shm_size);
1020
+ }
1021
+ shm_unlink (shm_name.c_str ());
1022
+ }
1023
+
1024
+ protected:
1025
+ cairo_surface_t *shm_surface = nullptr ;
1026
+ unsigned char *shm_data = nullptr ;
1027
+ size_t shm_size;
1028
+ std::string shm_name;
1029
+ };
953
1030
954
1031
class Osd {
955
1032
public:
@@ -993,6 +1070,9 @@ class Osd {
993
1070
if (type == " TextWidget" ) {
994
1071
addWidget (new TextWidget (x, y, widget_j.at (" text" ).template get <std::string>()),
995
1072
matchers);
1073
+ }
1074
+ else if (type == " ExternalSurfaceWidget" ) {
1075
+ addWidget (new ExternalSurfaceWidget (x, y, name), matchers);
996
1076
} else if (type == " TplTextWidget" ) {
997
1077
auto tpl = widget_j.at (" template" ).template get <std::string>();
998
1078
addWidget (new TplTextWidget (x, y, tpl, (uint )matchers.size ()), matchers);
0 commit comments