Untitled
/*#include <stdio.h> #include <stdlib.h> #include <wlr/backend.h> #include <wlr/util/log.h> #include <wayland-server-core.h> #include "rdprail_backend.h" int main(void) { // Initialize Wayland display struct wl_display *display = wl_display_create(); if (!display) { fprintf(stderr, "Failed to create wayland display\n"); return 1; } // Create RDP backend struct wlr_backend *backend = wlr_rdp_backend_create(display, NULL, NULL); if (!backend) { fprintf(stderr, "Failed to create RDP backend\n"); wl_display_destroy(display); return 1; } // Get RDP backend from generic backend struct wlr_rdp_backend *rdp_backend = get_rdp_backend_from_backend(backend); if (!rdp_backend) { fprintf(stderr, "Failed to get RDP backend\n"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } // Print GPU info rdp_backend_print_gpu_info(rdp_backend); // Test GPU if (rdp_backend_test_gpu(rdp_backend)) { printf("GPU test passed!\n"); } else { printf("GPU test failed!\n"); } // Cleanup wlr_backend_destroy(backend); wl_display_destroy(display); return 0; }*/ /* #include <stdio.h> #include <stdlib.h> #include <wlr/backend.h> #include <wlr/util/log.h> #include <wayland-server-core.h> #include "rdprail_backend.h" #include "rdprail_window.h" static void handle_window_create(struct wlr_rdp_window *window, void *data) { printf("Window created: %dx%d\n", window->width, window->height); } static void handle_window_destroy(struct wlr_rdp_window *window, void *data) { printf("Window destroyed: %dx%d\n", window->width, window->height); } int main(void) { // Initialize Wayland display struct wl_display *display = wl_display_create(); if (!display) { fprintf(stderr, "Failed to create wayland display\n"); return 1; } // Create RDP backend struct wlr_backend *backend = wlr_rdp_backend_create(display, NULL, NULL); if (!backend) { fprintf(stderr, "Failed to create RDP backend\n"); wl_display_destroy(display); return 1; } // Get RDP backend from generic backend struct wlr_rdp_backend *rdp_backend = get_rdp_backend_from_backend(backend); if (!rdp_backend) { fprintf(stderr, "Failed to get RDP backend\n"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } // Print GPU info rdp_backend_print_gpu_info(rdp_backend); // Test GPU if (!rdp_backend_test_gpu(rdp_backend)) { fprintf(stderr, "GPU test failed!\n"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } printf("GPU test passed!\n"); // Set window callbacks wlr_rdp_backend_set_window_callbacks(rdp_backend, handle_window_create, handle_window_destroy, NULL ); // Create a test window struct wlr_rdp_window *window = wlr_rdp_window_create(rdp_backend, 640, 480); if (!window) { fprintf(stderr, "Failed to create window\n"); goto cleanup; } // Start the event loop printf("Starting Wayland event loop...\n"); wl_display_run(display); // Cleanup window wlr_rdp_window_destroy(window); cleanup: // Cleanup backend wlr_backend_destroy(backend); wl_display_destroy(display); return 0; } // rdprail_test.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <wlr/backend.h> #include <wlr/util/log.h> #include "rdprail.h" // Function prototypes for mock functions int mock_open_pool(struct _GfxRedirServerContext *ctx, GFXREDIR_OPEN_POOL_PDU *open_pool); int mock_create_buffer(struct _GfxRedirServerContext *ctx, GFXREDIR_CREATE_BUFFER_PDU *create_buffer); int mock_surface_command(struct _GfxRedirServerContext *ctx, void *surface_data, int command, RECTANGLE_16 *rect, void *buffer_data); // Mock implementations for context methods int mock_open_pool(struct _GfxRedirServerContext *ctx, GFXREDIR_OPEN_POOL_PDU *open_pool) { open_pool->poolId = 1; wlr_log(WLR_INFO, "Opened pool with ID: %u", open_pool->poolId); return 0; } int mock_create_buffer(struct _GfxRedirServerContext *ctx, GFXREDIR_CREATE_BUFFER_PDU *create_buffer) { create_buffer->bufferId = 1; wlr_log(WLR_INFO, "Created buffer in pool %u with ID: %u", create_buffer->poolId, create_buffer->bufferId); return 0; } int mock_surface_command(struct _GfxRedirServerContext *ctx, void *surface_data, int command, RECTANGLE_16 *rect, void *buffer_data) { wlr_log(WLR_INFO, "Surface command executed"); return 0; } // Prototype for main to satisfy strict prototypes int main(void); // Create a test context GfxRedirServerContext test_context = { .OpenPool = mock_open_pool, .CreateBuffer = mock_create_buffer, .SurfaceCommand = mock_surface_command, .HandleInput = default_handle_input, .HandleMouseEvent = default_handle_mouse_event, .HandleKeyboardEvent = default_handle_keyboard_event, .HandleTouchEvent = default_handle_touch_event }; int main(void) { // Set logging level for visibility wlr_log_init(WLR_DEBUG, NULL); wlr_log(WLR_INFO, "Starting RDP Backend Test"); // Test Pool Creation GFXREDIR_OPEN_POOL_PDU open_pool = {0}; if (test_context.OpenPool(&test_context, &open_pool) != 0) { wlr_log(WLR_ERROR, "Failed to open pool"); return 1; } // Test Buffer Creation GFXREDIR_CREATE_BUFFER_PDU create_buffer = { .poolId = open_pool.poolId, .width = 640, .height = 480, .format = 1 // Assuming ARGB8888 }; if (test_context.CreateBuffer(&test_context, &create_buffer) != 0) { wlr_log(WLR_ERROR, "Failed to create buffer"); return 1; } // Test Surface Command uint32_t buffer_id = create_buffer.bufferId; RECTANGLE_16 rect = { .left = 0, .top = 0, .right = 640, .bottom = 480 }; if (test_context.SurfaceCommand(&test_context, NULL, GFX_REDIR_SURFACE_COMMAND_UPDATEREGION, &rect, &buffer_id) != 0) { wlr_log(WLR_ERROR, "Failed to execute surface command"); return 1; } // Test Input Events wlr_log(WLR_INFO, "Sending test input events"); // Mouse event send_mouse_event(&test_context, 100, 200, 1, true); send_mouse_event(&test_context, 100, 200, 1, false); // Keyboard event send_keyboard_event(&test_context, 65, 38, true, 0); // 'A' key press send_keyboard_event(&test_context, 65, 38, false, 0); // 'A' key release // Touch event send_touch_event(&test_context, 300, 400, 1, true); send_touch_event(&test_context, 300, 400, 1, false); wlr_log(WLR_INFO, "RDP Backend Test Complete"); return 0; }*/ /* #include <stdio.h> #include <stdlib.h> #include <wlr/backend.h> #include <wlr/util/log.h> #include <wayland-server-core.h> #include "rdprail_backend.h" #include "rdprail_window.h" // rdprail_test.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <wlr/backend.h> #include <wlr/util/log.h> #include "rdprail.h" // Function prototypes for mock functions int mock_open_pool(struct _GfxRedirServerContext *ctx, GFXREDIR_OPEN_POOL_PDU *open_pool); int mock_create_buffer(struct _GfxRedirServerContext *ctx, GFXREDIR_CREATE_BUFFER_PDU *create_buffer); int mock_surface_command(struct _GfxRedirServerContext *ctx, void *surface_data, int command, RECTANGLE_16 *rect, void *buffer_data); // Mock implementations for context methods int mock_open_pool(struct _GfxRedirServerContext *ctx, GFXREDIR_OPEN_POOL_PDU *open_pool) { open_pool->poolId = 1; wlr_log(WLR_INFO, "Opened pool with ID: %u", open_pool->poolId); return 0; } int mock_create_buffer(struct _GfxRedirServerContext *ctx, GFXREDIR_CREATE_BUFFER_PDU *create_buffer) { create_buffer->bufferId = 1; wlr_log(WLR_INFO, "Created buffer in pool %u with ID: %u", create_buffer->poolId, create_buffer->bufferId); return 0; } int mock_surface_command(struct _GfxRedirServerContext *ctx, void *surface_data, int command, RECTANGLE_16 *rect, void *buffer_data) { wlr_log(WLR_INFO, "Surface command executed"); return 0; } // Prototype for main to satisfy strict prototypes int main(void); // Create a test context GfxRedirServerContext test_context = { .OpenPool = mock_open_pool, .CreateBuffer = mock_create_buffer, .SurfaceCommand = mock_surface_command, .HandleInput = default_handle_input, .HandleMouseEvent = default_handle_mouse_event, .HandleKeyboardEvent = default_handle_keyboard_event, .HandleTouchEvent = default_handle_touch_event }; static void handle_window_create(struct wlr_rdp_window *window, void *data) { printf("Window created: %dx%d\n", window->width, window->height); } static void handle_window_destroy(struct wlr_rdp_window *window, void *data) { printf("Window destroyed: %dx%d\n", window->width, window->height); } */ /* int main(void) { // Set logging level for visibility wlr_log_init(WLR_DEBUG, NULL); wlr_log(WLR_INFO, "Starting RDP Backend Test"); // Test Pool Creation GFXREDIR_OPEN_POOL_PDU open_pool = {0}; if (test_context.OpenPool(&test_context, &open_pool) != 0) { wlr_log(WLR_ERROR, "Failed to open pool"); return 1; } // Test Buffer Creation GFXREDIR_CREATE_BUFFER_PDU create_buffer = { .poolId = open_pool.poolId, .width = 640, .height = 480, .format = 1 // Assuming ARGB8888 }; if (test_context.CreateBuffer(&test_context, &create_buffer) != 0) { wlr_log(WLR_ERROR, "Failed to create buffer"); return 1; } // Test Surface Command uint32_t buffer_id = create_buffer.bufferId; RECTANGLE_16 rect = { .left = 0, .top = 0, .right = 640, .bottom = 480 }; if (test_context.SurfaceCommand(&test_context, NULL, GFX_REDIR_SURFACE_COMMAND_UPDATEREGION, &rect, &buffer_id) != 0) { wlr_log(WLR_ERROR, "Failed to execute surface command"); return 1; } // Test Input Events wlr_log(WLR_INFO, "Sending test input events"); // Mouse event send_mouse_event(&test_context, 100, 200, 1, true); send_mouse_event(&test_context, 100, 200, 1, false); // Keyboard event send_keyboard_event(&test_context, 65, 38, true, 0); // 'A' key press send_keyboard_event(&test_context, 65, 38, false, 0); // 'A' key release // Touch event send_touch_event(&test_context, 300, 400, 1, true); send_touch_event(&test_context, 300, 400, 1, false); wlr_log(WLR_INFO, "RDP Backend Test Complete"); // Initialize Wayland display struct wl_display *display = wl_display_create(); if (!display) { fprintf(stderr, "Failed to create wayland display\n"); return 1; } // Create RDP backend struct wlr_backend *backend = wlr_rdp_backend_create(display, NULL, NULL); if (!backend) { fprintf(stderr, "Failed to create RDP backend\n"); wl_display_destroy(display); return 1; } // Get RDP backend from generic backend struct wlr_rdp_backend *rdp_backend = get_rdp_backend_from_backend(backend); if (!rdp_backend) { fprintf(stderr, "Failed to get RDP backend\n"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } // Print GPU info rdp_backend_print_gpu_info(rdp_backend); // Test GPU if (!rdp_backend_test_gpu(rdp_backend)) { fprintf(stderr, "GPU test failed!\n"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } printf("GPU test passed!\n"); // Set window callbacks wlr_rdp_backend_set_window_callbacks(rdp_backend, handle_window_create, handle_window_destroy, NULL ); // Create a test window struct wlr_rdp_window *window = wlr_rdp_window_create(rdp_backend, 640, 480); if (!window) { fprintf(stderr, "Failed to create window\n"); goto cleanup; } // Start the event loop printf("Starting Wayland event loop...\n"); wl_display_run(display); // Cleanup window wlr_rdp_window_destroy(window); cleanup: // Cleanup backend wlr_backend_destroy(backend); wl_display_destroy(display); return 0; } */ /* int main(void) { wLog* logger = WLog_Get("rdprail-test"); WLog_SetLogLevel(logger, WLOG_DEBUG); WLog_Print(logger, WLOG_INFO, "Starting RDP Backend Test with VAIL"); // Initialize Wayland display struct wl_display *display = wl_display_create(); if (!display) { WLog_Print(logger, WLOG_ERROR, "Failed to create wayland display"); return 1; } // Create RDP backend struct wlr_backend *backend = wlr_rdp_backend_create(display, NULL, NULL); if (!backend) { WLog_Print(logger, WLOG_ERROR, "Failed to create RDP backend"); wl_display_destroy(display); return 1; } // Get RDP backend and test GPU capabilities struct wlr_rdp_backend *rdp_backend = get_rdp_backend_from_backend(backend); if (!rdp_backend) { WLog_Print(logger, WLOG_ERROR, "Failed to get RDP backend"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } // Print GPU info and test capabilities rdp_backend_print_gpu_info(rdp_backend); if (!rdp_backend_test_gpu(rdp_backend)) { WLog_Print(logger, WLOG_ERROR, "GPU test failed!"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } WLog_Print(logger, WLOG_INFO, "GPU test passed!"); // Create test pattern in GPU buffer if (!rdp_backend->redir_ctx) { WLog_Print(logger, WLOG_ERROR, "No RAIL context available"); goto cleanup; } // Create pool and buffer GFXREDIR_OPEN_POOL_PDU pool_pdu = {0}; if (rdp_backend->redir_ctx->OpenPool(rdp_backend->redir_ctx, &pool_pdu) != 0) { WLog_Print(logger, WLOG_ERROR, "Failed to create pool"); goto cleanup; } GFXREDIR_CREATE_BUFFER_PDU buffer_pdu = { .poolId = pool_pdu.poolId, .width = 640, .height = 480, .format = PIXEL_FORMAT_BGRA32 }; if (rdp_backend->redir_ctx->CreateBuffer(rdp_backend->redir_ctx, &buffer_pdu) != 0) { WLog_Print(logger, WLOG_ERROR, "Failed to create buffer"); goto cleanup; } // Create a window that will use the buffer struct wlr_rdp_window *window = wlr_rdp_window_create(rdp_backend, 640, 480); if (!window) { WLog_Print(logger, WLOG_ERROR, "Failed to create window"); goto cleanup; } // Set up the surface command RECTANGLE_16 rect = { .left = 0, .top = 0, .right = 640, .bottom = 480 }; // Send surface command to display the buffer if (rdp_backend->redir_ctx->SurfaceCommand(rdp_backend->redir_ctx, NULL, // surface data RDPGFX_CMDID_SURFACETOSURFACE, &rect, &buffer_pdu.bufferId) != 0) { WLog_Print(logger, WLOG_ERROR, "Failed to execute surface command"); goto cleanup; } // Run the event loop WLog_Print(logger, WLOG_INFO, "Starting event loop..."); wl_display_run(display); cleanup: if (window) { wlr_rdp_window_destroy(window); } wlr_backend_destroy(backend); wl_display_destroy(display); return 0; }*/ // rdprail_test.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <wlr/backend.h> #include <wlr/util/log.h> #include <wayland-server-core.h> #include <freerdp/types.h> #include <freerdp/codec/color.h> #include <rfb/rfb.h> #include "rdprail.h" #include "rdprail_backend.h" #include <rfb/rfbconfig.h> #include <rfb/rfb.h> // Forward declarations struct wlr_rdp_window; struct wlr_rdp_backend; int export_buffer_to_ppm(void *buffer, int width, int height, const char *filename); // Function prototypes void create_vail_diagnostic_buffer(void *buffer, int width, int height); void convert_buffer_for_vnc(void *src_buffer, unsigned char *vnc_buffer, int width, int height); int start_vnc_server_for_buffer(void *buffer, int width, int height); void update_vnc_buffer(void *src_buffer, int width, int height); void* vnc_server_thread(void *arg); void debug_buffer_contents(char *buffer, int width, int height, const char *label); // VNC server context to maintain state // VNC server context to maintain state // VNC server context to maintain state // VNC server context with animation support typedef struct { rfbScreenInfoPtr screen; int width; int height; volatile bool running; uint32_t frame_counter; pthread_mutex_t frame_mutex; } VNCServer; static VNCServer *g_vnc_server = NULL; // Debug function to check buffer contents void debug_buffer_contents(char *buffer, int width, int height, const char *label) { fprintf(stdout, "Buffer check (%s) - first 4 pixels:\n", label); for (int i = 0; i < 4; i++) { unsigned char r = buffer[i * 4 + 0]; unsigned char g = buffer[i * 4 + 1]; unsigned char b = buffer[i * 4 + 2]; fprintf(stdout, "Pixel %d: R:%02x G:%02x B:%02x\n", i, r, g, b); } } // Animation function to update the pattern static void update_animation_frame(char *framebuffer, int width, int height, uint32_t frame) { uint32_t *fb32 = (uint32_t*)framebuffer; float time = frame * 0.1f; // Slow down the animation for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Create a moving wave pattern float dx = (float)x / width; float dy = (float)y / height; float wave = sinf(dx * 10 + time) * cosf(dy * 10 + time) * 0.5f + 0.5f; // Create color components with phase shifts uint8_t r = (uint8_t)(255 * (sinf(wave * 3.14 + time) * 0.5f + 0.5f)); uint8_t g = (uint8_t)(255 * (sinf(wave * 3.14 + time + 3.14 * 2/3) * 0.5f + 0.5f)); uint8_t b = (uint8_t)(255 * (sinf(wave * 3.14 + time + 3.14 * 4/3) * 0.5f + 0.5f)); // Combine into ARGB fb32[y * width + x] = (0xFF << 24) | (r << 16) | (g << 8) | b; } } } // Mouse handler (just ignore mouse events) static void handle_mouse(int buttonMask, int x, int y, rfbClientPtr cl) { // Intentionally empty - ignore mouse events } // Client connection handler static enum rfbNewClientAction vnc_new_client(rfbClientPtr cl) { cl->format.bitsPerPixel = 32; cl->format.depth = 24; cl->format.bigEndian = FALSE; cl->format.trueColour = TRUE; cl->format.redMax = 255; cl->format.greenMax = 255; cl->format.blueMax = 255; cl->format.redShift = 16; cl->format.greenShift = 8; cl->format.blueShift = 0; // Force RAW encoding and disable features cl->preferredEncoding = rfbEncodingRaw; cl->useCopyRect = FALSE; cl->enableCursorShapeUpdates = FALSE; cl->enableCursorPosUpdates = FALSE; cl->enableLastRectEncoding = FALSE; cl->useNewFBSize = FALSE; fprintf(stdout, "New client connected - forcing RAW encoding\n"); return RFB_CLIENT_ACCEPT; } // Animation thread function static void* animation_thread(void *arg) { VNCServer *server = (VNCServer*)arg; while (server->running) { pthread_mutex_lock(&server->frame_mutex); if (server->screen && server->screen->frameBuffer) { // Update animation update_animation_frame(server->screen->frameBuffer, server->width, server->height, server->frame_counter++); // Mark screen as modified rfbMarkRectAsModified(server->screen, 0, 0, server->width, server->height); } pthread_mutex_unlock(&server->frame_mutex); // Sleep for ~16ms (60fps) usleep(16666); } return NULL; } // VNC server thread function void* vnc_server_thread(void *arg) { VNCServer *server = (VNCServer*)arg; while (server->running && server->screen) { pthread_mutex_lock(&server->frame_mutex); rfbProcessEvents(server->screen, 100); pthread_mutex_unlock(&server->frame_mutex); } return NULL; } int start_vnc_server_for_buffer(void *input_buffer, int width, int height) { // Cleanup existing server if (g_vnc_server) { g_vnc_server->running = false; usleep(100000); if (g_vnc_server->screen) { rfbScreenCleanup(g_vnc_server->screen); } pthread_mutex_destroy(&g_vnc_server->frame_mutex); free(g_vnc_server); g_vnc_server = NULL; } // Allocate server context g_vnc_server = calloc(1, sizeof(VNCServer)); if (!g_vnc_server) { fprintf(stderr, "Failed to allocate VNC server context\n"); return -1; } // Initialize mutex if (pthread_mutex_init(&g_vnc_server->frame_mutex, NULL) != 0) { fprintf(stderr, "Failed to initialize mutex\n"); free(g_vnc_server); return -1; } // Initialize VNC screen rfbScreenInfoPtr screen = rfbGetScreen(NULL, NULL, width, height, 8, 3, 4); if (!screen) { fprintf(stderr, "Failed to create VNC screen\n"); pthread_mutex_destroy(&g_vnc_server->frame_mutex); free(g_vnc_server); return -1; } // Allocate framebuffer char *framebuffer = calloc(width * height * 4, 1); if (!framebuffer) { fprintf(stderr, "Failed to allocate framebuffer\n"); pthread_mutex_destroy(&g_vnc_server->frame_mutex); free(g_vnc_server); return -1; } // Configure screen screen->frameBuffer = framebuffer; screen->alwaysShared = TRUE; screen->serverFormat.bitsPerPixel = 32; screen->serverFormat.depth = 24; screen->serverFormat.trueColour = TRUE; screen->serverFormat.bigEndian = FALSE; screen->serverFormat.redMax = 255; screen->serverFormat.greenMax = 255; screen->serverFormat.blueMax = 255; screen->serverFormat.redShift = 16; screen->serverFormat.greenShift = 8; screen->serverFormat.blueShift = 0; // Set up event handlers screen->ptrAddEvent = handle_mouse; screen->kbdAddEvent = NULL; screen->newClientHook = vnc_new_client; // Disable features screen->permitFileTransfer = FALSE; screen->maxRectsPerUpdate = 1; // Store info g_vnc_server->screen = screen; g_vnc_server->width = width; g_vnc_server->height = height; g_vnc_server->running = true; g_vnc_server->frame_counter = 0; // Initialize server rfbInitServer(screen); // Create animation thread pthread_t anim_thread; if (pthread_create(&anim_thread, NULL, animation_thread, g_vnc_server) != 0) { fprintf(stderr, "Failed to create animation thread\n"); free(framebuffer); rfbScreenCleanup(screen); pthread_mutex_destroy(&g_vnc_server->frame_mutex); free(g_vnc_server); return -1; } pthread_detach(anim_thread); // Create server thread pthread_t server_thread; if (pthread_create(&server_thread, NULL, vnc_server_thread, g_vnc_server) != 0) { fprintf(stderr, "Failed to create server thread\n"); g_vnc_server->running = false; usleep(100000); free(framebuffer); rfbScreenCleanup(screen); pthread_mutex_destroy(&g_vnc_server->frame_mutex); free(g_vnc_server); return -1; } pthread_detach(server_thread); fprintf(stdout, "VNC server started on port 5900 with animated pattern.\n"); return 0; } int vail_display_window( struct wlr_rdp_window *window, struct wlr_rdp_backend *rdp_backend ); // Diagnostic function to create a detailed test pattern in the buffer void create_vail_diagnostic_buffer(void *buffer, int width, int height) { if (!buffer) return; uint32_t *pixel_data = (uint32_t*)buffer; // Create a more informative diagnostic pattern for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Gradient with diagonal lines and color sections uint8_t r, g, b; // Diagonal gradient if ((x + y) % 20 < 10) { // Blue-green section r = (uint8_t)((float)x / width * 128); g = (uint8_t)((float)y / height * 255); b = 255 - r; } else { // Red-yellow section r = 255; g = (uint8_t)((float)y / height * 255); b = (uint8_t)((float)x / width * 128); } // BGRA format (using FreeRDP's pixel format) pixel_data[y * width + x] = (255 << 24) | // Alpha (b << 16) | // Blue (g << 8) | // Green r; // Red } } } // Function to export buffer contents as a PPM image int export_buffer_to_ppm(void *buffer, int width, int height, const char *filename) { if (!buffer || width <= 0 || height <= 0 || !filename) { fprintf(stderr, "Invalid parameters for buffer export\n"); return -1; } FILE *file = fopen(filename, "wb"); if (!file) { perror("Failed to open file for writing"); return -1; } // Write PPM header (P6 format - binary RGB) fprintf(file, "P6\n%d %d\n255\n", width, height); // Convert BGRA to RGB and write uint32_t *pixel_data = (uint32_t*)buffer; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint32_t pixel = pixel_data[y * width + x]; // Extract RGB components (from BGRA) uint8_t r = pixel & 0xFF; uint8_t g = (pixel >> 8) & 0xFF; uint8_t b = (pixel >> 16) & 0xFF; // Ignore alpha (pixel >> 24) // Write RGB bytes fputc(r, file); fputc(g, file); fputc(b, file); } } fclose(file); printf("Buffer exported to %s\n", filename); return 0; } // Enhanced VAIL window display function int vail_display_window( struct wlr_rdp_window *window, struct wlr_rdp_backend *rdp_backend ) { if (!rdp_backend || !rdp_backend->redir_ctx) { wlr_log(WLR_ERROR, "Invalid RDP backend or redirection context"); return -1; } // Diagnostic: Log detailed window information wlr_log(WLR_INFO, "VAIL Window Details:"); wlr_log(WLR_INFO, " Dimensions: %d x %d", window->width, window->height); // Shared memory buffer details void *buffer_data = NULL; size_t buffer_size = window->width * window->height * 4; int buffer_fd = -1; // Retrieve shared memory buffer_data = rdp_get_shared_memory(0, &buffer_size, &buffer_fd); if (!buffer_data) { wlr_log(WLR_ERROR, "Failed to get shared memory"); return -1; } // Log buffer details wlr_log(WLR_INFO, " Buffer Size: %zu bytes", buffer_size); wlr_log(WLR_INFO, " Buffer FD: %d", buffer_fd); // Fill buffer with diagnostic pattern create_vail_diagnostic_buffer(buffer_data, window->width, window->height); // export_buffer_to_ppm(buffer_data, window->width, window->height, "/tmp/vail_buffer.ppm"); start_vnc_server_for_buffer(buffer_data, window->width, window->height); // Attempt surface creation (if method exists) void *surface_data = NULL; if (rdp_backend->redir_ctx->CreateSurface) { wlr_log(WLR_INFO, "Attempting to create surface"); if (rdp_backend->redir_ctx->CreateSurface( rdp_backend->redir_ctx, window->width, window->height, &surface_data) != 0) { wlr_log(WLR_ERROR, "Failed to create surface"); return -1; } } // Prepare full rectangle for surface update RECTANGLE_16 full_rect = { .left = 0, .top = 0, .right = window->width, .bottom = window->height }; // Attempt surface update if (rdp_backend->redir_ctx->UpdateSurface) { wlr_log(WLR_INFO, "Attempting to update surface"); if (rdp_backend->redir_ctx->UpdateSurface( rdp_backend->redir_ctx, surface_data, &full_rect, buffer_data) != 0) { wlr_log(WLR_ERROR, "Failed to update surface"); return -1; } } // Cleanup shared memory rdp_cleanup_shared_memory(buffer_data, buffer_size, buffer_fd); wlr_log(WLR_INFO, "VAIL window display process completed"); return 0; } int main(void) { // Initialize logging wlr_log_init(WLR_DEBUG, NULL); wlr_log(WLR_INFO, "Starting RDP Backend Test with VAIL"); // Initialize Wayland display struct wl_display *display = wl_display_create(); if (!display) { wlr_log(WLR_ERROR, "Failed to create wayland display"); return 1; } // Create RDP backend struct wlr_backend *backend = wlr_rdp_backend_create(display, NULL, NULL); if (!backend) { wlr_log(WLR_ERROR, "Failed to create RDP backend"); wl_display_destroy(display); return 1; } // Get RDP backend and test GPU capabilities struct wlr_rdp_backend *rdp_backend = get_rdp_backend_from_backend(backend); if (!rdp_backend) { wlr_log(WLR_ERROR, "Failed to get RDP backend"); wlr_backend_destroy(backend); wl_display_destroy(display); return 1; } // Verify VAIL context if (!rdp_backend->redir_ctx) { wlr_log(WLR_ERROR, "No RAIL/VAIL context available"); goto cleanup; } // Create pool and buffer GFXREDIR_OPEN_POOL_PDU pool_pdu = {0}; if (rdp_backend->redir_ctx->OpenPool(rdp_backend->redir_ctx, &pool_pdu) != 0) { wlr_log(WLR_ERROR, "Failed to create pool"); goto cleanup; } GFXREDIR_CREATE_BUFFER_PDU buffer_pdu = { .poolId = pool_pdu.poolId, .width = 640, .height = 480, .format = PIXEL_FORMAT_BGRA32 }; if (rdp_backend->redir_ctx->CreateBuffer(rdp_backend->redir_ctx, &buffer_pdu) != 0) { wlr_log(WLR_ERROR, "Failed to create buffer"); goto cleanup; } // Create a window that will use the buffer struct wlr_rdp_window *window = wlr_rdp_window_create(rdp_backend, 640, 480); if (!window) { wlr_log(WLR_ERROR, "Failed to create window"); goto cleanup; } // Attempt to display the window using VAIL mechanism if (vail_display_window(window, rdp_backend) != 0) { wlr_log(WLR_ERROR, "Failed to display VAIL window"); goto cleanup; } // Run the event loop wlr_log(WLR_INFO, "Starting event loop..."); wl_display_run(display); cleanup: if (window) { wlr_rdp_window_destroy(window); } wlr_backend_destroy(backend); wl_display_destroy(display); return 0; }
Leave a Comment