Untitled
/* rdprail.c */ #include <assert.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/syscall.h> #include <linux/memfd.h> #include <wlr/render/allocator.h> #include <wlr/render/drm_format_set.h> #include <wlr/types/wlr_buffer.h> #include <wlr/interfaces/wlr_buffer.h> #include <wlr/util/log.h> #include <drm/drm_fourcc.h> #include <stdio.h> #include "rdprail.h" #include <unistd.h> #include <sys/syscall.h> #include <sys/mman.h> #include <fcntl.h> // For open() and O_RDWR #include <gbm.h> // For gbm_create_device and gbm_device_destroy #include <wayland-server.h> // For wl_event_loop functions #include "backend/rdprail/rdprail.h" // For RDP backend functions #include "backend/backend.h" void wlr_rdp_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer); // Rest of the existing code remains the same, but add these function implementations if they're not already defined /* void wlr_rdp_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { // Implement the function body, likely similar to other buffer access end functions in wlroots // This might involve releasing locks, syncing memory, or other cleanup }*/ // Logging function for debugging static void log_buffer_state(struct wlr_buffer *buffer, const char *context) { fprintf(stderr, "Buffer state at %s:\n", context); fprintf(stderr, " Width: %d\n", buffer->width); fprintf(stderr, " Height: %d\n", buffer->height); fprintf(stderr, " Impl: %p\n", (void*)buffer->impl); fprintf(stderr, " Dropped: %s\n", buffer->dropped ? "true" : "false"); fprintf(stderr, " Locks: %zu\n", buffer->n_locks); fprintf(stderr, " Accessing data ptr: %s\n", buffer->accessing_data_ptr ? "true" : "false"); } // Placeholder implementation for shared memory retrieval /*void* rdp_get_shared_memory(uint32_t pool_id, size_t *size, int *fd) { // Use syscall for memfd_create as a fallback *fd = syscall(SYS_memfd_create, "rdp_buffer", MFD_CLOEXEC); // If syscall fails, fall back to temporary file if (*fd == -1) { char temp_path[] = "/tmp/rdp_buffer_XXXXXX"; *fd = mkstemp(temp_path); if (*fd == -1) { wlr_log(WLR_ERROR, "Failed to create shared memory"); return NULL; } // Unlink the temporary file so it's not visible in the filesystem unlink(temp_path); } // Set size *size = 1024 * 1024; // 1MB // Resize the file descriptor if (ftruncate(*fd, *size) == -1) { wlr_log(WLR_ERROR, "Failed to resize shared memory"); close(*fd); return NULL; } // Map the shared memory void *memory = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); if (memory == MAP_FAILED) { wlr_log(WLR_ERROR, "Failed to map shared memory"); close(*fd); return NULL; } return memory; }*/ void* rdp_get_shared_memory(uint32_t pool_id, size_t *size, int *fd) { *size = 640 * 480 * 4; // Calculate exact size needed // Create memfd with specific size *fd = syscall(SYS_memfd_create, "rdp_buffer", MFD_CLOEXEC); if (*fd == -1) { char temp_path[] = "/tmp/rdp_buffer_XXXXXX"; *fd = mkstemp(temp_path); if (*fd == -1) { return NULL; } unlink(temp_path); } // Set the size if (ftruncate(*fd, *size) == -1) { close(*fd); return NULL; } // Map the memory with proper protection flags void *memory = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); if (memory == MAP_FAILED) { close(*fd); return NULL; } // Clear the memory memset(memory, 0, *size); return memory; } // Mock RDP context functions static int mock_open_pool(struct _GfxRedirServerContext *ctx, GFXREDIR_OPEN_POOL_PDU *open_pool) { static uint32_t next_pool_id = 1; open_pool->poolId = next_pool_id++; fprintf(stderr, "RDP Mock: Created pool %u\n", open_pool->poolId); return 0; } static int mock_create_buffer(struct _GfxRedirServerContext *ctx, GFXREDIR_CREATE_BUFFER_PDU *create_buffer) { static uint32_t next_buffer_id = 1; create_buffer->bufferId = next_buffer_id++; fprintf(stderr, "RDP Mock: Created buffer %u in pool %u\n", create_buffer->bufferId, create_buffer->poolId); return 0; } // Buffer method implementations /*static void wlr_rdp_buffer_destroy(struct wlr_buffer *buffer) { struct wlr_rdp_buffer *rdp_buffer = wl_container_of(buffer, rdp_buffer, buffer); fprintf(stderr, "Destroying RDP buffer\n"); // Ensure no data access in progress if (buffer->accessing_data_ptr) { wlr_log(WLR_ERROR, "Destroying buffer while data access in progress"); } // Unmap and close shared memory if (rdp_buffer->rdp_memory) { munmap(rdp_buffer->rdp_memory, rdp_buffer->rdp_memory_size); } if (rdp_buffer->fd != -1) { close(rdp_buffer->fd); } // Free the buffer struct free(rdp_buffer); }*/ static void wlr_rdp_buffer_destroy(struct wlr_buffer *buffer) { struct wlr_rdp_buffer *rdp_buffer = wl_container_of(buffer, rdp_buffer, buffer); // Wait for any ongoing data access to complete if (rdp_buffer->data_access_in_progress) { wlr_rdp_buffer_end_data_ptr_access(buffer); } // Clean up memory if (rdp_buffer->rdp_memory && rdp_buffer->rdp_memory_size > 0) { munmap(rdp_buffer->rdp_memory, rdp_buffer->rdp_memory_size); rdp_buffer->rdp_memory = NULL; } if (rdp_buffer->fd >= 0) { close(rdp_buffer->fd); rdp_buffer->fd = -1; } free(rdp_buffer); } static bool wlr_rdp_buffer_get_dmabuf( struct wlr_buffer *wlr_buffer, struct wlr_dmabuf_attributes *attribs ) { // No DMA-BUF support for this buffer type return false; } static bool wlr_rdp_buffer_get_shm( struct wlr_buffer *wlr_buffer, struct wlr_shm_attributes *attribs ) { struct wlr_rdp_buffer *rdp_buffer = wl_container_of(wlr_buffer, rdp_buffer, buffer); if (!rdp_buffer->rdp_memory) { return false; } attribs->fd = rdp_buffer->fd; attribs->format = DRM_FORMAT_ARGB8888; attribs->width = rdp_buffer->width; attribs->height = rdp_buffer->height; attribs->stride = rdp_buffer->width * 4; attribs->offset = 0; return true; } static bool wlr_rdp_buffer_begin_data_ptr_access( struct wlr_buffer *wlr_buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride ) { struct wlr_rdp_buffer *rdp_buffer = wl_container_of(wlr_buffer, rdp_buffer, buffer); fprintf(stderr, "Beginning data ptr access\n"); log_buffer_state(wlr_buffer, "Begin data ptr access"); // Additional safety checks if (wlr_buffer->accessing_data_ptr) { wlr_log(WLR_ERROR, "Attempting to access buffer data while already in access"); return false; } if (!rdp_buffer->rdp_memory) { wlr_log(WLR_ERROR, "No memory allocated for RDP buffer"); return false; } if (data) { *data = rdp_buffer->rdp_memory; fprintf(stderr, "Data pointer set to %p\n", *data); } if (format) { *format = DRM_FORMAT_ARGB8888; fprintf(stderr, "Format set to %u\n", *format); } if (stride) { *stride = rdp_buffer->width * 4; // 4 bytes per pixel fprintf(stderr, "Stride set to %zu\n", *stride); } // Mark that data access is in progress rdp_buffer->data_access_in_progress = true; return true; } void wlr_rdp_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { struct wlr_rdp_buffer *rdp_buffer = wl_container_of(wlr_buffer, rdp_buffer, buffer); fprintf(stderr, "Ending data ptr access\n"); log_buffer_state(wlr_buffer, "End data ptr access"); // Reset data access flag rdp_buffer->data_access_in_progress = false; } // Define the buffer implementation matching wlr_buffer_impl static const struct wlr_buffer_impl wlr_rdp_buffer_impl = { .destroy = wlr_rdp_buffer_destroy, .get_dmabuf = wlr_rdp_buffer_get_dmabuf, .get_shm = wlr_rdp_buffer_get_shm, .begin_data_ptr_access = wlr_rdp_buffer_begin_data_ptr_access, .end_data_ptr_access = wlr_rdp_buffer_end_data_ptr_access, }; // Allocator creation methods static struct wlr_buffer *rdp_allocator_create_buffer( struct wlr_allocator *alloc, int width, int height, const struct wlr_drm_format *format) { struct wlr_rdp_allocator *rdp_alloc = wl_container_of(alloc, rdp_alloc, base); fprintf(stderr, "Creating RDP buffer: %dx%d\n", width, height); // Create RDP pool and buffer GFXREDIR_OPEN_POOL_PDU open_pool = {0}; if (rdp_alloc->redir_ctx->OpenPool(rdp_alloc->redir_ctx, &open_pool) != 0) { wlr_log(WLR_ERROR, "Failed to open RDP pool"); return NULL; } GFXREDIR_CREATE_BUFFER_PDU create_buffer = { .poolId = open_pool.poolId, .width = width, .height = height, .format = 1 // Placeholder for GFXREDIR_BUFFER_PIXEL_FORMAT_ARGB_8888 }; if (rdp_alloc->redir_ctx->CreateBuffer(rdp_alloc->redir_ctx, &create_buffer) != 0) { wlr_log(WLR_ERROR, "Failed to create RDP buffer"); return NULL; } // Allocate RDP buffer struct struct wlr_rdp_buffer *rdp_buffer = calloc(1, sizeof(struct wlr_rdp_buffer)); if (!rdp_buffer) { wlr_log(WLR_ERROR, "Failed to allocate wlr_rdp_buffer"); return NULL; } rdp_buffer->pool_id = open_pool.poolId; rdp_buffer->buffer_id = create_buffer.bufferId; rdp_buffer->width = width; rdp_buffer->height = height; rdp_buffer->fd = -1; rdp_buffer->data_access_in_progress = false; // Acquire shared memory rdp_buffer->rdp_memory = rdp_get_shared_memory( open_pool.poolId, &rdp_buffer->rdp_memory_size, &rdp_buffer->fd); if (!rdp_buffer->rdp_memory) { wlr_log(WLR_ERROR, "Failed to get shared memory for RDP buffer"); free(rdp_buffer); return NULL; } // Initialize the buffer with our implementation wlr_buffer_init( &rdp_buffer->buffer, &wlr_rdp_buffer_impl, width, height ); fprintf(stderr, "RDP buffer created successfully\n"); return &rdp_buffer->buffer; } static void rdp_allocator_destroy(struct wlr_allocator *alloc) { struct wlr_rdp_allocator *rdp_alloc = wl_container_of(alloc, rdp_alloc, base); fprintf(stderr, "Destroying RDP allocator\n"); free(rdp_alloc); } static const struct wlr_allocator_interface rdp_allocator_impl = { .create_buffer = rdp_allocator_create_buffer, .destroy = rdp_allocator_destroy, }; struct wlr_allocator *wlr_rdp_allocator_create( GfxRedirServerContext *redir_ctx) { fprintf(stderr, "Creating RDP allocator\n"); if (!redir_ctx) { wlr_log(WLR_ERROR, "Invalid RDP context"); return NULL; } struct wlr_rdp_allocator *alloc = calloc(1, sizeof(struct wlr_rdp_allocator)); if (!alloc) { wlr_log(WLR_ERROR, "Failed to allocate RDP allocator"); return NULL; } // Initialize allocator wlr_allocator_init(&alloc->base, &rdp_allocator_impl, WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_SHM); // Store RDP context alloc->redir_ctx = redir_ctx; fprintf(stderr, "RDP allocator created successfully\n"); return &alloc->base; }
Leave a Comment