Untitled

 avatar
unknown
plain_text
a month ago
32 kB
5
Indexable
/*#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