diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index faebc56..52a7df8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,7 @@ jobs: ./build.sh star6b0 ./build.sh star6e ./build.sh native + ./build.sh rockchip - name: Upload binary uses: actions/upload-artifact@v4 @@ -36,6 +37,7 @@ jobs: msposd_star6b0 msposd_star6e msposd + msposd_rockchip - name: Versioned release if: startsWith(github.ref, 'refs/tags/') @@ -47,6 +49,7 @@ jobs: msposd_star6b0 msposd_star6e msposd + msposd_rockchip - name: Upload latest if: github.ref == 'refs/heads/main' && github.event_name == 'push' @@ -59,3 +62,4 @@ jobs: msposd_star6b0 msposd_star6e msposd + msposd_rockchip diff --git a/.gitignore b/.gitignore index ff5c8d4..9cf818c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,11 +6,13 @@ majestic.yaml /msposd firmware/ release/ +aarch64/ +disk.raw msposd_goke msposd_hisi msposd_star6b0 msposd_star6e -msposd_x86 msposd -serial_monitor.c +msposd_rockchip version.h +serial_monitor.c diff --git a/Makefile b/Makefile index ffcfeea..0c7b466 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ version.h: all: version.h clean: - rm -f *.o msposd msposd_goke msposd_hisi msposd_star6b0 msposd_star6e + rm -f *.o msposd msposd_goke msposd_hisi msposd_star6b0 msposd_star6e msposd_rockchip goke: version.h $(eval SDK = ./sdk/gk7205v300) @@ -52,3 +52,9 @@ native: version.h $(eval BUILD = $(CC) $(SRCS) -I $(SDK)/include -L $(DRV) $(CFLAGS) $(LIB) -levent_core -O0 -g -o $(OUTPUT)) $(BUILD) +rockchip: version.h + $(eval SDK = ./sdk/gk7205v300) + $(eval CFLAGS += -D__ROCKCHIP__) + $(eval LIB = `pkg-config --libs cairo x11` -lm -lrt) + $(eval BUILD = $(CC) $(SRCS) -I $(SDK)/include -L $(DRV) $(CFLAGS) $(LIB) -levent_core -O0 -g -o $(OUTPUT)) + $(BUILD) \ No newline at end of file diff --git a/bmp/region.c b/bmp/region.c index 93e79e9..e2a572a 100644 --- a/bmp/region.c +++ b/bmp/region.c @@ -15,7 +15,7 @@ const double inv16 = 1.0 / 16.0; int create_region(int *handle, int x, int y, int width, int height) { int s32Ret = -1; -#ifndef _x86 +#if !defined(_x86) && !defined(__ROCKCHIP__) #ifdef __SIGMASTAR__ MI_RGN_ChnPort_t stChn; @@ -313,7 +313,7 @@ int prepare_bitmap(const char *filename, BITMAP *bitmap, int bFil, unsigned int int set_bitmap(int handle, BITMAP *bitmap) { int s32Ret=0; -#ifndef _x86 +#if !defined(_x86) && !defined(__ROCKCHIP__) #ifdef __SIGMASTAR__ s32Ret = MI_RGN_SetBitMap(handle, (MI_RGN_Bitmap_t *)(bitmap)); #elif __GOKE__ diff --git a/build.sh b/build.sh index 21722fb..194afef 100755 --- a/build.sh +++ b/build.sh @@ -19,7 +19,7 @@ fi GCC=$PWD/toolchain/$CC/bin/arm-linux-gcc OUT=msposd -if [[ "$1" != *"native"* ]]; then +if [[ "$1" != *"native"* && "$1" != *"rockhip"* ]]; then if [ ! -e toolchain/$CC ]; then wget -c -q --show-progress $DL.$CC.tgz -P $PWD mkdir -p toolchain/$CC @@ -29,7 +29,6 @@ if [[ "$1" != *"native"* ]]; then OUT=msposd_$1 fi - if [ ! -e firmware ]; then git clone https://github.com/openipc/firmware --depth=1 fi @@ -46,6 +45,8 @@ elif [ "$1" = "star6b0" ]; then elif [ "$1" = "star6e" ]; then DRV=$PWD/firmware/general/package/sigmastar-osdrv-infinity6e/files/lib make -B CC=$GCC DRV=$DRV TOOLCHAIN=$PWD/toolchain/$CC OUTPUT=$OUT $1 +elif [ "$1" = "rockchip" ]; then + ./build_rockchip.sh $1 else DRV=$PWD make DRV=$DRV OUTPUT=$OUT $1 diff --git a/build_rockchip.sh b/build_rockchip.sh new file mode 100755 index 0000000..bd013f0 --- /dev/null +++ b/build_rockchip.sh @@ -0,0 +1,58 @@ +#!/bin/sh +output=aarch64 + +# We run arm binary's under x86, crazy, right ;) +which qemu-arm-static 2>/dev/null > /dev/null || sudo apt-get install -y qemu-user-static + +# download and unpack debian arm image +host=https://cloud.debian.org/images/cloud/bullseye +release=latest +system=debian-11-generic-arm64.tar +if [ ! -f disk.raw ]; then + wget -nv ${host}/${release}/${system}.xz + tar -xf ${system}.xz + rm ${system}.xz +fi + +# loop mount the image +if [ ! -d output/tmp ]; then + mkdir -p $output + device=$(sudo losetup -P --show -f disk.raw) + sudo mount ${device}p1 $output + sudo mkdir -p $output/usr/src/msposd + sudo mount -o bind $(pwd) $output/usr/src/msposd +fi + +if [ ! -f $output/tmp/prepare_chroot.done ]; then + cat > prepare_chroot.sh << EOL + #!/bin/bash + cd /home + # install radxa APT repo, see https://radxa-repo.github.io/bullseye/ + keyring="/home/keyring.deb" + version="\$(curl -L https://github.com/radxa-pkg/radxa-archive-keyring/releases/latest/download/VERSION)" + curl -L --output "\$keyring" "https://github.com/radxa-pkg/radxa-archive-keyring/releases/download/\${version}/radxa-archive-keyring_\${version}_all.deb" + dpkg -i \$keyring + echo 'deb [signed-by=/usr/share/keyrings/radxa-archive-keyring.gpg] https://radxa-repo.github.io/bullseye/ bullseye main' > /etc/apt/sources.list.d/70-radxa.list + echo 'deb [signed-by=/usr/share/keyrings/radxa-archive-keyring.gpg] https://radxa-repo.github.io/bullseye rockchip-bullseye main' > /etc/apt/sources.list.d/80-rockchip.list + + apt-get update + apt-get install -y git gcc make pkg-config libspdlog-dev libevent-dev libcairo-dev + apt clean + touch /tmp/prepare_chroot.done +EOL + chmod +x prepare_chroot.sh + sudo cp prepare_chroot.sh $output/home + sudo rm $output/etc/resolv.conf + echo nameserver 1.1.1.1 | sudo tee $output/etc/resolv.conf + sudo chroot $output /home/prepare_chroot.sh + rm prepare_chroot.sh +fi + +if [ "$(uname -m)" = "x86_64" ]; then + sudo chroot aarch64 make OUTPUT=msposd_$1 $1 -C /usr/src/msposd +else + make OUTPUT=$OUT $1 +fi +sudo umount $output/usr/src/msposd +sudo umount $output +sudo losetup -d ${device} diff --git a/compat.c b/compat.c index 763cff4..6ac55c9 100644 --- a/compat.c +++ b/compat.c @@ -32,7 +32,7 @@ int __ctype_b; int __stdin; -#ifndef _x86 +#if !defined(_x86) && !defined(__ROCKCHIP__) int __fgetc_unlocked(FILE *stream) { return fgetc(stream); } diff --git a/osd.c b/osd.c index 07fda86..75aa0b0 100644 --- a/osd.c +++ b/osd.c @@ -15,7 +15,7 @@ #include "osd/msp/msp.h" #include "osd/msp/msp_displayport.h" -#ifdef _x86 +#if defined(_x86) || defined(__ROCKCHIP__) // #include // #include // #include @@ -23,7 +23,7 @@ // #include // #include // #include - #include "osd/util/Render_x86.c" + #include "osd/util/Render_gs.c" #else #include "bmp/region.h" #include "bmp/common.h" @@ -680,9 +680,9 @@ int y_end = 500; } void LineDirect(uint8_t* bmpData, uint32_t width, uint32_t height, int x0, int y0, int x1, int y1, uint8_t color, int thickness) { -#ifdef _x86 +#if defined(_x86) || defined(__ROCKCHIP__) - drawLine_x86(x0, y0, x1, y1, getcolor(color), thickness, false); + drawLineGS(x0, y0, x1, y1, getcolor(color), thickness, false); #else drawLineI4( bmpData, width, height, x0, y0, x1, y1, color, thickness); #endif @@ -690,8 +690,8 @@ int y_end = 500; void LineTranspose(uint8_t* bmpData, int posX0, int posY0, int posX1, int posY1, uint8_t color, int thickness) { -#ifdef _x86 - drawLine_x86(posX0, posY0, posX1, posY1, getcolor(color), thickness, true); +#if defined(_x86) || defined(__ROCKCHIP__) + drawLineGS(posX0, posY0, posX1, posY1, getcolor(color), thickness, true); #else drawLine( bmpData, posX0, posY0, posX1, posY1, color, thickness); #endif @@ -948,11 +948,11 @@ void LineTranspose(uint8_t* bmpData, int posX0, int posY0, int posX1, int posY1, sprintf(buffer, "%+02d°", -last_pitch/10); int osd_font_size=18; -#ifdef _x86 +#if defined(_x86) || defined(__ROCKCHIP__) uint32_t color = getcolor(COLOR_YELLOW); if ((-50 < last_pitch) && (last_pitch <50)) color = getcolor(COLOR_WHITE); - drawText_x86(buffer, start_x + width_ladder*2.5 - spacing/3, y + osd_font_size/2 - 4, color, osd_font_size, true,1); + drawText(buffer, start_x + width_ladder*2.5 - spacing/3, y + osd_font_size/2 - 4, color, osd_font_size, true,1); #endif if (AHI_Enabled==3){//Draw home @@ -1021,8 +1021,8 @@ void LineTranspose(uint8_t* bmpData, int posX0, int posY0, int posX1, int posY1, //needed since we may have already painted the icons } } - #ifdef _x86 - Render_x86_rect(bmpBuff.pData,bmpBuff.u32Width, bmpBuff.u32Height,xR,yR,xR,yR,s_width,s_height); + #if defined(_x86) || defined(__ROCKCHIP__) + Render_rect(bmpBuff.pData,bmpBuff.u32Width, bmpBuff.u32Height,xR,yR,xR,yR,s_width,s_height); #endif } @@ -1491,7 +1491,7 @@ bool Convert2SmallGlyph(BITMAP *fnt , u_int16_t *s_left, u_int16_t *s_top, u_in //Not needed, but somehow parsing DrawString in InjectChars sometimes does not work. static bool ReplaceWidgets_Slow(int* x, int* y){ -#ifdef _x86 +#if defined(_x86) || defined(__ROCKCHIP__) if (character_map[*x][*y]=='!' && character_map[*x+1][*y]=='R' && character_map[*x+2][*y]=='C' && character_map[*x+3][*y]=='!'){ RCWidgetX = *x *current_display_info.font_width; RCWidgetY = current_display_info.font_height * *y; @@ -1664,7 +1664,7 @@ static void draw_screenBMP(){ } step2=get_time_ms(); -#ifndef _x86 +#if !defined(_x86) && !defined(__ROCKCHIP__) if (AHI_Enabled==2) draw_AHI(); @@ -1683,7 +1683,7 @@ static void draw_screenBMP(){ stat_screen_refresh_count++; uint64_t step3=get_time_ms(); -#ifdef _x86 +#if defined(_x86) || defined(__ROCKCHIP__) if (bmp_x86==NULL)//lets cache it bmp_x86 = malloc(bmpBuff.u32Width * bmpBuff.u32Height * 4); // Allocate memory for RGBA data @@ -1699,8 +1699,8 @@ static void draw_screenBMP(){ bmp_x86=bmpBuff.pData; if (DrawOSD){ - //ClearScreen_x86(); - Render_x86(bmp_x86,bmpBuff.u32Width, bmpBuff.u32Height); + //ClearScreen(); + Render(bmp_x86,bmpBuff.u32Width, bmpBuff.u32Height); if (AHI_Enabled==2) draw_AHI(); @@ -1713,7 +1713,7 @@ static void draw_screenBMP(){ if (strlen(air_unit_info_msg)>1){ int osd_font_size=osds[FULL_OVERLAY_ID].size - 6; //Some offset needed to keep the same with air rendering uint64_t timems=get_time_ms(); - int width=getTextWidth_x86(air_unit_info_msg,osd_font_size); + int width=getTextWidth(air_unit_info_msg,osd_font_size); int posX=0,posY=0; if (msg_layout%4==0)// left @@ -1726,10 +1726,10 @@ static void draw_screenBMP(){ posX=20 + ((timems/16)%(bmpBuff.u32Width - width - 40))& ~1; posY=(msg_layout/4)== 0 ? osd_font_size : (bmpBuff.u32Height ) - 6;//Uppper or lower line - drawText_x86(air_unit_info_msg, posX , posY, getcolor(msg_colour), /*font_size*/ osd_font_size, false,0); + drawText(air_unit_info_msg, posX , posY, getcolor(msg_colour), /*font_size*/ osd_font_size, false,0); } - FlushDrawing_x86(); + FlushDrawing(); } @@ -1778,7 +1778,7 @@ static void clear_screen() { if (cntr++<0 ) return ; - //ClearScreen_x86(); + //ClearScreen(); //BetaFlight needs this. INAV can be configured to skip it if (!DrawOSD || font_pages == 1 || font_pages>2 || (get_time_ms() - LastCleared)>300) {//no faster than 0.5 per second memset(character_map, 0, sizeof(character_map)); @@ -1859,7 +1859,7 @@ unsigned char* loadPngToBMP(const char* filename, unsigned int* width, unsigned else if (PIXEL_FORMAT_DEFAULT==PIXEL_FORMAT_8888){ // memcpy(bmpData,pngData,bmpSize); convertRGBAToARGB( pngData, *width , *height, bmpData); -#ifdef _x86 +#if defined(_x86) || defined(__ROCKCHIP__) premultiplyAlpha((uint32_t*) bmpData, *width, *height);//RGBA format needs to be converted when using transparency? #endif }else @@ -2057,7 +2057,7 @@ static void InitMSPHook(){ PIXEL_FORMAT_DEFAULT=PIXEL_FORMAT_I4;//I4 format, 4 bits per pixel PIXEL_FORMAT_BitsPerPixel = 4; #endif - #ifdef _x86 + #if defined(_x86) || defined(__ROCKCHIP__) //enable this to simulate I4 Bitmap Processing on SigmaStar //PIXEL_FORMAT_DEFAULT=PIXEL_FORMAT_I4;//I4 format, 4 bits per pixel //PIXEL_FORMAT_BitsPerPixel = 4; @@ -2070,10 +2070,11 @@ static void InitMSPHook(){ height = GetMajesticVideoConfig(&majestic_width); majestic_height=height; - #ifdef _x86 + #if defined(_x86) || defined(__ROCKCHIP__) if (DrawOSD) - Init_x86(&OVERLAY_WIDTH, &OVERLAY_HEIGHT); + Init(&OVERLAY_WIDTH, &OVERLAY_HEIGHT); height=OVERLAY_HEIGHT; + printf("OSD is %ix%i pixels\n",OVERLAY_WIDTH,OVERLAY_HEIGHT); #endif //Get video resolution @@ -2232,7 +2233,7 @@ On sigmastar the BMP row stride is aligned to 8 bytes, that is 16 pixels in PIXE printf("Set Goke Font Review %d:%d\r\n", bitmap.u32Width, bitmap.u32Height); set_bitmap(osds[FULL_OVERLAY_ID].hand, &bitmap);//bitmap must match region dimensions! - #elif _x86 + #elif defined(_x86) || defined(__ROCKCHIP__) //sfRenderWindow_clear(window, sfColor_fromRGB(255, 255, 0)); unsigned char* rgbaData = malloc(bitmap.u32Width * bitmap.u32Height * 4); // Allocate memory for RGBA data @@ -2243,9 +2244,9 @@ On sigmastar the BMP row stride is aligned to 8 bytes, that is 16 pixels in PIXE else Convert1555ToRGBA( bitmap.pData, rgbaData, bitmap.u32Width, bitmap.u32Height); - Render_x86(rgbaData,bitmap.u32Width, bitmap.u32Height); - //Render_x86(bitmapFnt.pData,bitmapFnt.u32Width,700);//test - FlushDrawing_x86(); + Render(rgbaData,bitmap.u32Width, bitmap.u32Height); + //Render(bitmapFnt.pData,bitmapFnt.u32Width,700);//test + FlushDrawing(); free(rgbaData); //cairo_surface_destroy(image_surface); //image_surface = NULL; @@ -2294,8 +2295,8 @@ static void CloseMSP(){ if (deinit) printf("[%s:%d]RGN_DeInit failed with %#x!\n", __func__, __LINE__, s32Ret); #endif - #ifdef _x86 - Close_x86(); + #if defined(_x86) || defined(__ROCKCHIP__) + Close(); #endif munmap(osds, sizeof(*osds) * MAX_OSD); diff --git a/osd/msp/vtxmenu.c b/osd/msp/vtxmenu.c index 4d5339e..c9535b7 100644 --- a/osd/msp/vtxmenu.c +++ b/osd/msp/vtxmenu.c @@ -50,16 +50,42 @@ void display_menu(displayport_vtable_t *display_driver,MenuSection *section, int clearNextDraw = true; } if (showStatusScreen) { - for (int row = 0; row < OSD_HD_ROWS-menu_offset_row; row++) { - for (int col = 0; col < OSD_HD_COLS-menu_offset_cols; col++) { - display_driver->draw_character(col+menu_offset_cols, row+menu_offset_row, ' '); + for (int row = 0; row < OSD_HD_ROWS - menu_offset_row; row++) { + for (int col = 0; col < OSD_HD_COLS - menu_offset_cols; col++) { + display_driver->draw_character(col + menu_offset_cols, row + menu_offset_row, ' '); } } - display_driver->draw_character(OSD_HD_COLS/2 - menu_offset_cols,OSD_HD_ROWS/2, 'D'); - display_driver->draw_character(OSD_HD_COLS/2 - menu_offset_cols + 1,OSD_HD_ROWS/2, 'O'); - display_driver->draw_character(OSD_HD_COLS/2 - menu_offset_cols + 2,OSD_HD_ROWS/2, 'N'); - display_driver->draw_character(OSD_HD_COLS/2 - menu_offset_cols + 3,OSD_HD_ROWS/2, 'E'); + + const char *status_msg = "DONE"; + int msg_len = strlen(status_msg); + int start_col = OSD_HD_COLS / 2 - msg_len / 2; + + for (int i = 0; i < msg_len; i++) { + display_driver->draw_character(start_col + i, OSD_HD_ROWS / 2, status_msg[i]); + } display_driver->draw_complete(); + + if (out_sock > 0) { // Send status screen to the ground + // Clear the screen remotely + payload_buffer[0] = MSP_DISPLAYPORT_CLEAR; + construct_msp_command(message_buffer, MSP_CMD_DISPLAYPORT, payload_buffer, 2, MSP_INBOUND); + sendto(out_sock, message_buffer, 6 + 2, 0, (struct sockaddr *)&sin_out, sizeof(sin_out)); + + // Draw the "DONE" message remotely + payload_buffer[0] = MSP_DISPLAYPORT_DRAW_STRING; + payload_buffer[1] = OSD_HD_ROWS / 2; // Row for "DONE" + payload_buffer[2] = OSD_HD_COLS / 2 - msg_len / 2; // Center column + payload_buffer[3] = 0; // Reserved byte + memcpy(&payload_buffer[4], status_msg, msg_len); // Copy the message into the payload + + construct_msp_command(message_buffer, MSP_CMD_DISPLAYPORT, payload_buffer, 4 + msg_len, MSP_INBOUND); + sendto(out_sock, message_buffer, 6 + 4 + msg_len, 0, (struct sockaddr *)&sin_out, sizeof(sin_out)); + + // Instruct remote display to draw the complete screen + payload_buffer[0] = MSP_DISPLAYPORT_DRAW_SCREEN; + construct_msp_command(message_buffer, MSP_CMD_DISPLAYPORT, payload_buffer, 2, MSP_INBOUND); + sendto(out_sock, message_buffer, 6 + 2, 0, (struct sockaddr *)&sin_out, sizeof(sin_out)); + } return; } diff --git a/osd/util/Render_x86.c b/osd/util/Render_gs.c similarity index 79% rename from osd/util/Render_x86.c rename to osd/util/Render_gs.c index fbd5ec8..ea9eed8 100644 --- a/osd/util/Render_x86.c +++ b/osd/util/Render_gs.c @@ -13,24 +13,35 @@ #include #include +#if defined(_x86) Display* display=NULL; Window window =NULL; -cairo_surface_t* surface_x11=NULL; -cairo_surface_t* surface=NULL; -cairo_surface_t* image_surface = NULL; -cairo_t* cr=NULL; -cairo_t* cr_x11=NULL; Pixmap backbuffer_pixmap; -cairo_surface_t* backbuffer_surface; - bool forcefullscreen=true; -extern bool verbose; extern struct event_base *base; struct event *x11_event=NULL; - Window RootWindow; +#endif + +#if defined(__ROCKCHIP__) +#define SHM_NAME "msposd" +// Define the shared memory region structure +typedef struct { + uint16_t width; // Image width + uint16_t height; // Image height + unsigned char data[]; // Flexible array for image data +} SharedMemoryRegion; +#endif +cairo_surface_t* surface=NULL; +cairo_surface_t* surface_back=NULL; +cairo_surface_t* image_surface = NULL; +cairo_t* cr=NULL; +cairo_t* cr_back=NULL; +extern bool verbose; + +#if defined(_x86) extern int AHI_TiltY; void handle_key_press(XEvent *event) { KeySym keysym = XLookupKeysym(&event->xkey, 0); // Map keycode to keysym @@ -64,14 +75,11 @@ void event_callback(evutil_socket_t fd, short event, void *arg) { } } - -int Init_x86(uint16_t *width, uint16_t *height) { +int Init(uint16_t *width, uint16_t *height) { if (verbose) forcefullscreen=false; -#ifdef _x86 setenv("DISPLAY", ":0", 0); -#endif display = XOpenDisplay(NULL); if (!display) { @@ -136,12 +144,95 @@ int Init_x86(uint16_t *width, uint16_t *height) { XChangeProperty(display, window, windowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&windowTypeDock, 1); } // Create a Cairo surface for drawing on the X11 window - surface_x11 = cairo_xlib_surface_create(display, window, vinfo.visual, *width, *height); + surface_back = cairo_xlib_surface_create(display, window, vinfo.visual, *width, *height); surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, *width, *height); cr = cairo_create(surface); - cr_x11 = cairo_create(surface_x11); + cr_back = cairo_create(surface_back); + +} +#endif + +#if defined(__ROCKCHIP__) +int Init(uint16_t *width, uint16_t *height) { + // Create shared memory region + const char *shm_name = "msposd"; // Name of the shared memory region + int shm_fd = -1; + + // Wait until the shared memory segment exists + while (shm_fd == -1) { + shm_fd = shm_open(shm_name, O_RDWR, 0666); + if (shm_fd == -1) { + if (errno == ENOENT) { + printf("Shared memory '%s' does not exist. Waiting...\n", shm_name); + sleep(1); // Wait for 1 second before trying again + continue; + } else { + perror("Failed to open shared memory"); + return -1; + } + } + + } + // Map just the header to read width and height + size_t header_size = sizeof(SharedMemoryRegion); + SharedMemoryRegion *shm_region = (SharedMemoryRegion *) mmap(0, header_size, PROT_READ, MAP_SHARED, shm_fd, 0); + if (shm_region == MAP_FAILED) { + perror("Failed to map shared memory header"); + close(shm_fd); + return -1; + } + + // Validate width and height (optional) + if (shm_region->width <= 0 || shm_region->width <= 0) { + fprintf(stderr, "Invalid width or height in shared memory\n"); + munmap(shm_region, header_size); + close(shm_fd); + return -1; + } + + int shm_width = shm_region->width; + int shm_height = shm_region->height; + *width = shm_region->width; + *height = shm_region->height; + + printf("Surface is %ix%i pixels\n",shm_width,shm_height); + + // Unmap the header (optional, as we'll remap everything) + munmap(shm_region, header_size); + // Calculate the total size of shared memory + size_t shm_size = header_size + (shm_width * shm_height * 4); // Header + Image data + + // Remap the entire shared memory region (header + image data) + shm_region = (SharedMemoryRegion *) mmap(0, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shm_region == MAP_FAILED) { + perror("Failed to remap shared memory"); + close(shm_fd); + return -1; + } + + // Create a Cairo surface for the image data + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, shm_width, shm_width); + if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "Failed to create Cairo surface\n"); + return -1; + } + + // Create a Cairo surface for the image data connecto to the shm + surface_back = cairo_image_surface_create_for_data( + shm_region->data, CAIRO_FORMAT_ARGB32, shm_width, shm_height, shm_width * 4); + if (cairo_surface_status(surface_back) != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "Failed to create Cairo surface_back\n"); + munmap(shm_region, shm_size); + close(shm_fd); + return -1; + } + + // Create a Cairo context + cr = cairo_create(surface); + cr_back = cairo_create(surface_back); } +#endif void premultiplyAlpha(uint32_t* rgbaData, uint32_t width, uint32_t height) { for (uint32_t i = 0; i < width * height; ++i) { @@ -156,14 +247,14 @@ void premultiplyAlpha(uint32_t* rgbaData, uint32_t width, uint32_t height) { } -void ClearScreen_x86(){ +void ClearScreen(){ cairo_set_source_rgba(cr, 0, 0, 0, 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE ); cairo_paint(cr); } -void Render_x86( unsigned char* rgbaData, int u32Width, int u32Height){ +void Render( unsigned char* rgbaData, int u32Width, int u32Height){ cairo_set_source_rgba(cr, 0, 0, 0, 0); // Transparent background for buffer @@ -191,14 +282,14 @@ void Render_x86( unsigned char* rgbaData, int u32Width, int u32Height){ cairo_paint(cr); //XSync(display, False);//seems not needed? +#if defined(_x86) if (forcefullscreen) XRaiseWindow(display, window);//Raise the window to the top - - +#endif } -void Render_x86_rect(unsigned char* rgbaData, int u32Width, int u32Height, int src_x, int src_y, int dest_x, int dest_y, int rect_width, int rect_height) { +void Render_rect(unsigned char* rgbaData, int u32Width, int u32Height, int src_x, int src_y, int dest_x, int dest_y, int rect_width, int rect_height) { // Check if the bitmap has changed and recreate the image surface if necessary if (image_surface != NULL && cairo_image_surface_get_data(image_surface) != rgbaData) { cairo_surface_destroy(image_surface); @@ -229,8 +320,8 @@ void Render_x86_rect(unsigned char* rgbaData, int u32Width, int u32Height, int s } -void FlushDrawing_x86(){ - +void FlushDrawing(){ +#if defined(_x86) //Hook keyboard- can't be in init procs since there the libevent is not still created. // base = event_base_new(); if (x11_event==NULL && base!=NULL){ @@ -255,34 +346,37 @@ void FlushDrawing_x86(){ GrabModeAsync, GrabModeAsync); // Alt + Down Arrow } - +#endif + // Copy work buffer to the display surface do avoid flickering - cairo_set_operator(cr_x11, CAIRO_OPERATOR_SOURCE); + cairo_set_operator(cr_back, CAIRO_OPERATOR_SOURCE); // Copy buffer to the display surface - cairo_set_source_surface(cr_x11, surface, 0, 0); - cairo_paint(cr_x11); + cairo_set_source_surface(cr_back, surface, 0, 0); + cairo_paint(cr_back); - cairo_surface_flush(surface_x11); + cairo_surface_flush(surface_back); +#if defined(_x86) XFlush(display); - +#endif //XSync(display, False);//seems not needed? } -void Close_x86(){ +void Close(){ // Clean up resources cairo_destroy(cr); - cairo_destroy(cr_x11); + cairo_destroy(cr_back); cairo_surface_destroy(image_surface); cairo_surface_destroy(surface); - cairo_surface_destroy(surface_x11); + cairo_surface_destroy(surface_back); +#if defined(_x86) XDestroyWindow(display, window); XCloseDisplay(display); // Cleanup event_free(x11_event); event_base_free(base); - +#endif } @@ -291,7 +385,7 @@ extern uint16_t Transform_OVERLAY_HEIGHT; extern float Transform_Roll; extern float Transform_Pitch; bool outlined=true; -void drawLine_x86(int x0, int y0, int x1, int y1, uint32_t color, double thickness, bool Transpose) { +void drawLineGS(int x0, int y0, int x1, int y1, uint32_t color, double thickness, bool Transpose) { if (Transpose){ @@ -359,7 +453,7 @@ void drawLine_x86(int x0, int y0, int x1, int y1, uint32_t color, double thickne // Function to draw rotated text with rotation -int getTextWidth_x86(const char* text , double size) { +int getTextWidth(const char* text , double size) { cairo_set_font_size(cr, size); cairo_text_extents_t extents; // Get the extents of the text @@ -371,7 +465,7 @@ int getTextWidth_x86(const char* text , double size) { // Function to draw rotated text with rotation -void drawText_x86(const char* text, int x, int y, uint32_t color, double size, bool Transpose, int Outline) { +void drawText(const char* text, int x, int y, uint32_t color, double size, bool Transpose, int Outline) { // Extract the RGBA components from the color double r = ((color >> 24) & 0xFF) / 255.0; double g = ((color >> 16) & 0xFF) / 255.0; @@ -485,6 +579,4 @@ void drawRC_Channels(int posX, int posY, int m1X, int m1Y, int m2X, int m2Y){//i cairo_set_source_rgb(cr, 1, 1, 1); // Set color to white for the circle cairo_arc(cr, rect_center_x, rect_center_y, circle_radius, 0, 2 * M_PI); cairo_fill(cr); - - return 0; }