--- /dev/null
+/*
+ Card types
+
+ Currently implements DRM dumb buffer interface only.
+
+*/
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+// requires global.c
+
+//--------------------------------------------------------------------------------
+// Card Abstract Interface
+
+typedef void (*CaptureCallback)
+(
+ Frame *captured_frame
+ ,Frame *display_frame
+ ,CircularQueue *context_window
+ ,Closure *closure
+ );
+
+typedef struct {
+ void (*capture)(Frame *capture_frame ,CaptureCallback f ,Closure *closure);
+ void (*display)(Frame *dipslay_frame); // nonblocking
+} Card;
+
+//--------------------------------------------------------------------------------
+// Instance data for the generic primitive `drm` card.
+
+typedef struct {
+
+} CardPrimitiveDRM·CaptureClosure;
+
+CardPrimitiveDRM·capture(Frame *capture_frame ,CaptureCallback f ,Closure *closure){
+ CardPrimitiveDRM·CaptureClosure capture_closure = (CardPrimitiveDRM·CaptureClosure *)closure;
+
+}
+
+
+
+// Frame stream interface
+typedef struct {
+ void (*capture_frame)(Frame *frame ,FrameCallback callback ,void *user_data);
+} FrameStream;
+
+// Example of the frame stream implementation (for capturing frames from some device)
+void FrameStreamDRM·capture(Frame *frame ,FrameCallback callback ,void *user_data){
+ // Simulate frame capture or retrieval logic here...
+
+ // Once the frame is captured, call the provided callback
+ Frame *display_frame = NULL; // Allocate or retrieve the display frame as needed
+ CircularQueue *context_window = NULL; // Optionally pass context
+ callback(frame, display_frame, context_window, user_data);
+}
// Search for an element where f returns non-null (exist pattern)
-void* Frame·exist(Frame·Instance *frame ,Frame·PixelPredicate f ,void *arg) {
+void* Frame·exist(Frame·Instance *frame ,Frame·PixelPredicate f ,Closure *closure) {
if (!frame || !f) return NULL;
Index32·Instance index = Index32·origin; // Start from (0, 0)
do{
void *pixel = Frame·access(frame ,index);
if( pixel ){
- void *result = f(frame ,pixel ,index ,arg);
+ void *result = f(frame ,pixel ,index ,closure);
if( result ) return result;
}
}while( Index32·increment(&index ,bound ,frame->pixel_size) );
typedef struct {
Frame·PixelPredicate f; // PixelPredicate type for the function
- void *arg; // User-provided metadata
-} Frame·every_arg_t;
+ Closure *closure; // User-provided metadata
+} Frame·every_closure_t;
-void *Frame·every_1(Frame *frame ,void *pixel ,Index32·Instance index ,void *arg0) {
- Frame·every_arg_t *ea = (Frame·every_arg_t *)arg0;
- ea->f(frame ,pixel ,index ,ea->arg);
+void *Frame·every_1(Frame *frame ,void *pixel ,Index32·Instance index ,Closure *closure0) {
+ Frame·every_closure_t *ea = (Frame·every_closure_t *)closure0;
+ ea->f(frame ,pixel ,index ,ea->closure);
return NULL; // Return NULL for `every`
}
-void Frame·every(Frame *frame ,Frame·PixelPredicate f ,void *arg) {
- Frame·every_arg_t ea = {.f = f ,.arg = arg};
+void Frame·every(Frame *frame ,Frame·PixelPredicate f ,Closure *closure) {
+ Frame·every_closure_t ea = {.f = f ,.closure = closure};
Frame·exist(frame ,Frame·every_1 ,&ea);
}
typedef struct {
Frame·PixelPredicate f; // PixelPredicate type for the function
- void *arg; // User-provided metadata
-} Frame·all_arg_t;
+ Closure *closure; // User-provided metadata
+} Frame·all_closure_t;
-void *Frame·all_1(Frame *frame ,void *pixel ,Index32·Instance index ,void *arg0) {
- Frame·all_arg_t *aa = (Frame·all_arg_t *)arg0;
- if( !aa->f(frame ,pixel ,index ,aa->arg) ) return pixel; // If a pixel doesn't satisfy the predicate, return it
+void *Frame·all_1(Frame *frame ,void *pixel ,Index32·Instance index ,Closure *closure0) {
+ Frame·all_closure_t *aa = (Frame·all_closure_t *)closure0;
+ if( !aa->f(frame ,pixel ,index ,aa->closure) ) return pixel; // If a pixel doesn't satisfy the predicate, return it
return NULL;
}
-bool Frame·all(Frame *frame ,Frame·PixelPredicate f ,void *arg) {
- Frame·all_arg_t aa = {.f = f ,.arg = arg};
+bool Frame·all(Frame *frame ,Frame·PixelPredicate f ,Closure *closure) {
+ Frame·all_closure_t aa = {.f = f ,.closure = closure};
return Frame·exist(frame ,Frame·all_1 ,&aa) == NULL; // If `exist` returns NULL, all elements satisfied the predicate
}
// Fill the frame with a specific pixel
-void *Frame·fill_1(Frame *frame ,void *pixel_in_frame ,Index32·Instance index ,void *arg) {
- // `arg` contains the pixel value to fill with
- const void *fill_pixel = arg;
+void *Frame·fill_1(Frame *frame ,void *pixel_in_frame ,Index32·Instance index ,Closure *closure) {
+ // `closure` contains the pixel value to fill with
+ const void *fill_pixel = closure;
memcpy(pixel_in_frame ,fill_pixel ,((Frame·Instance *)frame)->pixel_size);
return NULL; // Return NULL to indicate that we don't stop the loop (like `Frame·every`)
}
--- /dev/null
+/*
+A Frame is a 2D array of pixels.
+
+The main loop consists of:
+
+1. capture frame
+2. transform frame
+3. display frame
+
+The capture frame is what the graphics card would have dip slayed, had we not
+interceded.
+
+This version uses dumb buffers that the program manages.
+
+*/
+
+void main_loop(){
+
+
+
+}
+
+
+int main() {
+ int fd = open("/dev/dri/card2", O_RDWR | O_CLOEXEC); // Open the DRM device
+ if (fd < 0) {
+ perror("Failed to open DRM device");
+ return -1;
+ }
+
+ // Create a dumb buffer
+ struct drm_mode_create_dumb create_dumb = {0};
+ create_dumb.width = 1920;
+ create_dumb.height = 1080;
+ create_dumb.bpp = 32; // 32 bits per pixel
+
+ if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb) < 0) {
+ perror("DRM_IOCTL_MODE_CREATE_DUMB failed");
+ close(fd);
+ return -1;
+ }
+
+ // Map the dumb buffer
+ struct drm_mode_map_dumb map_dumb = {0};
+ map_dumb.handle = create_dumb.handle;
+
+ if (drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb) < 0) {
+ perror("DRM_IOCTL_MODE_MAP_DUMB failed");
+ close(fd);
+ return -1;
+ }
+
+ size_t buffer_size = create_dumb.size;
+ void* buffer = mmap(NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, map_dumb.offset);
+ if (buffer == MAP_FAILED) {
+ perror("mmap failed for dumb buffer");
+ close(fd);
+ return -1;
+ }
+
+ printf("Dumb buffer created and mapped successfully. Size: %zu bytes\n", buffer_size);
+
+ // Clean up
+ munmap(buffer, buffer_size);
+ struct drm_mode_destroy_dumb destroy_dumb = {0};
+ destroy_dumb.handle = create_dumb.handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+
+ close(fd);
+ return 0;
+}