Files
LNXRNT/Sources/viewport_server.h
2026-02-20 23:40:15 -08:00

122 lines
4.4 KiB
C

/**
* Viewport Server - Shared Memory Framebuffer Export for Blender Integration
*
* This module provides headless rendering with framebuffer export via shared memory
* for integration with Blender's viewport as an external render engine.
*
* Protocol:
* - RunT renders to offscreen render target
* - Pixels are exported to shared memory each frame
* - Blender Python addon reads shared memory and displays in viewport
*/
#ifndef VIEWPORT_SERVER_H
#define VIEWPORT_SERVER_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#define INPUT_EVENT_NONE 0
#define INPUT_EVENT_MOUSE_MOVE 1
#define INPUT_EVENT_MOUSE_DOWN 2
#define INPUT_EVENT_MOUSE_UP 3
#define INPUT_EVENT_KEY_DOWN 4
#define INPUT_EVENT_KEY_UP 5
#define INPUT_EVENT_MOUSE_WHEEL 6
#define MOUSE_BUTTON_LEFT 0
#define MOUSE_BUTTON_RIGHT 1
#define MOUSE_BUTTON_MIDDLE 2
#define MAX_INPUT_EVENTS 32
#pragma pack(push, 1)
typedef struct {
uint8_t type; // INPUT_EVENT_* type
uint8_t button; // mouse button or key code
int16_t x; // mouse X position or delta
int16_t y; // mouse Y position or delta
int16_t delta; // scroll wheel delta
uint32_t modifiers; // shift/ctrl/alt flags
} InputEvent;
#pragma pack(pop)
// shared memory header structure must match Python end
#pragma pack(push, 1)
typedef struct {
uint32_t magic; // 0x52554E54 = 'RUNT'
uint32_t version; // protocol version (2)
uint32_t width; // current frame width
uint32_t height; // current frame height
uint64_t frame_id; // incrementing frame counter
uint32_t ready_flag; // 1 = new frame ready, 0 = consumed by blender
uint32_t format; // 0 = RGBA8, 1 = BGRA8
uint32_t viewport_width; // requested viewport width from Blender
uint32_t viewport_height; // requested viewport height from Blender
uint32_t resize_request; // 1 = blender requests resize
uint32_t shutdown_flag; // 1 = blender requests shutdown
uint32_t input_enabled; // 1 = blender is capturing input for RunT
float view_matrix[16]; // view matrix from blender column-major
float proj_matrix[16]; // projection matrix from blender column-major
// camera output from RunT to Blender bidirectional sync
float runt_camera_pos[3]; // camera position from RunT (x, y, z)
float runt_camera_rot[4]; // camera rotation from RunT quaternion: x, y, z, w
uint32_t runt_camera_dirty; // 1 = RunT updated camera, 0 = consumed by blender
// input event queue from blender to RunT
uint32_t input_write_idx; // write index Blender increments
uint32_t input_read_idx; // read index RunT increments
InputEvent input_events[MAX_INPUT_EVENTS]; // ring buffer of input events
// pixel data follows header width * height * 4 bytes for RGBA8
} SharedFramebufferHeader;
#pragma pack(pop)
#define VIEWPORT_MAGIC 0x52554E54
#define VIEWPORT_VERSION 2
#define VIEWPORT_HEADER_SIZE sizeof(SharedFramebufferHeader)
// default shared memory name
#define VIEWPORT_SHMEM_NAME "RUNT_VIEWPORT_FB"
#define VIEWPORT_MAX_WIDTH 4096
#define VIEWPORT_MAX_HEIGHT 4096
// viewport server state
typedef struct {
bool enabled;
bool initialized;
int width;
int height;
char shmem_name[256];
uint64_t frame_count;
void* render_target; // kinc_g4_render_target_t*
uint8_t* pixel_buffer; // CPU-side pixel buffer
void* shmem_handle; // platform-specific handle
void* shmem_ptr; // mapped memory pointer
size_t shmem_size; // total shared memory size
} ViewportServerState;
bool viewport_server_init(const char* shmem_name, int width, int height);
void viewport_server_shutdown(void);
bool viewport_server_is_enabled(void);
void viewport_server_begin_frame(void);
void viewport_server_end_frame(void);
bool viewport_server_check_resize(int* new_width, int* new_height);
bool viewport_server_resize(int new_width, int new_height);
bool viewport_server_check_shutdown(void);
bool viewport_server_get_view_matrix(float* matrix);
bool viewport_server_get_proj_matrix(float* matrix);
ViewportServerState* viewport_server_get_state(void);
void viewport_server_set_camera(float pos_x, float pos_y, float pos_z, float rot_x, float rot_y, float rot_z, float rot_w);
bool viewport_server_read_input(InputEvent* event);
bool viewport_server_input_enabled(void);
#ifdef __cplusplus
}
#endif
#endif