Added drm support
This commit is contained in:
parent
3e75f74d6f
commit
cdd5c9bcf5
10
Makefile
10
Makefile
|
@ -1,16 +1,20 @@
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -Wshadow -Werror
|
||||
LDFLAGS = -lc
|
||||
CFLAGS = -Wall -Wshadow -Werror -I/usr/include/libdrm
|
||||
LDFLAGS = -lc -ldrm
|
||||
|
||||
SRCS := $(wildcard src/modules/*.c)
|
||||
OBJS := $(patsubst src/modules/%.c,%,$(SRCS))
|
||||
MODS := $(patsubst src/modules/%.c,%.so,$(SRCS))
|
||||
|
||||
%:
|
||||
mkdir -p build/modules
|
||||
$(CC) $(CFLAGS) src/modules/$@.c -o build/modules/$@.so -shared -fPIC -rdynamic
|
||||
$(CC) $(CFLAGS) src/modules/$@.c -o build/modules/$@.so -shared -fPIC -rdynamic -g
|
||||
|
||||
all: $(OBJS)
|
||||
gcc -std=c23 -g -o build/twm src/core/*.c $(CFLAGS) $(LDFLAGS) -ldl
|
||||
|
||||
clean:
|
||||
rm -rf build/*
|
||||
|
||||
run: all
|
||||
cd build; ./twm drm fb uevent ; cd -
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
#include "twm.h"
|
||||
#include "../twm.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
ModuleDisplay m = load_display_module("modules/fb.so");
|
||||
if (m.init == 0) abort();
|
||||
Modules ms = load_modules("modules", argv + 1, argc - 1);
|
||||
Vec2 (*get_size)() = module_find_func(ms, DISPLAY_GET_SIZE);
|
||||
void (*flip)() = module_find_func(ms, DISPLAY_FLIP);
|
||||
void (*put_pixel)(Vec2, Color) = module_find_func(ms, DISPLAY_PUT_PIXEL);
|
||||
|
||||
Vec2 display_size = get_size();
|
||||
for (int x = 0; x < display_size.x; x++) {
|
||||
for (int y = 0; y < display_size.y; y++) {
|
||||
put_pixel((Vec2){x,y}, (Color){x%256,y%256,0});
|
||||
}
|
||||
}
|
||||
|
||||
flip();
|
||||
|
||||
getchar();
|
||||
|
||||
unload_modules(ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,34 +1,88 @@
|
|||
#include "twm.h"
|
||||
#include "../twm.h"
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
||||
ModuleDisplay load_display_module(char* name) {
|
||||
void* dl = dlopen(name, RTLD_LAZY);
|
||||
if (dl == NULL) {
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "Failed to load module %s (%s)\n", name, dlerror());
|
||||
fflush(stderr);
|
||||
return (ModuleDisplay){0};
|
||||
int bitcount(uint64_t v) {
|
||||
int count = 0;
|
||||
while (v > 0) {
|
||||
v &= v - 1;
|
||||
count ++;
|
||||
}
|
||||
|
||||
ModuleDisplay m = {0};
|
||||
m.dll = dl;
|
||||
m.init = (DisplayInit)dlsym(dl, "display_init");
|
||||
if (m.init == NULL) goto error;
|
||||
m.blit = (DisplayBlit)dlsym(dl, "display_blit");
|
||||
if (m.blit == NULL) goto error;
|
||||
m.flip = (DisplayFlip)dlsym(dl, "display_flip");
|
||||
if (m.flip == NULL) goto error;
|
||||
m.close = (DisplayClose)dlsym(dl, "display_close");
|
||||
if (m.close == NULL) goto error;
|
||||
m.put_pixel = (DisplayPutPixel)dlsym(dl, "display_put_pixel");
|
||||
if (m.put_pixel == NULL) goto error;
|
||||
return m;
|
||||
|
||||
error:
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "Failed to load module %s (%s)\n", name, dlerror());
|
||||
fflush(stderr);
|
||||
dlclose(dl);
|
||||
return (ModuleDisplay){0};
|
||||
return count;
|
||||
}
|
||||
|
||||
void unload_modules(Modules ms) {
|
||||
for (size_t i = 0; i < ms.count; i++) {
|
||||
ms.modules[i].close();
|
||||
dlclose(ms.modules[i].dll);
|
||||
}
|
||||
}
|
||||
|
||||
Modules load_modules(char *module_dir, char *modules[], size_t num_modules) {
|
||||
Modules ms = { 0 };
|
||||
uint64_t needed = BIT(FEATURE_MAX) - 1;
|
||||
|
||||
for (size_t i = 0; i < num_modules && needed != 0; i++) {
|
||||
Module m = { 0 };
|
||||
char dll_name[1024];
|
||||
strcpy(dll_name, module_dir);
|
||||
strcat(dll_name, "/");
|
||||
strcat(dll_name, modules[i]);
|
||||
strcat(dll_name, ".so");
|
||||
m.dll = dlopen(dll_name, RTLD_LAZY);
|
||||
if (!m.dll) {
|
||||
LOG_WARNING("Failed to load library %s (%s)", dll_name, dlerror());
|
||||
continue;
|
||||
}
|
||||
uint64_t *feature_lists = (uint64_t*)dlsym(m.dll, "FEATURE_LISTS");
|
||||
|
||||
size_t best_feature = 0;
|
||||
int best_feature_value = 0;
|
||||
|
||||
for (size_t j = 0; feature_lists[j] != 0; j++) {
|
||||
if ((needed & feature_lists[j]) != 0 && (~needed & feature_lists[j]) == 0) {
|
||||
int value = bitcount(feature_lists[j]);
|
||||
if (value > best_feature_value) {
|
||||
best_feature_value = value;
|
||||
best_feature = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_feature_value == 0) {
|
||||
dlclose(m.dll);
|
||||
continue;
|
||||
}
|
||||
|
||||
m.init = (ModuleInit)dlsym(m.dll, "module_init");
|
||||
twm_assert(m.init, "Module doesn't have module_init");
|
||||
m.close = (ModuleClose)dlsym(m.dll, "module_close");
|
||||
twm_assert(m.close, "Module doesn't have module_close");
|
||||
|
||||
if ((m.funcs = (void*)m.init(best_feature)) == NULL) {
|
||||
dlclose(m.dll);
|
||||
continue;
|
||||
}
|
||||
|
||||
ms.modules = realloc(ms.modules, sizeof(Module) * ++ms.count);
|
||||
twm_assert(ms.modules, "Get more ram");
|
||||
memcpy(&ms.modules[ms.count - 1], &m, sizeof(Module));
|
||||
needed &= ~feature_lists[best_feature];
|
||||
}
|
||||
if (needed != 0) {
|
||||
LOG_WARNING("Failed to find all needed modules: %lu", needed);
|
||||
}
|
||||
return ms;
|
||||
}
|
||||
|
||||
void* module_find_func(Modules ms, ModuleFunc type) {
|
||||
for (size_t i = 0; i < ms.count; i++) {
|
||||
for (size_t j = 0; ms.modules[i].funcs[j].function_type != FUNC_END; j++) {
|
||||
if (ms.modules[i].funcs[j].function_type == type) {
|
||||
return ms.modules[i].funcs[j].func;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
} Color;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} Vec2;
|
||||
|
||||
typedef struct {
|
||||
Vec2 pos;
|
||||
Vec2 size;
|
||||
} Rect;
|
||||
|
||||
typedef struct {
|
||||
Rect size;
|
||||
Color *data;
|
||||
} Image;
|
||||
|
||||
typedef bool (*DisplayInit)(void**);
|
||||
typedef void (*DisplayPutPixel)(void*, Vec2, Color);
|
||||
typedef void (*DisplayBlit)(void*, Vec2, Image);
|
||||
typedef void (*DisplayFlip)(void*);
|
||||
typedef void (*DisplayClose)(void*);
|
||||
|
||||
typedef struct {
|
||||
void* dll;
|
||||
DisplayInit init;
|
||||
DisplayPutPixel put_pixel;
|
||||
DisplayBlit blit;
|
||||
DisplayFlip flip;
|
||||
DisplayClose close;
|
||||
} ModuleDisplay;
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef _TWM_H
|
||||
#define _TWM_H
|
||||
#include "module_display.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
ModuleDisplay load_display_module(char* name);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void* (*ModuleInit)(int);
|
||||
typedef void (*ModuleClose)();
|
||||
|
||||
typedef struct {
|
||||
ModuleFunc function_type;
|
||||
void *func;
|
||||
} FeatureFunc;
|
||||
|
||||
typedef struct {
|
||||
void *dll;
|
||||
void *state;
|
||||
|
||||
ModuleInit init;
|
||||
ModuleClose close;
|
||||
|
||||
FeatureFunc *funcs;
|
||||
} Module;
|
||||
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
Module *modules;
|
||||
} Modules;
|
|
@ -1,38 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
} Color;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} Vec2;
|
||||
|
||||
typedef struct {
|
||||
Vec2 pos;
|
||||
Vec2 size;
|
||||
} Rect;
|
||||
|
||||
typedef struct {
|
||||
Rect size;
|
||||
Color *data;
|
||||
} Image;
|
||||
|
||||
typedef bool (*DisplayInit)(void**);
|
||||
typedef void (*DisplayPutPixel)(void*, Vec2, Color);
|
||||
typedef void (*DisplayBlit)(void*, Vec2, Image);
|
||||
typedef void (*DisplayFlip)(void*);
|
||||
typedef void (*DisplayClose)(void*);
|
||||
|
||||
typedef struct {
|
||||
void* dll;
|
||||
DisplayInit init;
|
||||
DisplayPutPixel put_pixel;
|
||||
DisplayBlit blit;
|
||||
DisplayFlip flip;
|
||||
DisplayClose close;
|
||||
} ModuleDisplay;
|
|
@ -0,0 +1,228 @@
|
|||
#define MODULE_NAME "drm"
|
||||
#include "../twm.h"
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#define max(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
typedef struct {
|
||||
uint32_t id; // Unknown use
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t pitch;
|
||||
uint32_t handle;
|
||||
uint64_t size;
|
||||
uint8_t *data;
|
||||
} DRMFb;
|
||||
|
||||
typedef struct _DRMConnector {
|
||||
uint32_t id;
|
||||
bool enabled;
|
||||
|
||||
drmModeCrtcPtr old_mode;
|
||||
|
||||
uint32_t crtc_id;
|
||||
drmModeModeInfo mode;
|
||||
|
||||
Vec2 size;
|
||||
DRMFb frame;
|
||||
|
||||
struct _DRMConnector *next;
|
||||
} DRMConnector;
|
||||
|
||||
typedef struct {
|
||||
int drm_fd;
|
||||
DRMFb frameBuffer;
|
||||
DRMConnector *connectors;
|
||||
} DRMState;
|
||||
|
||||
static DRMState *data;
|
||||
|
||||
uint32_t find_crtc(int fd, drmModeResPtr resources, drmModeConnectorPtr connector, uint32_t *taken) {
|
||||
for (int i = 0; i < connector->count_encoders; i++) {
|
||||
drmModeEncoderPtr encoder = drmModeGetEncoder(fd, connector->encoders[i]);
|
||||
if (!encoder) continue;
|
||||
for (int j = 0; j < resources->count_crtcs; j++) {
|
||||
if ((encoder->possible_crtcs & BIT(j)) == 0) continue; // Not compatible
|
||||
if ((*taken & BIT(j)) != 0) continue; // Already taken
|
||||
drmModeFreeEncoder(encoder);
|
||||
*taken |= BIT(j);
|
||||
return resources->crtcs[j];
|
||||
}
|
||||
drmModeFreeEncoder(encoder);
|
||||
}
|
||||
LOG_WARNING("Failed to find CRTC for connector %d", connector->connector_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool create_fb(int fd, DRMFb *out, Vec2 size) {
|
||||
if(drmModeCreateDumbBuffer(fd, size.x, size.y, 32, 0, &out->handle, &out->pitch, &out->size) < 0) return false;
|
||||
|
||||
uint32_t handles[4] = { out->handle };
|
||||
uint32_t pitches[4] = { out->pitch };
|
||||
uint32_t offsets[4] = { 0 };
|
||||
|
||||
if (drmModeAddFB2(fd, size.x, size.y, DRM_FORMAT_XRGB8888, handles, pitches, offsets, &out->id, 0) < 0) goto err_dumb;
|
||||
|
||||
uint64_t offset;
|
||||
if(drmModeMapDumbBuffer(fd,out->handle, &offset) < 0) goto err_dumb;
|
||||
|
||||
out->data = mmap(0, out->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
|
||||
if (out->data == MAP_FAILED) goto err_fb;
|
||||
return true;
|
||||
|
||||
err_fb:
|
||||
drmModeRmFB(fd, out->id);
|
||||
err_dumb:
|
||||
drmModeDestroyDumbBuffer(fd, out->handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
void destroy_fb(int fd, DRMFb *fb) {
|
||||
munmap(fb->data, fb->size);
|
||||
drmModeRmFB(fd, fb->id);
|
||||
drmModeDestroyDumbBuffer(fd, fb->handle);
|
||||
}
|
||||
|
||||
void display_put_pixel(Vec2 position, Color col) {
|
||||
DRMConnector *conn = data->connectors;
|
||||
while (conn) {
|
||||
if (conn->enabled) {
|
||||
if (position.x < 0 || position.x >= conn->size.x || position.y < 0 || position.y >= conn->size.y) continue;
|
||||
uint8_t *row = conn->frame.data + position.y*conn->frame.pitch;
|
||||
row[position.x * 4 + 0] = col.blue;
|
||||
row[position.x * 4 + 1] = col.green;
|
||||
row[position.x * 4 + 2] = col.red;
|
||||
row[position.x * 4 + 3] = 0x00;
|
||||
}
|
||||
conn = conn->next;
|
||||
}
|
||||
}
|
||||
|
||||
void display_blit(Vec2 pos, Image image) {
|
||||
for (int x = 0; x < image.size.x; x++) {
|
||||
for (int y = 0; y < image.size.y; y++) {
|
||||
display_put_pixel((Vec2){x+pos.x,y+pos.y}, image.data[y][x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display_flip() {
|
||||
DRMConnector *conn = data->connectors;
|
||||
while (conn) {
|
||||
if (conn->enabled) {
|
||||
drmModeClip clip = (drmModeClip){.x1 = 0, .y1 = 0, .x2 = conn->frame.width, .y2 = conn->frame.height};
|
||||
drmModeDirtyFB(data->drm_fd, conn->frame.id, &clip, 1);
|
||||
}
|
||||
conn = conn->next;
|
||||
}
|
||||
}
|
||||
|
||||
Vec2 display_get_size() {
|
||||
int maxX = 0;
|
||||
int maxY = 0;
|
||||
DRMConnector *conn = data->connectors;
|
||||
while (conn) {
|
||||
if (conn->enabled) {
|
||||
maxX = max(maxX, conn->size.x);
|
||||
maxY = max(maxY, conn->size.y);
|
||||
}
|
||||
conn = conn->next;
|
||||
}
|
||||
return (Vec2){maxX, maxY};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
const uint64_t FEATURE_LISTS[] = {
|
||||
BIT(BASIC_RENDERING) | BIT(ADVANCED_RENDERING),
|
||||
0
|
||||
};
|
||||
|
||||
const FeatureFunc FUNCTIONS[] = {
|
||||
(FeatureFunc){ DISPLAY_PUT_PIXEL, display_put_pixel },
|
||||
(FeatureFunc){ DISPLAY_BLIT, display_blit },
|
||||
(FeatureFunc){ DISPLAY_GET_SIZE, display_get_size },
|
||||
(FeatureFunc){ DISPLAY_FLIP, display_flip },
|
||||
(FeatureFunc){ FUNC_END, NULL }
|
||||
};
|
||||
|
||||
FeatureFunc* module_init(size_t features_selected) {
|
||||
data = malloc(sizeof(DRMState));
|
||||
if (data == NULL) return NULL;
|
||||
|
||||
data->drm_fd = open("/dev/dri/card0", O_RDWR);
|
||||
|
||||
drmModeResPtr resources = drmModeGetResources(data->drm_fd);
|
||||
twm_assert_custom(resources, "Failed to find drm resources", return NULL);
|
||||
|
||||
data->connectors = NULL;
|
||||
uint32_t taken_crtcs = 0;
|
||||
|
||||
for (int i = 0; i < resources->count_connectors; i++) {
|
||||
drmModeConnectorPtr drm_connector = drmModeGetConnector(data->drm_fd, resources->connectors[i]);
|
||||
twm_assert_custom(drm_connector != NULL, "Failed to open connector", continue);
|
||||
|
||||
DRMConnector *connector = malloc(sizeof(DRMConnector));
|
||||
twm_assert_custom(connector != NULL, "Failed to allocate connector data", goto cleanup);
|
||||
connector->next = data->connectors;
|
||||
data->connectors = connector;
|
||||
|
||||
connector->id = drm_connector->connector_id;
|
||||
connector->enabled = drm_connector->connection == DRM_MODE_CONNECTED;
|
||||
|
||||
LOG_INFO("Found connector %d (%s)", connector->id, connector->enabled?"Enabled":"Disabled");
|
||||
|
||||
if (!connector->enabled) goto cleanup;
|
||||
twm_assert_custom(drm_connector->modes != NULL, "Connector has no modes", connector->enabled = false; goto cleanup);
|
||||
|
||||
connector->crtc_id = find_crtc(data->drm_fd, resources, drm_connector, &taken_crtcs);
|
||||
twm_assert_custom(connector->crtc_id != 0, "Failed to find crtc", connector->enabled = false; goto cleanup);
|
||||
|
||||
LOG_INFO("\tFound CRTC %d", connector->crtc_id);
|
||||
|
||||
connector->mode = drm_connector->modes[0];
|
||||
connector->size = (Vec2){connector->mode.hdisplay, connector->mode.vdisplay};
|
||||
|
||||
LOG_INFO("\tUsing Mode %dx%d", connector->size.x, connector->size.y);
|
||||
|
||||
twm_assert_custom(create_fb(data->drm_fd, &connector->frame, connector->size), "Failed to make framebuffer", connector->enabled = false; goto cleanup);
|
||||
LOG_INFO("\tMade framebuffer with id %d", connector->frame.id);
|
||||
|
||||
connector->old_mode = drmModeGetCrtc(data->drm_fd, connector->crtc_id);
|
||||
|
||||
twm_assert_custom(drmModeSetCrtc(data->drm_fd, connector->crtc_id, connector->frame.id, 0, 0, &connector->id, 1, &connector->mode) >= 0, "Failed to set CRTC mode", connector->enabled = false; goto cleanup);
|
||||
|
||||
cleanup:
|
||||
drmModeFreeConnector(drm_connector);
|
||||
}
|
||||
|
||||
drmModeFreeResources(resources);
|
||||
|
||||
return (FeatureFunc*)FUNCTIONS;
|
||||
}
|
||||
|
||||
|
||||
void module_close() {
|
||||
while (data->connectors) {
|
||||
if (data->connectors->enabled) {
|
||||
destroy_fb(data->drm_fd, &data->connectors->frame);
|
||||
drmModeCrtcPtr crtc = data->connectors->old_mode;
|
||||
if (crtc) {
|
||||
drmModeSetCrtc(data->drm_fd, crtc->crtc_id, crtc->buffer_id,
|
||||
crtc->x, crtc->y, &data->connectors->id, 1, &crtc->mode);
|
||||
drmModeFreeCrtc(crtc);
|
||||
}
|
||||
}
|
||||
DRMConnector *tmp = data->connectors->next;
|
||||
free(data->connectors);
|
||||
data->connectors = tmp;
|
||||
}
|
||||
close(data->drm_fd);
|
||||
free(data);
|
||||
}
|
|
@ -1 +1,83 @@
|
|||
void t(){}
|
||||
#define MODULE_NAME "drm"
|
||||
#include "../twm.h"
|
||||
#include <linux/fb.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct {
|
||||
int fb_fd;
|
||||
long screen_size;
|
||||
struct fb_fix_screeninfo fscrinfo;
|
||||
struct fb_var_screeninfo vscrinfo;
|
||||
uint8_t *frame_buffer;
|
||||
} FBData;
|
||||
|
||||
static FBData *data;
|
||||
|
||||
Vec2 display_get_size() {
|
||||
return (Vec2){data->vscrinfo.xres, data->vscrinfo.yres};
|
||||
}
|
||||
|
||||
uint32_t get_pixel_color(Color col) {
|
||||
return (col.red<<data->vscrinfo.red.offset) | (col.green<<data->vscrinfo.green.offset) | (col.blue<<data->vscrinfo.blue.offset);
|
||||
}
|
||||
|
||||
void display_put_pixel(Vec2 pos, Color col) {
|
||||
long pixel_offset = (pos.x + data->vscrinfo.xoffset) * (data->vscrinfo.bits_per_pixel / 8) + (pos.y + data->vscrinfo.yoffset) * data->fscrinfo.line_length;
|
||||
*((uint32_t*)(data->frame_buffer + pixel_offset)) = get_pixel_color(col);
|
||||
}
|
||||
|
||||
|
||||
void display_blit(Vec2 pos, Image image) {
|
||||
for (int x = 0; x < image.size.x; x++) {
|
||||
for (int y = 0; y < image.size.y; y++) {
|
||||
display_put_pixel((Vec2){x+pos.x,y+pos.y}, image.data[y][x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display_flip() {
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
|
||||
const uint64_t FEATURE_LISTS[] = {
|
||||
BIT(BASIC_RENDERING),
|
||||
0
|
||||
};
|
||||
|
||||
const FeatureFunc FUNCTIONS[] = {
|
||||
(FeatureFunc){ DISPLAY_PUT_PIXEL, display_put_pixel },
|
||||
(FeatureFunc){ DISPLAY_BLIT, display_blit },
|
||||
(FeatureFunc){ DISPLAY_GET_SIZE, display_get_size },
|
||||
(FeatureFunc){ DISPLAY_FLIP, display_flip },
|
||||
(FeatureFunc){ FUNC_END, NULL },
|
||||
};
|
||||
|
||||
FeatureFunc *module_init(size_t feature_selected) {
|
||||
data = malloc(sizeof(FBData));
|
||||
if (data == NULL) return NULL;
|
||||
data->fb_fd = open("/dev/fb0", O_RDWR);
|
||||
|
||||
ioctl(data->fb_fd, FBIOGET_FSCREENINFO, &data->fscrinfo);
|
||||
ioctl(data->fb_fd, FBIOGET_VSCREENINFO, &data->vscrinfo);
|
||||
|
||||
data->vscrinfo.bits_per_pixel = 32;
|
||||
data->vscrinfo.grayscale = 0;
|
||||
|
||||
ioctl(data->fb_fd, FBIOPUT_VSCREENINFO, &data->vscrinfo);
|
||||
ioctl(data->fb_fd, FBIOGET_VSCREENINFO, &data->vscrinfo);
|
||||
|
||||
data->screen_size = data->vscrinfo.yres_virtual * data->fscrinfo.line_length;
|
||||
data->frame_buffer = mmap(0, data->screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, data->fb_fd, (off_t)0);
|
||||
|
||||
return (FeatureFunc*)FUNCTIONS;
|
||||
}
|
||||
|
||||
void module_close() {
|
||||
munmap(data->frame_buffer, data->screen_size);
|
||||
close(data->fb_fd);
|
||||
free(data);
|
||||
}
|
||||
|
|
43
src/twm.h
43
src/twm.h
|
@ -1,8 +1,47 @@
|
|||
#ifndef _TWM_H
|
||||
#define _TWM_H
|
||||
#include "module_display.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
ModuleDisplay load_display_module(char* name);
|
||||
typedef enum {
|
||||
BASIC_RENDERING = 0,
|
||||
ADVANCED_RENDERING = 1,
|
||||
FEATURE_MAX
|
||||
} ModuleFeatures;
|
||||
|
||||
typedef enum {
|
||||
FUNC_END = 0,
|
||||
DISPLAY_PUT_PIXEL,
|
||||
DISPLAY_BLIT,
|
||||
DISPLAY_FLIP,
|
||||
DISPLAY_GET_SIZE,
|
||||
MODULE_FUNC_MAX
|
||||
} ModuleFunc;
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#define BIT(n) ((uint64_t)1<<(n))
|
||||
|
||||
#ifdef MODULE_NAME
|
||||
#define LOG_WARNING(f, ...) do {printf("\033[33;1m[ WARNING ]\033[0m Module " MODULE_NAME ": " f "\n", __VA_ARGS__); fflush(stdout); } while (0)
|
||||
#define LOG_INFO(f, ...) do {printf("\033[34;1m[ INFO ]\033[0m Module " MODULE_NAME ": " f "\n", __VA_ARGS__); fflush(stdout); } while (0)
|
||||
#define LOG_ERROR(f, ...) do {printf("\033[31;1m[ ERROR ]\033[0m Module " MODULE_NAME ": " f "\n", __VA_ARGS__); fflush(stdout); } while (0)
|
||||
#else
|
||||
#define LOG_WARNING(f, ...) do {printf("\033[33;1m[ WARNING ]\033[0m " f "\n", __VA_ARGS__); fflush(stdout); } while (0)
|
||||
#define LOG_INFO(f, ...) do {printf("\033[34;1m[ INFO ]\033[0m " f "\n", __VA_ARGS__); fflush(stdout); } while (0)
|
||||
#define LOG_ERROR(f, ...) do {printf("\033[31;1m[ ERROR ]\033[0m " f "\n", __VA_ARGS__); fflush(stdout); } while (0)
|
||||
#endif
|
||||
|
||||
#define twm_assert(e, m) do { if (!e) { LOG_ERROR("Assertion Failed: %s (%s:%d %s)", m, __FILE__, __LINE__, #e); abort(); } } while (0)
|
||||
#define twm_assert_custom(e, m, c) do { if (!(e)) { LOG_ERROR("Assertion Failed: %s (%s:%d %s)", m, __FILE__, __LINE__, #e); c; } } while (0)
|
||||
|
||||
Modules load_modules(char*, char*[], size_t);
|
||||
void unload_modules(Modules);
|
||||
void* module_find_func(Modules ms, ModuleFunc type);
|
||||
|
||||
typedef struct { int x; int y; } Vec2;
|
||||
typedef struct { uint8_t red; uint8_t green; uint8_t blue; } Color;
|
||||
typedef struct { Vec2 size; Color** data; } Image;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue