From 1729f8c0b6fd64c8fb554e0489cfcb5c5301ef2f Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Tue, 17 Sep 2024 21:54:57 +0000 Subject: [PATCH] first commit --- developer/Erebus/framebuffer_filter | Bin 0 -> 17112 bytes developer/Erebus/framebuffer_filter.c | 85 ++++ developer/Erebus/transform_frame_stream.c | 369 +++++++++++++++++ developer/Erebus/transform_frame_stream.c~ | 89 ++++ developer/Erebus/transform_frames.c | 89 ++++ developer/Erebus/transform_frames.c~ | 81 ++++ developer/cc/drm_info | Bin 0 -> 17272 bytes developer/cc/drm_info.c | 81 ++++ .../cc/modified_transform_frame_stream.c | 136 ++++++ developer/cc/transform_frame_stream | Bin 0 -> 18512 bytes developer/cc/transform_frame_stream.c | 386 ++++++++++++++++++ developer/cc/transform_frame_stream_2.c | 386 ++++++++++++++++++ developer/developer | 0 13 files changed, 1702 insertions(+) create mode 100755 developer/Erebus/framebuffer_filter create mode 100644 developer/Erebus/framebuffer_filter.c create mode 100644 developer/Erebus/transform_frame_stream.c create mode 100644 developer/Erebus/transform_frame_stream.c~ create mode 100644 developer/Erebus/transform_frames.c create mode 100644 developer/Erebus/transform_frames.c~ create mode 100755 developer/cc/drm_info create mode 100644 developer/cc/drm_info.c create mode 100644 developer/cc/modified_transform_frame_stream.c create mode 100755 developer/cc/transform_frame_stream create mode 100644 developer/cc/transform_frame_stream.c create mode 100644 developer/cc/transform_frame_stream_2.c create mode 100644 developer/developer diff --git a/developer/Erebus/framebuffer_filter b/developer/Erebus/framebuffer_filter new file mode 100755 index 0000000000000000000000000000000000000000..9b49c289685a5dea050876ad0c08c9a5156046f3 GIT binary patch literal 17112 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 literal 0 HcmV?d00001 diff --git a/developer/Erebus/framebuffer_filter.c b/developer/Erebus/framebuffer_filter.c new file mode 100644 index 0000000..fefd64a --- /dev/null +++ b/developer/Erebus/framebuffer_filter.c @@ -0,0 +1,85 @@ +// gcc framebuffer_filter.c -o framebuffer_filter + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_DELTA 10 // Max pixel change allowed + +// Function to clamp a value within a certain range +unsigned char clamp(unsigned char current, unsigned char previous) { + if (current > previous + MAX_DELTA) + return previous + MAX_DELTA; + else if (current < previous - MAX_DELTA) + return previous - MAX_DELTA; + else + return current; +} + +int main() { + int fb_fd = open("/dev/fb0", O_RDWR); + if (fb_fd == -1) { + perror("Error: cannot open framebuffer device"); + return 1; + } + + struct fb_var_screeninfo vinfo; + if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("Error reading variable information"); + close(fb_fd); + return 1; + } + + // Calculate the screen size + int screensize = vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8; + + // Map framebuffer into memory + unsigned char *fb_ptr = (unsigned char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0); + if ((intptr_t)fb_ptr == -1) { + perror("Error: failed to map framebuffer device to memory"); + close(fb_fd); + return 1; + } + + // Allocate memory for previous frame buffer + unsigned char *prev_frame = malloc(screensize); + if (!prev_frame) { + perror("Error: unable to allocate memory for previous frame"); + munmap(fb_ptr, screensize); + close(fb_fd); + return 1; + } + + // Initial copy of the framebuffer + memcpy(prev_frame, fb_ptr, screensize); + + // Frame processing loop + while (1) { + // Process each pixel (assuming 32 bits per pixel - adjust as needed) + for (int i = 0; i < screensize; i += 4) { + // R, G, B values + fb_ptr[i] = clamp(fb_ptr[i], prev_frame[i]); // Blue + fb_ptr[i + 1] = clamp(fb_ptr[i + 1], prev_frame[i + 1]); // Green + fb_ptr[i + 2] = clamp(fb_ptr[i + 2], prev_frame[i + 2]); // Red + // fb_ptr[i + 3] = Alpha channel, leave as is or modify if necessary + } + + // Copy current frame to previous frame for the next iteration + memcpy(prev_frame, fb_ptr, screensize); + + // Sleep to avoid high CPU usage + usleep(16000); // ~60 FPS + } + + // Clean up + free(prev_frame); + munmap(fb_ptr, screensize); + close(fb_fd); + + return 0; +} diff --git a/developer/Erebus/transform_frame_stream.c b/developer/Erebus/transform_frame_stream.c new file mode 100644 index 0000000..15ebf5f --- /dev/null +++ b/developer/Erebus/transform_frame_stream.c @@ -0,0 +1,369 @@ +// +// gcc -I/usr/include/libdrm drm_info.c -o transform_frame_stream -ldrm +// ./transform_frame_stream + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -------------------------------------------------------------------------------- +// Pixel + +// These pixels have hardware support ,and thus must be packed in the order +// expected by the hardware. +// 0xAARRGGBB +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + }; + } PixelRGBA; +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t alpha; + uint8_t red; + uint8_t green; + uint8_t blue; + }; + } PixelRGBA; +#else + #warning "Unknown __BYTE_ORDER__ found when packing a PixelRGBA." +#endif + +const PixelRGBA black = {.aggregate = 0xff000000}; +const PixelRGBA white = {.aggregate = 0xffffffff}; + +PixelRGBA·structure + ( + PixelRGBA *to_px + ,uint8_t red + ,uint8_t green + ,uint8_t blue + ,uint8_t alpha + ){ + px->blue = blue; + px->green = green; + px->red = red; + px->alpha = alpha; +} +PixelRGBA·destructure + ( + PixelRGBA *from_px + ,uint8_t *red + ,uint8_t *green + ,uint8_t *blue + ,uint8_t *alpha + ){ + *blue = from_px->blue; + *green = from_px->green; + *red = from_px->red; + *alpha = from_px->alpha; +} + + +// -------------------------------------------------------------------------------- +// Frame + +typedef struct __attribute__((packed)){ + uint32_t width; + uint32_t height; + PixelRGBA data[]; +} FrameRGBA; + +FrameRGBA·alloc(int width ,int height){ + bool null_frame = false; + + if( width == 0 ){ + fprintf(stderr, "FrameRGBA·alloc:: frame width of zero, so returning a null frame pointer\n"); + null_frame = true; + } + if( height == 0 ){ + fprintf(stderr, "FrameRGBA·alloc:: frame height of zero, so returning a null frame pointer\n"); + null_frame = true; + } + if(null_frame) return NULL; + + FrameRGBA *frame = malloc(sizeof(FrameRGBA)); + if(!frame){ + fprintf(stderr ,"FrameRGBA·alloc::failed to allocate frame\n"); + null_frame = true; + } + frame->data = malloc( width * height * sizeof(int) ); + if(!frame->data){ + fprintf(stderr ,"FrameRGBA·alloc::failed to allocate frame data\n"); + null_frame = true; + } + if(null_frame) return NULL; + + frame->width = width; + frame->height = height; + return frame; +} +FrameRGBA·alloc_same(Frame_data *frame){ + if(!frame) return NULL; + return alloc(frame->width ,frame->height); +} +FrameRGBA·dealloc(FrameRGBA *frame){ + free(frame); +} + +FrameRGBA·dimensions(FrameRGBA *frame ,uint32_t *width ,uint32_t *height){ + if(!frame){ + *width = 0; + *height = 0; + return; + } + *width = frame->width; + *height = frame->height; +} + +// both frames have already been allocated +FrameRGBA·copy(FrameRGBA *from_frame ,FrameRGBA **to_frame_arg){ + if(to_frame_arg == NULL) return; + if(*to_frame_arg == NULL) return; + if( from_frame == NULL ){ + *to_frame = NULL; + return; + } + FrameRGBA *to_frame = *to_frame_arg; + + int32_t width, height; + FrameRGBA·dimensions(from_frame ,&width ,&height); + if(**to_frame.width < width){ + width = to_frame.width; + fprintf(stderr ,"FrameRGBA·copy:: from_frame is wider than to_frame ,there will be truncation\n"); + }else if(to_frame.width > width){ + fprintf(stderr ,"FrameRGBA·copy:: to_frame is wider, so stale uninitialized pixels will remain at the end of scan lines.\n"); + } + if(to_frame.height < height){ + height = to_frame.height; + fprintf(stderr ,"FrameRGBA·copy:: from_frame is taller than to_frame ,there will be truncation\n"); + }else if(to_frame.height > height){ + fprintf(stderr ,"FrameRGBA·copy:: to_frame is taller, so stale or uninitialized scan lines will remain at the bottom of the frame.\n"); + } + + int32_t j = 0; + int32_t offset = 0; + do{ + memcpy( + from_frame->data + offset + ,to_frame-data + ,width * sizeof(PixelRGBA) + ); + offset += width; + j++; + }while(j <= height); +} +// if i and j walk out of frame returns NULL +PixelRGB *FrameRGBA·access(FrameRGBA *from_frame ,uint32_t i ,uint32_t j){ + int32_t width, height; + FrameRGBA·dimensions(from_frame ,&width ,&height); + if(i > width) return NULL; + if(j > height) return NULL; + uint32_t line_size = from_frame->width * sizeof(PixelRGB); + return from_frame->data + j*line_size + i*sizeof(PixelRGB); +} +PixelRGB FrameRGBA·read(FrameRGBA *from_frame ,uint32_t i ,uint32_t j){ + return *FrameRGBA·access(FrameRGBA *from_frame ,uint32_t i ,uint32_t j); +} +void FrameRGBA·write(FrameRGBA *to_frame ,uint32_t i ,uint32_t j ,PixelRGBA px){ + *FrameRGBA·access(FrameRGBA *from_frame ,uint32_t i ,uint32_t j) = px; +} + +// search frame for condition where f returns a non-null pointer +// f is handed successive pointers to pixels in the frame. +// f is given the frame in case it needs context. +// f is given an argument is it is difficult to curry functions in C. +void *FrameRGBA·exist +( + FrameRGBA *frame + ,void *f(FrameRGBA *frame ,PixelRGBA *px ,void *arg) + ,void *arg + ){ + + if(!frame) return NULL; + + void *item; + int32_t width, height; + FrameRGBA·dimensions(frame ,&width ,&height); + int32_t i = 0; + int32_t j = 0; + do{ + PixelRGBA *px = FrameRGBA·access(frame ,i ,j); + if( item=f(frame ,px ,arg) ) return item; + + if(i == width){ + i = 0; + j++; + }else{ + i++; + } + }while(j <= height); + return NULL; +} + +typedef struct{ + void f(FrameRGBA *frame ,PixelRGBA *px ,void *arg) f; + void *arg; +} every_arg_t; +void *(*every_f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg0){ + every_arg_t *ea = arg0; + ea->f(frame ,px ,ea->arg); + return NULL; +} +void *FrameRGBA·every +( + FrameRGBA *frame + ,void *f(FrameRGBA *frame ,PixelRGBA *px ,void *arg) + ,void *arg + ){ + ever_arg_t ea = {.f = f ,.arg = arg}; + FrameRGBA·exist(to_frame ,ever_f ,&ea); +} + +void (*fill_f)(FrameRGBA *to_frame ,PixelRGBA *to_px ,void *arg){ + PixelRGBA *px = arg; + *to_px = *px; + return NULL; +} +FrameRGBA·fill(Frame_data *to_frame ,PixelRGB *fill_px){ + FrameRGBA·every(to_frame ,fill_f ,fill_px); +} +FrameRGBA·fill_black(Frame_data *to_frame){ + FrameRGBA·fill(to_frame ,&black); +} +FrameRGBA·fill_white(Frame_data *to_frame){ + FrameRGBA·fill(to_frame ,&black); +} + +// -------------------------------------------------------------------------------- +// Transform functions +// Given the previous frame, current frame, and an argument; modifies the +// current frame. + +int identity_transform(FrameRGBA *prev_frame ,FrameRGBA *curr_frame ,void *args){ + // no processing in the identity transform + copy_FrameRGBA(curr_frame ,prev_frame); + return 0; // Success +} + +// -------------------------------------------------------------------------------- +// transform frame stream + +int transform_frame_stream(int (*transform)(FrameRGBA * ,FrameRGBA * ,void *) ,void *transform_args){ + // Simulated screen info (would be fetched from the actual DRM system) + FrameRGBA *prev_frame = Framedata·alloc(3840 ,2400); + FrameRGBA *curr_frame = Framedata·alloc_same(prev_frame); + + // Fornow ,we'll simulate grabbing the first frame by filling it with random values. + // In the real implementation ,you will fetch the current frame data from the DRM API. + for(int i = 0; i < width * height; i++){ + curr_frame.data[i] = rand(); // Simulate grabbing a frame with random pixel data + } + + // Call the transform function forthe first frame (identity in this case) + transform(&prev_frame ,&curr_frame ,transform_args); + + // Main processing loop (simplified to one iteration fornow) + while (1){ + // Simulate grabbing the next frame (we just reuse the current one forthis example) + // In real code ,you would fetch the next frame from the DRM system here. + + // Call the transform function foreach new frame + transform(&prev_frame ,&curr_frame ,transform_args); + + // Copy current frame to previous frame (fornext iteration) + memcpy(prev_frame.data ,curr_frame.data ,width * height * sizeof(unsigned int)); + + break; // Exit after one loop forthis example (replace with continuous loop in real implementation) + } + + // Clean up memory + free(prev_frame.data); + free(curr_frame.data); + + return 0; // Success +} + +int main(int argc ,char **argv){ + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2" ,O_RDWR | O_CLOEXEC); + if(fd < 0){ + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if(!resources){ + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for(int i = 0; i < resources->count_connectors; i++){ + connector = drmModeGetConnector(fd ,resources->connectors[i]); + if(connector->connection == DRM_MODE_CONNECTED){ + break; + } + drmModeFreeConnector(connector); + } + + if(!connector || connector->connection != DRM_MODE_CONNECTED){ + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd ,connector->encoder_id); + if(!encoder){ + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd ,encoder->crtc_id); + if(!crtc){ + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Call transform_frame_stream with identity transform + transform_frame_stream(identity_transform ,NULL); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return 0; +} diff --git a/developer/Erebus/transform_frame_stream.c~ b/developer/Erebus/transform_frame_stream.c~ new file mode 100644 index 0000000..f45ce5d --- /dev/null +++ b/developer/Erebus/transform_frame_stream.c~ @@ -0,0 +1,89 @@ +// gcc -I/usr/include/libdrm drm_info.c -o drm_info -ldrm +// ./drm_info + + + +#include +#include +#include +#include +#include + + +int transform_frame_stream(){ + printf("Framebuffer ID: %d\n", crtc->buffer_id); + printf("Resolution: %dx%d\n", crtc->width, crtc->height); +} + +// no argument parsing for this first version. +int main(int argc ,char **arc ,char **envp){ + + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2", O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if (!resources) { + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for (int i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector->connection == DRM_MODE_CONNECTED) { + break; + } + drmModeFreeConnector(connector); + } + + if (!connector || connector->connection != DRM_MODE_CONNECTED) { + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd, connector->encoder_id); + if (!encoder) { + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd, encoder->crtc_id); + if (!crtc) { + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + int error; + error = transform_frame_stream(crtc->buffer); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return error; +} diff --git a/developer/Erebus/transform_frames.c b/developer/Erebus/transform_frames.c new file mode 100644 index 0000000..f45ce5d --- /dev/null +++ b/developer/Erebus/transform_frames.c @@ -0,0 +1,89 @@ +// gcc -I/usr/include/libdrm drm_info.c -o drm_info -ldrm +// ./drm_info + + + +#include +#include +#include +#include +#include + + +int transform_frame_stream(){ + printf("Framebuffer ID: %d\n", crtc->buffer_id); + printf("Resolution: %dx%d\n", crtc->width, crtc->height); +} + +// no argument parsing for this first version. +int main(int argc ,char **arc ,char **envp){ + + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2", O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if (!resources) { + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for (int i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector->connection == DRM_MODE_CONNECTED) { + break; + } + drmModeFreeConnector(connector); + } + + if (!connector || connector->connection != DRM_MODE_CONNECTED) { + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd, connector->encoder_id); + if (!encoder) { + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd, encoder->crtc_id); + if (!crtc) { + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + int error; + error = transform_frame_stream(crtc->buffer); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return error; +} diff --git a/developer/Erebus/transform_frames.c~ b/developer/Erebus/transform_frames.c~ new file mode 100644 index 0000000..dad6da8 --- /dev/null +++ b/developer/Erebus/transform_frames.c~ @@ -0,0 +1,81 @@ +// gcc -I/usr/include/libdrm drm_info.c -o drm_info -ldrm +// ./drm_info + + + +#include +#include +#include +#include +#include + +int main() { + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2", O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if (!resources) { + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for (int i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector->connection == DRM_MODE_CONNECTED) { + break; + } + drmModeFreeConnector(connector); + } + + if (!connector || connector->connection != DRM_MODE_CONNECTED) { + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd, connector->encoder_id); + if (!encoder) { + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd, encoder->crtc_id); + if (!crtc) { + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + printf("Framebuffer ID: %d\n", crtc->buffer_id); + printf("Resolution: %dx%d\n", crtc->width, crtc->height); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return 0; +} diff --git a/developer/cc/drm_info b/developer/cc/drm_info new file mode 100755 index 0000000000000000000000000000000000000000..3722f7c04aa12079c163deeb07b079ff8ecc6049 GIT binary patch literal 17272 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 l>o-2Xesi{MhlzW}aHv|IoH literal 0 HcmV?d00001 diff --git a/developer/cc/drm_info.c b/developer/cc/drm_info.c new file mode 100644 index 0000000..dad6da8 --- /dev/null +++ b/developer/cc/drm_info.c @@ -0,0 +1,81 @@ +// gcc -I/usr/include/libdrm drm_info.c -o drm_info -ldrm +// ./drm_info + + + +#include +#include +#include +#include +#include + +int main() { + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2", O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if (!resources) { + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for (int i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector->connection == DRM_MODE_CONNECTED) { + break; + } + drmModeFreeConnector(connector); + } + + if (!connector || connector->connection != DRM_MODE_CONNECTED) { + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd, connector->encoder_id); + if (!encoder) { + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd, encoder->crtc_id); + if (!crtc) { + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + printf("Framebuffer ID: %d\n", crtc->buffer_id); + printf("Resolution: %dx%d\n", crtc->width, crtc->height); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return 0; +} diff --git a/developer/cc/modified_transform_frame_stream.c b/developer/cc/modified_transform_frame_stream.c new file mode 100644 index 0000000..7e1a824 --- /dev/null +++ b/developer/cc/modified_transform_frame_stream.c @@ -0,0 +1,136 @@ + +// gcc -I/usr/include/libdrm transform_frame_stream.c -o transform_frame_stream -ldrm +// ./transform_frame_stream + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -------------------------------------------------------------------------------- +// Pixel + +#if __BYTE_ORDER == __LITTLE_ENDIAN + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + }; + } PixelRGBA; +#elif __BYTE_ORDER == __BIG_ENDIAN + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t alpha; + uint8_t red; + uint8_t green; + uint8_t blue; + }; + } PixelRGBA; +#else + #warning "Unknown __BYTE_ORDER__ found when packing a PixelRGBA." +#endif + +PixelRGBA black = {.aggregate = 0xff000000}; +PixelRGBA white = {.aggregate = 0xffffffff}; + +void PixelRGBA_structure(PixelRGBA *px, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha){ + px->blue = blue; + px->green = green; + px->red = red; + px->alpha = alpha; +} + +void PixelRGBA_destructure(PixelRGBA *px, uint8_t *red, uint8_t *green, uint8_t *blue, uint8_t *alpha){ + *blue = px->blue; + *green = px->green; + *red = px->red; + *alpha = px->alpha; +} + +PixelRGBA PixelRGBA_random(){ + PixelRGBA px; + px.aggregate = rand(); + return px; +} + +// -------------------------------------------------------------------------------- +// Frame + +typedef struct{ + uint32_t width; + uint32_t height; + PixelRGBA data[]; +} FrameRGBA; + +FrameRGBA *FrameRGBA_alloc(int width ,int height){ + if(width == 0 || height == 0){ + fprintf(stderr, "FrameRGBA_alloc: Invalid frame dimensions\n"); + return NULL; + } + + FrameRGBA *frame = (FrameRGBA *)malloc(sizeof(FrameRGBA) + width * height * sizeof(PixelRGBA)); + if(!frame){ + fprintf(stderr, "Failed to allocate memory for frame\n"); + return NULL; + } + + frame->width = width; + frame->height = height; + + // Initialize frame with random pixels for now (could be replaced with real frame data later) + for(int i = 0; i < width * height; i++){ + frame->data[i] = PixelRGBA_random(); + } + + return frame; +} + +void FrameRGBA_free(FrameRGBA *frame){ + if(frame){ + free(frame); + } +} + +// -------------------------------------------------------------------------------- +// Identity Transform + +void apply_identity_transform(FrameRGBA *frame){ + // This is an identity transform, so nothing is changed in the frame + printf("Applying identity transform to frame\n"); + // Normally, transformations would modify the frame data here +} + +// -------------------------------------------------------------------------------- +// Main function to grab frames and apply identity transform + +int main(){ + // Simulating grabbing a frame with fixed dimensions for now + int width = 640; + int height = 480; + + FrameRGBA *frame = FrameRGBA_alloc(width, height); + if(!frame){ + return EXIT_FAILURE; + } + + // Apply identity transform (does nothing) + apply_identity_transform(frame); + + // Simulate some output (e.g., saving frame, displaying, etc.) + printf("Frame processed and passed through identity transform\n"); + + // Clean up + FrameRGBA_free(frame); + + return EXIT_SUCCESS; +} diff --git a/developer/cc/transform_frame_stream b/developer/cc/transform_frame_stream new file mode 100755 index 0000000000000000000000000000000000000000..179a66889d11303253299d4ec918cb88a4ac61de GIT binary patch literal 18512 zcmeHPdvsjId7oX`SOi;Mo0oYMF2;aO?6qW!AEMM(mRDYbWK`KQX$x6ayI0nR)vnmR zi)9igCUR0O!lzC`2`AwXH>Ko-Pl4tD#nhH<4l*2?3IbF#ZYqeOt4JX-5vh_o+5Wzn zZ|>e*Yn>*ir>8wf1G?XQ&-vz?$DN(Ie8@wKm(8(+QNDyYuGbKqqg=p3pP))H$ z%)!$TSBi6h&yX}cBs7cQkXNEY!%BsU3P93ZKp6?mB6zvPgwRlXNRadj$>gkppEy^c z8VaAnNpB`)85cg2FyN*H@0=%r&``@c-K3kjh080~4huN`8gh8W@_4Lm z)yn1Z=(2b$k?CI6y=K+2RV)4Jq<@8Uf&8k*AN8q?n_GoXYy(2%=kU6zzHOWvt$R^29B6)UM;*=*lBqQUa9FQVJ zU;AO79zwv*OizO}|4gztUWWd78TyyY(3h8?*O#HcQ-)5}GVoWL{vCv={6A8LzN-v< zTN(NbW$526L;s)*-6%t+_MOWAyUWm@Ekpko(C3Lu#D3F6P6$1|MJTkrGnojb?QqHt zg+w&f*_4c04Jpg2PuUTTZ?x=EG?_?P5j&aEBBT;XM4((msxOs;sVT%-taLJyidboF z4q^pbSH@0@E-RHnaqTEaq{4})NOoBX(HV}%lMz${12V$Z=nTgaB5lKyl!(NWX-jlk zosq7cqJ2jyW?KTHsHYmNq(-?_Vq@c`_4T0@{+g9e_J%@sh5ts1n-?PtV^#h~a0X*u zzyh6e6@p%ydY*acOAllC%@F4??Ryfh5En6?xip41lUG~?oYK%bQ$iZE?(sbAqC0H} z8Qrcl-_W>r61O+KhS;=ZRl4XrwM)9sMW^{irv)y$d`~jNaM9)b!t}*1I==!Xr`kp5 zSFxn8anV1~sXCBQPC-=?F|m;Qw+2em?h#Uj=){DuaD9U&C5G_=SGkn;#7J zyjXcmx}CrA6_E4Syo%@CD^27G?;zgDa31NJqlDAaV`Na`&lBz?ykFu^6HZHzktZeo z9l~kpF|uFc-yocp93%TA{x!mBsWGx!;$J45mKY;l5`TbjS{jYqCGpP_PD_oEW{KZN zI4v{d2F}0~H}i{#XIs z_uL~`Km>25r+xl&BtcDZ?qMS2huilZYcB{>{0~X_`#+E%J03jp!Mfm)$%>%orQmD7 zvFAA!X0e4*eJX$V%?IF=$eiCA%)Xbq50!dp=GQ^-+8iur?&E1v&h9#q z%?!O1$cvs`Cq!l;`uVr9wGzx8dHxo};1G4(!#=|lxp#k!I0W*Zo?Syq?tYfL)sef4 zpA2kOIPKpfsumJqYK66I)sLY7$ zTPXS?grr0VQsmSPr}O!J%py~|Ii$&pU}Ag#&LL7LRpmx6k%p;>#BK{0nv9Px$xV6cz+_1rxn!exZXz+g~W9@*p)qrmM&zu4O}1`!zhKDoOU zy_5>>^YsPB)*ekSk%-6!AT;xz5l3p#%}zLnDV#o3arEO#u&C; zAO9y8&^!Y*hV1oH5%HuRKGSBc+Z?U^q;&vVqf1$`ua)$uj0ToYJJRDM{W(Yv1Wtn} z1_F}=P?>ChaPI|QAOvQHf_sCN)I!vSJV(fIaBo+Eg8n4K@#e4cdFXlqlRbgc9&$Kv zI`#DEjD4dX-Kafd1{x!m&791(4kMzIi0Ek;#E6q7yyzMjDr*BLQ{01Apy0KEVU1o5 zE;{va_Gn+=q-U_m&s@-hCho5+?pxW+M7DLj5C1n!prlDvPy$WYCmhKIaw3tE*`~2l z;W`p-9n1O()i9ktm2Ew)I?u=CC>hyDLEB5UYdVSYbYEGFVN??4*2z9u`61=f4^j7^ z9HFq-*ECMbjnp3{yACfvJzVW`C}g8c5Q3hZ2T{($N`B`KZMoPKG(`Rp zmC{k0x@eSzK+H#QodN5k){uiAEkSM_dY#R6qb0OC%&t<7_z#+@xPxW*`lCs?Z;!j-_2(xlgYW6%pWXQ9NQ8ZD+<4 zvC9k|x(f@2!vb&h+z)=KyMmgmAB9)4r3!Np49XERNGxhO7~hQAk?V-)AX*WPs=FWc z9u``1R-s~V55o99X%W_Mb(ORZ`QmDr*7*WH5d1_P6Q*b2amjqd25hn=@aq=bowI>CqmL^`g$fkHYP|FLlYKz0u!`W z80<5RwSkGxJcY)UZ#8>1NwLQDhyR9r*+;hIC>_X6Ag}y-9ywK&JRFi*G=;0;Z&r2U zSMRFBN6Ai3*^%w|g3IQ9$7Z`@^SjDs4ue(Oe3?|TfnoSLEHdj3|B!4xr0ifM59Ai8 zytIFZ%40$q$eGA1pU*)~`aHV%5DE~7pF{u7ZKHJp);}a`D?MrN_=KcOd$V2k#z9y1 zo9wQO8pcl23#@KRfAv=hnL z5sTU#MzYj&K4N6nQC7D@8R%o!TtJ zPGu62upLV#VDe0RTFubbWN>ia7PpKH!V|M&;dtymxY!lzw&GMI?4~R_#4^G*6=qn8 zC`BS2fg3n)w$gqM-xTGwr`-OdnE3BffwTLsthp+XOqJB3;Nn#EXiM65vXiPpwUR+b zO_oQkdzVL3vE`9)D!M|{hZBh;S{|o+#)g(A1Ke1|n(AE8P;DzVCyj_YW<(S@2hZA* z8JrUGiDu#0QEL?#bhN3d=>DF|DsCDAycB;+f11x{I#t46hJd0T%(j^C9#Bn|=;`z#V{l0KWzJ z7+?r*>=yyQ0eBMdM}RXb@I3+E?~4GJ0d4?n0*nH70`38P81ON`7Xe=c{1EUY;NN4R zGXuM7`fSj1UyJZ``#hJ;o>jRI{?UdNeF)Hu`d$ktHq7!7tr~xE(Da$#B4XjMax9-W zpeL$)4OI(nnS0)j%H3k!r8ixF!=iyY#{K>QM zXJcHPgK;P~nRNSkk4gj7eoMhW0RAG_aqL%I=~X3Aq0?zP0@D$gj=*#TrX%qGI|9ah zQ&wP{zw5@*L8gxwYFvK`KAY+K`)E2KrS!&Sri7Qsrx5ykX1T@!4NE_nXl+etoWEbD z_bnyO$H7#R@cs&ufciEYaCoLksQQ)_FvooTduSOudY+WR_u~xZ8j|w_@M@PS$KTV@ zE1uFLtgqL}vlLle%&>o!DRY|M&A9eE$Z~YxOi7oIeQ8;rH7t*c!%T_ND#nSk^Q%SEW zkp^Q~%@R?!t#)Ns&59dWigcNK z8&|C`{Ql+Xo$096m0phT#FvNLV$1Lg*YZcimgd?U#FqNn8d2X+yXGu{4UM(cXJK!w zgNf!%wJXJzKy9^%ZNa0+1=?pod9oDFOOu>0lEvPH9g8eWS@^J4`B-g~(4?IbnzUC! zljE6wN7Bcq8|xN%ZV1;ncSqW}ZE5V3%4C?Q;Z!nu?zxEj&{Q&dK03kk(o{0LxvXn> z4xCEnHP+Yg_m$DUUUn9rwXg4RncVlM1T=rl5U1#9qbQMo^mX#16{e&c@~OThpGy7@ z!1szOp<}_~xWS|7PZp0uv4ZLPeWB%p$awIb`L|3{lJxwxRnjkT=6lJ+9j{QAN8WcS4#3XIG~T|bvV$WWXPuw*Gf7gF0i@`{cgOl47^=>InG*T ztCX)2Pn~Z{lHB`1?o(y#e7X$%FUrvWn(YtqSb3WZ{vPN)`14SSKL^X$`99ITbDi}9 zn-OoYeLB#kB!Bw@zRPqyM&+Io=>NfVae)a8=X>%g#2mzj;(zx=rliO{6y&a8I-O!u zx=ucYSdP81dGMc3uPFhQ=^B>*CCe{n`i+v#hzo3F`5^lv_lCf~o$1FoZWpqS0spC7 zIu)m+%Z)*v;#u0h_p+S_I6iXk1A2QwH^@LqdKC0|UZ1Em%p%UWrJW*@L=KWX&BiRR z{dq;oSBW<-RCeT^7Bo(jvGX&~eV7NHG?lzGj>iPad#gkj&nGjPk(73-oOgrVg9MNE zXy$8W7raW+s{|d4Qqpl)2|ATq+7C^ZzlY=BBDK&iW$edUo<7o}B=>*-?_v7G+#lrL z8R(y9`lH<6$h{A@HdjhFX$-q7pyE17;3mus-G8;S14uK=IvHZN|H@fVgCtx_N?GAftfk;A&T^#x4J~y|fly%c2Hd&|ZTOSTbxoVz+xoi3&}|J3TLN1{TkF<0213HR*GlaSwY$%M+Hr0a+R;H5oal~}sqZt<&80K0 zM>$+vadMsc$Rn~)8Wk0E=gN^H8-??d!o{ott#Hq))SL)e(XbuX`tEyTGRQ(YPB*&f z;7T;pDVRE8MA$MB93on77o)LGE0M-&TiQ)k7rUgTGlHV-fECrnOz^jAeXa{DY`ocm2@(Mqrzxh-#Bv$#ig>)rrTgH8cT#SX)Efs8IIuMTbi%3IV!T< z&|5?(8V||EILJCdnF zL&|G(u1Lu~=l0v`#$c1z@QR#P7xjurE-M%bQQTPs4 z(PcDh$)4*b$%bl+ha-0jIY8b0j}H7aUN{((w+f32S9b`DNW!1q*=dK{0PU259Xclu zw!4I1{3haW-&jBcZAa&!XMq4KoJVsDaFBP zr!HTFgup|$2$KTmy5hF*(`+RCw$+U%O=93B!m{e1Q*C5T{bAcq#o979X5#;eMDHamnVhc@7F3wh ztp0Zb^gfa#;z6?RbTts#yTNiprZudu@5P%;*Pv2o7_I_z>+5^)`hNVP5_!DFiqa-v zZhigx>`}azDH-xvc$Dhj4i=7bX}Kg*Kl|U$`nr6&AVI0r|1fB@H>UOV{#lOoCq1O4 ze59<_*ZWv8&`4D4>;1T4UdZYFH;Bl@<}@nqL5}vmw7%Z&s-mDE>Gh8GU(0FuS;){{ zn#T2h+8Wk3$p{jmZvQ0_kG=S#m}-5!f7i|WK^D~Im)8HQtiPV+^nPGJ>p#L3CjE=? zSE~P4ppl5S@2sD&YdtboqLpLjQXp!&EsW?v9Q<-To8ck%-pU_soZu zlNSAUDo(mw4Sxx?TVL;cf*7ri$t*?LI_EsxJ=Ujp9l=dImS0P*4|NW*Z zB_Cq_QvVIfEj;FM`7G`*wEi6qMP?_kB$x*n5M*D%toIKw UJNQjDwf?+yO8=%3g%VW!7o%<|PXGV_ literal 0 HcmV?d00001 diff --git a/developer/cc/transform_frame_stream.c b/developer/cc/transform_frame_stream.c new file mode 100644 index 0000000..322caf6 --- /dev/null +++ b/developer/cc/transform_frame_stream.c @@ -0,0 +1,386 @@ +// +// gcc -I/usr/include/libdrm transform_frame_stream.c -o transform_frame_stream -ldrm +// ./transform_frame_stream + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -------------------------------------------------------------------------------- +// Pixel + +// These pixels have hardware support ,and thus must be packed in the order +// expected by the hardware. +// 0xAARRGGBB +#if __BYTE_ORDER == __LITTLE_ENDIAN + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + }; + } PixelRGBA; +#elif __BYTE_ORDER == __BIG_ENDIAN + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t alpha; + uint8_t red; + uint8_t green; + uint8_t blue; + }; + } PixelRGBA; +#else + #warning "Unknown __BYTE_ORDER__ found when packing a PixelRGBA." +#endif + +PixelRGBA black = {.aggregate = 0xff000000}; +PixelRGBA white = {.aggregate = 0xffffffff}; + +void PixelRGBA·structure + ( + PixelRGBA *px + ,uint8_t red + ,uint8_t green + ,uint8_t blue + ,uint8_t alpha + ){ + px->blue = blue; + px->green = green; + px->red = red; + px->alpha = alpha; +} +void PixelRGBA·destructure + ( + PixelRGBA *px + ,uint8_t *red + ,uint8_t *green + ,uint8_t *blue + ,uint8_t *alpha + ){ + *blue = px->blue; + *green = px->green; + *red = px->red; + *alpha = px->alpha; +} + +PixelRGBA PixelRGBA·random(){ + PixelRGBA px; + px.aggregate = rand(); + return px; +} + + + +// -------------------------------------------------------------------------------- +// Frame + +typedef struct{ + uint32_t width; + uint32_t height; + PixelRGBA data[]; +} FrameRGBA; + +FrameRGBA *FrameRGBA·alloc(int width ,int height){ + bool null_frame = false; + + if( width == 0 ){ + fprintf(stderr ,"FrameRGBA·alloc:: frame width of zero, so returning a null frame pointer\n"); + null_frame = true; + } + if( height == 0 ){ + fprintf(stderr ,"FrameRGBA·alloc:: frame height of zero, so returning a null frame pointer\n"); + null_frame = true; + } + if(null_frame) return NULL; + + size_t size = sizeof(FrameRGBA) + width * height * sizeof(PixelRGBA); + FrameRGBA *frame = malloc(size); + if(!frame){ + fprintf(stderr ,"FrameRGBA·alloc::failed to allocate frame\n"); + return NULL; + } + + frame->width = width; + frame->height = height; + return frame; +} + +FrameRGBA *FrameRGBA·alloc_same(FrameRGBA *frame){ + if(!frame) return NULL; + return FrameRGBA·alloc(frame->width ,frame->height); +} + +void FrameRGBA·dealloc(FrameRGBA *frame){ + free(frame); +} + +void FrameRGBA·dimensions(FrameRGBA *frame ,uint32_t *width ,uint32_t *height){ + if(!frame){ + *width = 0; + *height = 0; + return; + } + *width = frame->width; + *height = frame->height; +} + +// both frames have already been allocated +void FrameRGBA·copy(FrameRGBA *from_frame ,FrameRGBA **to_frame_arg){ + if( to_frame_arg == NULL ) return; + if(*to_frame_arg == NULL) return; + if( from_frame == NULL ){ + *to_frame_arg = NULL; + return; + } + FrameRGBA *to_frame = *to_frame_arg; + + uint32_t width ,height; + FrameRGBA·dimensions(from_frame ,&width ,&height); + if(to_frame->width < width){ + width = to_frame->width; + fprintf(stderr ,"FrameRGBA·copy:: from_frame is wider than to_frame, there will be truncation\n"); + }else if(to_frame->width > width){ + fprintf(stderr ,"FrameRGBA·copy:: to_frame is wider, so stale uninitialized pixels will remain at the end of scan lines.\n"); + } + if(to_frame->height < height){ + height = to_frame->height; + fprintf(stderr ,"FrameRGBA·copy:: from_frame is taller than to_frame, there will be truncation\n"); + }else if(to_frame->height > height){ + fprintf(stderr ,"FrameRGBA·copy:: to_frame is taller, so stale or uninitialized scan lines will remain at the bottom of the frame.\n"); + } + + uint32_t j = 0; + uint32_t offset = 0; + do{ + memcpy( + to_frame->data + offset, + from_frame->data + offset, + width * sizeof(PixelRGBA) + ); + offset += width; + j++; + }while(j < height); +} + +// if i and j walk out of frame returns NULL +PixelRGBA *FrameRGBA·access(FrameRGBA *from_frame ,uint32_t i ,uint32_t j){ + uint32_t width ,height; + FrameRGBA·dimensions(from_frame ,&width ,&height); + if(i >= width) return NULL; + if(j >= height) return NULL; + return &(from_frame->data[j * width + i]); +} + +PixelRGBA FrameRGBA·read(FrameRGBA *from_frame ,uint32_t i ,uint32_t j){ + return *FrameRGBA·access(from_frame ,i ,j); +} + +void FrameRGBA·write(FrameRGBA *to_frame ,uint32_t i ,uint32_t j ,PixelRGBA px){ + *FrameRGBA·access(to_frame ,i ,j) = px; +} + +// search frame for condition where f returns a non-null pointer +// f is handed successive pointers to pixels in the frame. +// f is given the frame in case it needs context. +// f is given an argument is it is difficult to curry functions in C. +void *FrameRGBA·exist +( + FrameRGBA *frame + ,void *(*f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg) + ,void *arg + ){ + + if(!frame) return NULL; + + void *item; + uint32_t width ,height; + FrameRGBA·dimensions(frame ,&width ,&height); + uint32_t i = 0; + uint32_t j = 0; + do{ + PixelRGBA *px = FrameRGBA·access(frame ,i ,j); + if( item=f(frame ,px ,arg) ) return item; + + if( i == width - 1 ){ + i = 0; + j++; + }else{ + i++; + } + }while(j < height); + return NULL; +} + +typedef struct{ + void (*f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg); + void *arg; +} every_arg_t; + +void *every_f(FrameRGBA *frame ,PixelRGBA *px ,void *arg0){ + every_arg_t *ea = arg0; + ea->f(frame ,px ,ea->arg); + return NULL; +} +void FrameRGBA·every +( + FrameRGBA *frame + ,void (*f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg) + ,void *arg + ){ + every_arg_t ea = {.f = f ,.arg = arg}; + FrameRGBA·exist(frame ,every_f ,&ea); +} + +void fill_f(FrameRGBA *to_frame ,PixelRGBA *to_px ,void *arg){ + PixelRGBA *px = arg; + *to_px = *px; +} +void FrameRGBA·fill(FrameRGBA *to_frame ,PixelRGBA *fill_px){ + FrameRGBA·every(to_frame ,fill_f ,fill_px); +} + +void FrameRGBA·fill_black(FrameRGBA *to_frame){ + FrameRGBA·fill(to_frame ,&black); +} + +void FrameRGBA·fill_white(FrameRGBA *to_frame){ + FrameRGBA·fill(to_frame ,&white); +} + +void fill_random_f(FrameRGBA *frame ,PixelRGBA *px ,void *arg){ + *px = PixelRGBA·random(); +} +void FrameRGBA·fill_random(FrameRGBA *frame){ + if(!frame) return; + FrameRGBA·every(frame ,fill_random_f ,NULL); +} + + +// -------------------------------------------------------------------------------- +// Transform functions +// Given the previous frame ,current frame ,and an argument; modifies the +// current frame. + +int identity_transform(FrameRGBA *prev_frame ,FrameRGBA *curr_frame ,void *args){ + // no processing in the identity transform + FrameRGBA·copy(prev_frame ,&curr_frame); + return 0; // Success +} + +// -------------------------------------------------------------------------------- +// transform frame stream + +int transform_frame_stream(int (*transform)(FrameRGBA * ,FrameRGBA * ,void *) ,void *transform_args){ + // Simulated screen info (would be fetched from the actual DRM system) + FrameRGBA *prev_frame = FrameRGBA·alloc(3840 ,2400); + FrameRGBA *curr_frame = FrameRGBA·alloc_same(prev_frame); + + // For now ,we'll simulate grabbing the first frame by filling it with random values. + // In the real implementation ,you will fetch the current frame data from the DRM API. + uint32_t width ,height; + FrameRGBA·dimensions(curr_frame ,&width ,&height); + FrameRGBA·fill_random(curr_frame); + + // Call the transform function for the first frame (identity in this case) + transform(prev_frame ,curr_frame ,transform_args); + + // Main processing loop (simplified to one iteration for now) + while(1){ + // Simulate grabbing the next frame (we just reuse the current one for this example) + // In real code ,you would fetch the next frame from the DRM system here. + FrameRGBA·fill_random(curr_frame); + + // Call the transform function for each new frame + transform(prev_frame ,curr_frame ,transform_args); + FrameRGBA·copy(curr_frame ,&prev_frame); + + break; // Exit after one loop for this example (replace with continuous loop in real implementation) + } + + // Clean up memory + FrameRGBA·dealloc(prev_frame); + FrameRGBA·dealloc(curr_frame); + + return 0; // Success +} + +int main(int argc ,char **argv){ + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2",O_RDWR | O_CLOEXEC); + if(fd < 0){ + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if(!resources){ + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for(int i = 0; i < resources->count_connectors; i++){ + connector = drmModeGetConnector(fd ,resources->connectors[i]); + if(connector->connection == DRM_MODE_CONNECTED){ + break; + } + drmModeFreeConnector(connector); + } + + if(!connector || connector->connection != DRM_MODE_CONNECTED){ + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd ,connector->encoder_id); + if(!encoder){ + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd ,encoder->crtc_id); + if(!crtc){ + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Call transform_frame_stream with identity transform + transform_frame_stream(identity_transform ,NULL); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return 0; +} diff --git a/developer/cc/transform_frame_stream_2.c b/developer/cc/transform_frame_stream_2.c new file mode 100644 index 0000000..322caf6 --- /dev/null +++ b/developer/cc/transform_frame_stream_2.c @@ -0,0 +1,386 @@ +// +// gcc -I/usr/include/libdrm transform_frame_stream.c -o transform_frame_stream -ldrm +// ./transform_frame_stream + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -------------------------------------------------------------------------------- +// Pixel + +// These pixels have hardware support ,and thus must be packed in the order +// expected by the hardware. +// 0xAARRGGBB +#if __BYTE_ORDER == __LITTLE_ENDIAN + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + }; + } PixelRGBA; +#elif __BYTE_ORDER == __BIG_ENDIAN + typedef union{ + uint32_t aggregate; + struct __attribute__((packed)) { + uint8_t alpha; + uint8_t red; + uint8_t green; + uint8_t blue; + }; + } PixelRGBA; +#else + #warning "Unknown __BYTE_ORDER__ found when packing a PixelRGBA." +#endif + +PixelRGBA black = {.aggregate = 0xff000000}; +PixelRGBA white = {.aggregate = 0xffffffff}; + +void PixelRGBA·structure + ( + PixelRGBA *px + ,uint8_t red + ,uint8_t green + ,uint8_t blue + ,uint8_t alpha + ){ + px->blue = blue; + px->green = green; + px->red = red; + px->alpha = alpha; +} +void PixelRGBA·destructure + ( + PixelRGBA *px + ,uint8_t *red + ,uint8_t *green + ,uint8_t *blue + ,uint8_t *alpha + ){ + *blue = px->blue; + *green = px->green; + *red = px->red; + *alpha = px->alpha; +} + +PixelRGBA PixelRGBA·random(){ + PixelRGBA px; + px.aggregate = rand(); + return px; +} + + + +// -------------------------------------------------------------------------------- +// Frame + +typedef struct{ + uint32_t width; + uint32_t height; + PixelRGBA data[]; +} FrameRGBA; + +FrameRGBA *FrameRGBA·alloc(int width ,int height){ + bool null_frame = false; + + if( width == 0 ){ + fprintf(stderr ,"FrameRGBA·alloc:: frame width of zero, so returning a null frame pointer\n"); + null_frame = true; + } + if( height == 0 ){ + fprintf(stderr ,"FrameRGBA·alloc:: frame height of zero, so returning a null frame pointer\n"); + null_frame = true; + } + if(null_frame) return NULL; + + size_t size = sizeof(FrameRGBA) + width * height * sizeof(PixelRGBA); + FrameRGBA *frame = malloc(size); + if(!frame){ + fprintf(stderr ,"FrameRGBA·alloc::failed to allocate frame\n"); + return NULL; + } + + frame->width = width; + frame->height = height; + return frame; +} + +FrameRGBA *FrameRGBA·alloc_same(FrameRGBA *frame){ + if(!frame) return NULL; + return FrameRGBA·alloc(frame->width ,frame->height); +} + +void FrameRGBA·dealloc(FrameRGBA *frame){ + free(frame); +} + +void FrameRGBA·dimensions(FrameRGBA *frame ,uint32_t *width ,uint32_t *height){ + if(!frame){ + *width = 0; + *height = 0; + return; + } + *width = frame->width; + *height = frame->height; +} + +// both frames have already been allocated +void FrameRGBA·copy(FrameRGBA *from_frame ,FrameRGBA **to_frame_arg){ + if( to_frame_arg == NULL ) return; + if(*to_frame_arg == NULL) return; + if( from_frame == NULL ){ + *to_frame_arg = NULL; + return; + } + FrameRGBA *to_frame = *to_frame_arg; + + uint32_t width ,height; + FrameRGBA·dimensions(from_frame ,&width ,&height); + if(to_frame->width < width){ + width = to_frame->width; + fprintf(stderr ,"FrameRGBA·copy:: from_frame is wider than to_frame, there will be truncation\n"); + }else if(to_frame->width > width){ + fprintf(stderr ,"FrameRGBA·copy:: to_frame is wider, so stale uninitialized pixels will remain at the end of scan lines.\n"); + } + if(to_frame->height < height){ + height = to_frame->height; + fprintf(stderr ,"FrameRGBA·copy:: from_frame is taller than to_frame, there will be truncation\n"); + }else if(to_frame->height > height){ + fprintf(stderr ,"FrameRGBA·copy:: to_frame is taller, so stale or uninitialized scan lines will remain at the bottom of the frame.\n"); + } + + uint32_t j = 0; + uint32_t offset = 0; + do{ + memcpy( + to_frame->data + offset, + from_frame->data + offset, + width * sizeof(PixelRGBA) + ); + offset += width; + j++; + }while(j < height); +} + +// if i and j walk out of frame returns NULL +PixelRGBA *FrameRGBA·access(FrameRGBA *from_frame ,uint32_t i ,uint32_t j){ + uint32_t width ,height; + FrameRGBA·dimensions(from_frame ,&width ,&height); + if(i >= width) return NULL; + if(j >= height) return NULL; + return &(from_frame->data[j * width + i]); +} + +PixelRGBA FrameRGBA·read(FrameRGBA *from_frame ,uint32_t i ,uint32_t j){ + return *FrameRGBA·access(from_frame ,i ,j); +} + +void FrameRGBA·write(FrameRGBA *to_frame ,uint32_t i ,uint32_t j ,PixelRGBA px){ + *FrameRGBA·access(to_frame ,i ,j) = px; +} + +// search frame for condition where f returns a non-null pointer +// f is handed successive pointers to pixels in the frame. +// f is given the frame in case it needs context. +// f is given an argument is it is difficult to curry functions in C. +void *FrameRGBA·exist +( + FrameRGBA *frame + ,void *(*f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg) + ,void *arg + ){ + + if(!frame) return NULL; + + void *item; + uint32_t width ,height; + FrameRGBA·dimensions(frame ,&width ,&height); + uint32_t i = 0; + uint32_t j = 0; + do{ + PixelRGBA *px = FrameRGBA·access(frame ,i ,j); + if( item=f(frame ,px ,arg) ) return item; + + if( i == width - 1 ){ + i = 0; + j++; + }else{ + i++; + } + }while(j < height); + return NULL; +} + +typedef struct{ + void (*f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg); + void *arg; +} every_arg_t; + +void *every_f(FrameRGBA *frame ,PixelRGBA *px ,void *arg0){ + every_arg_t *ea = arg0; + ea->f(frame ,px ,ea->arg); + return NULL; +} +void FrameRGBA·every +( + FrameRGBA *frame + ,void (*f)(FrameRGBA *frame ,PixelRGBA *px ,void *arg) + ,void *arg + ){ + every_arg_t ea = {.f = f ,.arg = arg}; + FrameRGBA·exist(frame ,every_f ,&ea); +} + +void fill_f(FrameRGBA *to_frame ,PixelRGBA *to_px ,void *arg){ + PixelRGBA *px = arg; + *to_px = *px; +} +void FrameRGBA·fill(FrameRGBA *to_frame ,PixelRGBA *fill_px){ + FrameRGBA·every(to_frame ,fill_f ,fill_px); +} + +void FrameRGBA·fill_black(FrameRGBA *to_frame){ + FrameRGBA·fill(to_frame ,&black); +} + +void FrameRGBA·fill_white(FrameRGBA *to_frame){ + FrameRGBA·fill(to_frame ,&white); +} + +void fill_random_f(FrameRGBA *frame ,PixelRGBA *px ,void *arg){ + *px = PixelRGBA·random(); +} +void FrameRGBA·fill_random(FrameRGBA *frame){ + if(!frame) return; + FrameRGBA·every(frame ,fill_random_f ,NULL); +} + + +// -------------------------------------------------------------------------------- +// Transform functions +// Given the previous frame ,current frame ,and an argument; modifies the +// current frame. + +int identity_transform(FrameRGBA *prev_frame ,FrameRGBA *curr_frame ,void *args){ + // no processing in the identity transform + FrameRGBA·copy(prev_frame ,&curr_frame); + return 0; // Success +} + +// -------------------------------------------------------------------------------- +// transform frame stream + +int transform_frame_stream(int (*transform)(FrameRGBA * ,FrameRGBA * ,void *) ,void *transform_args){ + // Simulated screen info (would be fetched from the actual DRM system) + FrameRGBA *prev_frame = FrameRGBA·alloc(3840 ,2400); + FrameRGBA *curr_frame = FrameRGBA·alloc_same(prev_frame); + + // For now ,we'll simulate grabbing the first frame by filling it with random values. + // In the real implementation ,you will fetch the current frame data from the DRM API. + uint32_t width ,height; + FrameRGBA·dimensions(curr_frame ,&width ,&height); + FrameRGBA·fill_random(curr_frame); + + // Call the transform function for the first frame (identity in this case) + transform(prev_frame ,curr_frame ,transform_args); + + // Main processing loop (simplified to one iteration for now) + while(1){ + // Simulate grabbing the next frame (we just reuse the current one for this example) + // In real code ,you would fetch the next frame from the DRM system here. + FrameRGBA·fill_random(curr_frame); + + // Call the transform function for each new frame + transform(prev_frame ,curr_frame ,transform_args); + FrameRGBA·copy(curr_frame ,&prev_frame); + + break; // Exit after one loop for this example (replace with continuous loop in real implementation) + } + + // Clean up memory + FrameRGBA·dealloc(prev_frame); + FrameRGBA·dealloc(curr_frame); + + return 0; // Success +} + +int main(int argc ,char **argv){ + int fd; + drmModeRes *resources; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + drmModeCrtc *crtc = NULL; + + // Open the DRM device + fd = open("/dev/dri/card2",O_RDWR | O_CLOEXEC); + if(fd < 0){ + perror("Cannot open DRM device"); + return -1; + } + + // Get resources + resources = drmModeGetResources(fd); + if(!resources){ + perror("drmModeGetResources failed"); + close(fd); + return -1; + } + + // Find a connected connector + for(int i = 0; i < resources->count_connectors; i++){ + connector = drmModeGetConnector(fd ,resources->connectors[i]); + if(connector->connection == DRM_MODE_CONNECTED){ + break; + } + drmModeFreeConnector(connector); + } + + if(!connector || connector->connection != DRM_MODE_CONNECTED){ + printf("No connected connector found\n"); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Get encoder and CRTC + encoder = drmModeGetEncoder(fd ,connector->encoder_id); + if(!encoder){ + perror("drmModeGetEncoder failed"); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + crtc = drmModeGetCrtc(fd ,encoder->crtc_id); + if(!crtc){ + perror("drmModeGetCrtc failed"); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + return -1; + } + + // Call transform_frame_stream with identity transform + transform_frame_stream(identity_transform ,NULL); + + // Clean up + drmModeFreeCrtc(crtc); + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + drmModeFreeResources(resources); + close(fd); + + return 0; +} diff --git a/developer/developer b/developer/developer new file mode 100644 index 0000000..e69de29 -- 2.20.1