Untitled
unknown
plain_text
9 months ago
32 kB
8
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;
}Editor is loading...
Leave a Comment