diff --git a/external/lua/CMakeLists.txt b/external/lua/CMakeLists.txt index 01a7e87f3..3dfd55210 100644 --- a/external/lua/CMakeLists.txt +++ b/external/lua/CMakeLists.txt @@ -2,7 +2,7 @@ # Port of LUA5.1 makefiles to CMakeLists for easier build integration # PROJECT ( lua51 ) -cmake_minimum_required( VERSION 2.8 ) +cmake_minimum_required( VERSION 3.5 ) set (MAJOR_VERSION 5 ) set (MINOR_VERSION 1 ) diff --git a/external/lua/ldump.c b/external/lua/ldump.c index c9d3d4870..b69a12729 100644 --- a/external/lua/ldump.c +++ b/external/lua/ldump.c @@ -60,7 +60,7 @@ static void DumpVector(const void* b, int n, size_t size, DumpState* D) static void DumpString(const TString* s, DumpState* D) { - if (s==NULL || getstr(s)==NULL) + if (s==NULL) { size_t size=0; DumpVar(size,D); diff --git a/external/lua/ltablib.c b/external/lua/ltablib.c index b6d9cb4ac..0bdac7f6c 100644 --- a/external/lua/ltablib.c +++ b/external/lua/ltablib.c @@ -137,7 +137,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) { if (!lua_isstring(L, -1)) luaL_error(L, "invalid value (%s) at index %d in table for " LUA_QL("concat"), luaL_typename(L, -1), i); - luaL_addvalue(b); + luaL_addvalue(b); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d417f69ac..cefb0f279 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -164,13 +164,13 @@ if (CLIENT_LIBRARY_BUILD OR BUILD_PRESET STREQUAL "client") endif() else() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(VPLATFORM_STR "sdl sdl2") + set(VPLATFORM_STR "sdl2") if (NOT VIDEO_PLATFORM) set(VIDEO_PLATFORM "sdl2") endif() set(CMAKE_INSTALL_LIBDIR /usr/local/share/lib) else() - set(VPLATFORM_STR "egl-dri, sdl, sdl2, egl-gles") + set(VPLATFORM_STR "egl-dri, sdl2, egl-gles") if (NOT VIDEO_PLATFORM) set(VIDEO_PLATFORM "egl-dri") endif() @@ -490,10 +490,10 @@ else() shmif/arcan_shmif_sub.c engine/arcan_vr.h engine/arcan_vr.c + engine/arcan_raster.c platform/platform.h platform/video_platform.h shmif/tui/raster/pixelfont.c - shmif/tui/raster/raster.c ) # database tool is sqlite3 + libc so less need to work diff --git a/src/a12/a12_int.h b/src/a12/a12_int.h index 2af478a2b..4342c56a8 100644 --- a/src/a12/a12_int.h +++ b/src/a12/a12_int.h @@ -406,4 +406,7 @@ struct appl_meta* a12int_get_directory(struct a12_state*, uint64_t* clk); * If notify is set changes will be sent dynamically */ void a12int_request_dirlist(struct a12_state*, bool notify); +unsigned long long arcan_timemillis(); +void arcan_random(uint8_t* dst, size_t ntc); + #endif diff --git a/src/a12/net/a12_helper_discover.c b/src/a12/net/a12_helper_discover.c index da7fb9737..84418f016 100644 --- a/src/a12/net/a12_helper_discover.c +++ b/src/a12/net/a12_helper_discover.c @@ -30,6 +30,10 @@ #include "anet_helper.h" #include "hashmap.h" +#ifndef LOG +#define LOG(X, ...) (fprintf(stderr, X, arcan_timemillis(), ## __VA_ARGS__)) +#endif + static struct hashmap_s known_beacons; struct ipcfg { diff --git a/src/a12/net/a12_helper_srv.c b/src/a12/net/a12_helper_srv.c index fc131abc6..6cb5c1ff7 100644 --- a/src/a12/net/a12_helper_srv.c +++ b/src/a12/net/a12_helper_srv.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/src/a12/net/dir_cl.c b/src/a12/net/dir_cl.c index 567b10505..63652252a 100644 --- a/src/a12/net/dir_cl.c +++ b/src/a12/net/dir_cl.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "../a12.h" #include "../a12_int.h" diff --git a/src/a12/net/dir_lua.c b/src/a12/net/dir_lua.c index 227d6420e..a42b022a0 100644 --- a/src/a12/net/dir_lua.c +++ b/src/a12/net/dir_lua.c @@ -25,6 +25,11 @@ #include "anet_helper.h" #include "directory.h" +#ifndef COUNT_OF +#define COUNT_OF(x) \ + ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) +#endif + #if LUA_VERSION_NUM == 501 #define lua_rawlen(x, y) lua_objlen(x, y) #endif diff --git a/src/a12/net/dir_srv_worker.c b/src/a12/net/dir_srv_worker.c index 369afbe87..8f0776657 100644 --- a/src/a12/net/dir_srv_worker.c +++ b/src/a12/net/dir_srv_worker.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "../a12.h" #include "../a12_int.h" diff --git a/src/a12/net/net.c b/src/a12/net/net.c index 9c4460f28..aa22cf327 100644 --- a/src/a12/net/net.c +++ b/src/a12/net/net.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/src/engine/arcan_conductor.c b/src/engine/arcan_conductor.c index f68335c31..bcfc22a7e 100644 --- a/src/engine/arcan_conductor.c +++ b/src/engine/arcan_conductor.c @@ -635,7 +635,7 @@ static arcan_tick_cb outcb; static void conductor_cycle(int); int arcan_conductor_run(arcan_tick_cb tick) { - arcan_evctx* evctx = arcan_event_defaultctx(); + struct arcan_evctx* evctx = arcan_event_defaultctx(); outcb = tick; int exit_code = EXIT_FAILURE; alloc_frameserver_struct(); diff --git a/src/engine/arcan_event.c b/src/engine/arcan_event.c index 40096d9ab..96c642439 100644 --- a/src/engine/arcan_event.c +++ b/src/engine/arcan_event.c @@ -46,7 +46,7 @@ typedef struct queue_cell queue_cell; -static arcan_event eventbuf[ARCAN_EVENT_QUEUE_LIM]; +static struct arcan_event eventbuf[ARCAN_EVENT_QUEUE_LIM]; static uint8_t eventfront = 0, eventback = 0; static int64_t epoch; @@ -83,7 +83,8 @@ static struct pollfd evsrc_pollset[64]; static struct evsrc_meta evsrc_meta[64]; static uint64_t evsrc_bitmap; -arcan_evctx* arcan_event_defaultctx(){ +struct arcan_evctx* arcan_event_defaultctx() +{ return &default_evctx; } @@ -91,7 +92,7 @@ arcan_evctx* arcan_event_defaultctx(){ * If the shmpage integrity is somehow compromised, * if semaphore use is out of order etc. */ -static void pull_killswitch(arcan_evctx* ctx) +static void pull_killswitch(struct arcan_evctx* ctx) { arcan_frameserver* ks = (arcan_frameserver*) ctx->synch.killswitch; arcan_sem_post(ctx->synch.handle); @@ -101,17 +102,17 @@ static void pull_killswitch(arcan_evctx* ctx) ctx->synch.killswitch = NULL; } -static bool queue_full(arcan_evctx* ctx) +static bool queue_full(struct arcan_evctx* ctx) { return (((*ctx->back + 1) % ctx->eventbuf_sz) == *ctx->front); } -static bool queue_empty(arcan_evctx* ctx) +static bool queue_empty(struct arcan_evctx* ctx) { return (*ctx->front == *ctx->back); } -int arcan_event_poll(arcan_evctx* ctx, struct arcan_event* dst) +int arcan_event_poll(struct arcan_evctx* ctx, struct arcan_event* dst) { assert(dst); if (queue_empty(ctx)) @@ -158,22 +159,22 @@ void arcan_event_repl(struct arcan_evctx* ctx, enum ARCAN_EVENT_CATEGORY cat, } -void arcan_event_maskall(arcan_evctx* ctx) +void arcan_event_maskall(struct arcan_evctx* ctx) { ctx->mask_cat_inp = 0xffffffff; } -void arcan_event_clearmask(arcan_evctx* ctx) +void arcan_event_clearmask(struct arcan_evctx* ctx) { ctx->mask_cat_inp = 0; } -void arcan_event_setmask(arcan_evctx* ctx, uint32_t mask) +void arcan_event_setmask(struct arcan_evctx* ctx, uint32_t mask) { ctx->mask_cat_inp = mask; } -int arcan_event_denqueue(arcan_evctx* ctx, const struct arcan_event* const src) +int arcan_event_denqueue(struct arcan_evctx* ctx, const struct arcan_event* const src) { if (ctx->drain){ arcan_event ev = *src; @@ -191,7 +192,7 @@ int arcan_event_denqueue(arcan_evctx* ctx, const struct arcan_event* const src) * implementation to support waking up the child, and that blocking behaviors * in the main thread is always forbidden. */ -int arcan_event_enqueue(arcan_evctx* ctx, const struct arcan_event* const src) +int arcan_event_enqueue(struct arcan_evctx* ctx, const struct arcan_event* const src) { /* early-out mask-filter, these are only ever used to silently * discard input / output (only operate on head and tail of ringbuffer) */ @@ -258,7 +259,7 @@ int arcan_event_enqueue(arcan_evctx* ctx, const struct arcan_event* const src) return ARCAN_OK; } -static inline int queue_used(arcan_evctx* dq) +static inline int queue_used(struct arcan_evctx* dq) { int rv = *(dq->front) > *(dq->back) ? dq->eventbuf_sz - *(dq->front) + *(dq->back) : *(dq->back) - *(dq->front); @@ -327,7 +328,8 @@ static bool append_bufferstream(struct arcan_frameserver* tgt, arcan_extevent* e } -int arcan_event_queuetransfer(arcan_evctx* dstqueue, arcan_evctx* srcqueue, +int arcan_event_queuetransfer( + struct arcan_evctx* dstqueue, struct arcan_evctx* srcqueue, enum ARCAN_EVENT_CATEGORY allowed, float sat, struct arcan_frameserver* tgt) { if (!srcqueue || !dstqueue || (srcqueue && !srcqueue->front) @@ -558,7 +560,7 @@ int64_t arcan_frametime() return now - epoch; } -float arcan_event_process(arcan_evctx* ctx, arcan_tick_cb cb) +float arcan_event_process(struct arcan_evctx* ctx, arcan_tick_cb cb) { int64_t base = ctx->c_ticks * ARCAN_TIMER_TICK; int64_t delta = arcan_frametime() - base; @@ -649,7 +651,7 @@ void arcan_bench_register_frame() lastframe = ftime; } -void arcan_event_deinit(arcan_evctx* ctx, bool flush) +void arcan_event_deinit(struct arcan_evctx* ctx, bool flush) { platform_event_deinit(ctx); @@ -826,14 +828,14 @@ bool arcan_event_del_source( return false; } -void arcan_event_setdrain(arcan_evctx* ctx, arcan_event_handler drain) +void arcan_event_setdrain(struct arcan_evctx* ctx, arcan_event_handler drain) { if (!ctx->local) return; ctx->drain = drain; } -void arcan_event_init(arcan_evctx* ctx) +void arcan_event_init(struct arcan_evctx* ctx) { /* * non-local (i.e. shmpage resident) event queues has a different diff --git a/src/engine/arcan_frameserver.h b/src/engine/arcan_frameserver.h index 7b45cb541..df7a51681 100644 --- a/src/engine/arcan_frameserver.h +++ b/src/engine/arcan_frameserver.h @@ -126,7 +126,7 @@ struct arcan_frameserver { /* signaling primitives */ sem_handle vsync, async, esync; - file_handle dpipe; + int dpipe; /* if we spawn child, track if it is alive */ process_handle child; @@ -378,7 +378,7 @@ bool arcan_frameserver_tick_control(arcan_frameserver* src, bool tick, int ff); * filter events that are outside the accepted category / kind maintained * in the frameserver struct */ -void arcan_frameserver_pollevent(arcan_frameserver*, arcan_evctx*); +void arcan_frameserver_pollevent(arcan_frameserver*, struct arcan_evctx*); /* * Attempt to retrieve a copy of the current LUT-ramps for a specific diff --git a/src/engine/arcan_main.c b/src/engine/arcan_main.c index 835a71fb4..f522809ca 100644 --- a/src/engine/arcan_main.c +++ b/src/engine/arcan_main.c @@ -560,7 +560,7 @@ int MAIN_REDIR(int argc, char* argv[]) fullscreen = false; /* grab video, (necessary) */ - arcan_evctx* evctx = arcan_event_defaultctx(); + struct arcan_evctx* evctx = arcan_event_defaultctx(); arcan_event_init(evctx); if (arcan_video_init(width, height, 32, fullscreen, windowed, diff --git a/src/engine/arcan_raster.c b/src/engine/arcan_raster.c new file mode 100644 index 000000000..50001a36d --- /dev/null +++ b/src/engine/arcan_raster.c @@ -0,0 +1,587 @@ +#include +#include "../shmif/arcan_shmif.h" +#include "../shmif/arcan_tui.h" + +#include "platform.h" +#include "arcan_ttf.h" + +#include "../shmif/tui/raster/raster.h" +#include "../shmif/tui/raster/pixelfont.h" + +struct cell { + shmif_pixel fc; + shmif_pixel bc; + uint32_t ucs4; + uint8_t attr; + uint8_t attr_ext; +}; + +struct tui_raster_context { + struct tui_font* fonts[4]; + int last_style; + int cursor_state; + + shmif_pixel cc; + +/* custom hook, when set the cursor won't actually be drawn but instead + * forwarded here in order to provide more styling / efficient drawing. */ + void (*ext_cursor)( + struct tui_raster_context*, + size_t x, size_t y, + size_t px, size_t py, + size_t cw, size_t pxw, + int style, + uint8_t col[static 3], + void* + ); + + size_t cell_w; + size_t cell_h; + + size_t min_x, min_y; + size_t max_x, max_y; +}; + +static bool draw_box_px( +shmif_pixel* px, size_t pitch, size_t max_w, size_t max_h, +size_t x, size_t y, size_t w, size_t h, shmif_pixel col) +{ + if (x >= max_w || y >= max_h || x + w > max_w || y + h > max_h) + return false; + + int ux = x + w > max_w ? max_w : x + w; + int uy = y + h > max_h ? max_h : y + h; + + for (int cy = y; cy < uy; cy++) + for (int cx = x; cx < ux; cx++) + px[ cy * pitch + cx ] = col; + + return true; +} + +static bool draw_box(struct arcan_shmif_cont* c, + size_t x, size_t y, int w, int h, shmif_pixel col) +{ + return draw_box_px(c->vidp, c->pitch, c->w, c->h, x, y, w, h, col); +} +void tui_raster_setfont( + struct tui_raster_context* ctx, struct tui_font** src, size_t n_fonts) +{ + for (size_t i = 0; i < 4; i++) + ctx->fonts[i] = i < n_fonts ? src[i] : NULL; + ctx->last_style = -1; +} + +struct tui_raster_context* tui_raster_setup(size_t cell_w, size_t cell_h) +{ + struct tui_raster_context* res = malloc(sizeof(struct tui_raster_context)); + if (!res) + return NULL; + + *res = (struct tui_raster_context){ + .cell_w = cell_w, + .cell_h = cell_h, + .cc = SHMIF_RGBA(0x00, 0xaa, 0x00, 0xff), + .last_style = -1 + }; + + return res; +} + +void tui_raster_get_cell_size( + struct tui_raster_context* ctx, size_t* w, size_t* h) +{ + *w = ctx->cell_w; + *h = ctx->cell_h; +} + +void tui_raster_cell_size(struct tui_raster_context* ctx, size_t w, size_t h) +{ + ctx->cell_w = w; + ctx->cell_h = h; +} + +void tui_raster_cursor_color(struct tui_raster_context* ctx, uint8_t col[static 3]) +{ + ctx->cc = SHMIF_RGBA(col[0], col[1], col[2], 0xff); +} + +void tui_raster_cursor_control + (struct tui_raster_context* ctx, + void (*ext_cursor) + (struct tui_raster_context*, size_t, size_t, + size_t, size_t, size_t, size_t, int, uint8_t[static 3], void*), void* tag) +{ + ctx->ext_cursor = ext_cursor; +} + +static void unpack_u32(uint32_t* dst, uint8_t* inbuf) +{ + *dst = + ((uint64_t)inbuf[0] << 0) | + ((uint64_t)inbuf[1] << 8) | + ((uint64_t)inbuf[2] << 16) | + ((uint64_t)inbuf[3] << 24); +} + +static void unpack_cell(uint8_t unpack[static 12], struct cell* dst, uint8_t alpha) +{ + dst->fc = SHMIF_RGBA(unpack[0], unpack[1], unpack[2], 0xff); + dst->bc = SHMIF_RGBA(unpack[3], unpack[4], unpack[5], alpha); + dst->attr = unpack[6]; + dst->attr_ext = unpack[7]; + + unpack_u32(&dst->ucs4, &unpack[8]); +} + +static void drawborder_edge( + struct tui_raster_context* ctx, struct cell* cell, shmif_pixel* vidp, + size_t pitch, int x, int y, size_t maxx, size_t maxy, int bv) +{ +/* Missing: + * Other heuristics to consider here would be LEFT,RIGHT+TOP,BOTTOM and use + * that to draw a rounded border. If there is cell-spacing inserted half the + * spacing area should be used instead. */ + +/* increase the border size when the cell size goes up, but keep uniform */ + int n_row = (ctx->cell_h + 15) / 16; + int n_col = (ctx->cell_w + 15) / 16; + + if (n_row > n_col) + n_row = n_col; + else + n_col = n_row; + + if (bv & CEATTR_BORDER_T){ + draw_box_px(vidp, pitch, maxx, maxy, x, y, ctx->cell_w, n_row, cell->fc); + } + + if (bv & CEATTR_BORDER_D){ + draw_box_px(vidp, pitch, maxx, maxy, + x, y + ctx->cell_h - n_row, ctx->cell_w, n_row, cell->fc); + } + + if (bv & CEATTR_BORDER_L){ + draw_box_px(vidp, pitch, maxx, maxy, x, y, n_col, ctx->cell_h, cell->fc); + } + + if (bv & CEATTR_BORDER_R){ + draw_box_px(vidp, pitch, maxx, maxy, + x + ctx->cell_w - n_col, y, n_col, ctx->cell_h, cell->fc); + } +} + +static void linehint(struct tui_raster_context* ctx, struct cell* cell, + shmif_pixel* vidp, size_t pitch, int x, int y, size_t maxx, size_t maxy, + bool strikethrough, bool underline) +{ + if (underline){ + int n_lines = (int)(ctx->cell_h * 0.05) | 1; + draw_box_px(vidp, pitch, maxx, maxy, + x, y + ctx->cell_h - n_lines, ctx->cell_w, n_lines, cell->fc); + } +/* the 'alt' underline mode should be drawn doubly or squiggly - e.g. + * float xf = 2pi/w + * for x to x+cell_w: y = yf * cos(x * xf) + y + 1 + * and grab y based on cell_h - underline start (then center Y in that) + * with rough wu antialiasing, i.e. calculate floor/ceil of y into y1,y2 + * and y - y1 gives i1, y2 - y gives i2, premut to color and draw. + */ + +/* the y value should be retrievable from the font rather than using the cell */ + if (strikethrough){ + int n_lines = (int)(ctx->cell_h * 0.05) | 1; + draw_box_px(vidp, pitch, maxx, maxy, + x, y + (ctx->cell_h >> 1) - (n_lines >> 1), + ctx->cell_w, n_lines, cell->fc); + } +} + +static void drawcursor_px( + struct tui_raster_context* ctx, shmif_pixel* vidp, + size_t pitch, int x, int y, size_t maxx, size_t maxy, shmif_pixel cc) +{ + struct cell cell = { + .fc = cc + }; + +/* blending might be a better option here .. */ + if (ctx->cursor_state & CURSOR_UNDER){ + drawborder_edge(ctx, &cell, vidp, pitch, x, y, maxx, maxy, CEATTR_BORDER_D); + } + else if (ctx->cursor_state & CURSOR_HOLLOW){ + drawborder_edge(ctx, &cell, vidp, pitch, x, y, maxx, maxy, + CEATTR_BORDER_D | CEATTR_BORDER_T | CEATTR_BORDER_L | CEATTR_BORDER_R); + } + else if (ctx->cursor_state & CURSOR_BAR){ + drawborder_edge(ctx, &cell, vidp, pitch, x, y, maxx, maxy, CEATTR_BORDER_L); + } +} + +static size_t drawglyph(struct tui_raster_context* ctx, struct cell* cell, + shmif_pixel* vidp, size_t pitch, int x, int y, size_t maxx, size_t maxy) +{ +/* draw glyph based on font state */ + bool draw_cursor = false; + + if (!ctx->fonts[0]->vector){ +/* other style option would be to swap CC and FC when drawing .. */ + if (cell->attr & CATTR_CURSOR){ + if (ctx->cursor_state == (CURSOR_ACTIVE | CURSOR_BLOCK)) + cell->bc = ctx->cc; + else + draw_cursor = true; + } + +/* linear search for cp, on fail, fill with background */ + tui_pixelfont_draw(ctx->fonts[0]->bitmap, + vidp, pitch, cell->ucs4, x, y, cell->fc, cell->bc, maxx, maxy, false); + +/* add line-marks */ + if (cell->ucs4 && + cell->attr & (CATTR_STRIKETHROUGH | CATTR_UNDERLINE)){ + linehint(ctx, cell, vidp, pitch, x, y, maxx, maxy, + cell->attr & CATTR_STRIKETHROUGH, + cell->attr & CATTR_UNDERLINE + ); + } + + drawborder_edge(ctx, cell, vidp, pitch, x, y, maxx, maxy, cell->attr_ext); + + if (draw_cursor){ + drawcursor_px(ctx, vidp, pitch, x, y, maxx, maxy, ctx->cc); + } + + return ctx->cell_w; + } + +/* vector font drawing */ + size_t nfonts = 1; + TTF_Font* fonts[2] = {ctx->fonts[0]->truetype, NULL}; + if (ctx->fonts[1]->vector && ctx->fonts[1]->truetype){ + nfonts = 2; + fonts[1] = ctx->fonts[1]->truetype; + } + +/* Clear to bg-color as the glyph drawing with background won't pad, except if + * it is the cursor color, then use that. We can't do the fg/bg swap as even in + * unshaped the glyph might be conditionally smaller than the cell size */ + shmif_pixel bc = cell->bc; + if (cell->attr & CATTR_CURSOR){ + if (ctx->cursor_state == (CURSOR_ACTIVE | CURSOR_BLOCK)){ + bc = ctx->cc; + } + else + draw_cursor = true; + } + + draw_box_px(vidp, + pitch, maxx, maxy, x, y, ctx->cell_w, ctx->cell_h, bc); + +/* fast-path, just clear to background and draw line attrs */ + if (!cell->ucs4){ + drawborder_edge(ctx, cell, vidp, pitch, x, y, maxx, maxy, cell->attr_ext); + if (draw_cursor){ + drawcursor_px(ctx, vidp, pitch, x, y, maxx, maxy, ctx->cc); + } + + return ctx->cell_w; + } + + int prem = TTF_STYLE_NORMAL; + prem |= TTF_STYLE_ITALIC * !!(cell->attr & CATTR_ITALIC); + prem |= TTF_STYLE_BOLD * !!(cell->attr & CATTR_BOLD); + +/* seriously expensive so only perform if we actually need to as it can cause a + * glyph cache flush (bold / italic / ...), other option would be to run + * separate glyph caches on the different style options.. */ + if (prem != ctx->last_style){ + ctx->last_style = prem; + TTF_SetFontStyle(fonts[0], prem); + if (fonts[1]) + TTF_SetFontStyle(fonts[1], prem); + } + + uint8_t fg[4], bg[4]; + SHMIF_RGBA_DECOMP(cell->fc, &fg[0], &fg[1], &fg[2], &fg[3]); + SHMIF_RGBA_DECOMP(bc, &bg[0], &bg[1], &bg[2], &bg[3]); + + /* these are mainly used as state machine for kernel / shaping, + * we need the 'x-start' position from the previous glyph and commit + * that to the line-offset table for coordinate translation */ + int adv = 0; + unsigned xs = 0; + unsigned ind = 0; + TTF_RenderUNICODEglyph(&vidp[y * pitch + x], + ctx->cell_w, ctx->cell_h, pitch, fonts, nfonts, cell->ucs4, &xs, + fg, bg, true, true, ctx->last_style, &adv, &ind + ); + +/* add line-marks, this actually does not belong here, it should be part of the + * style marker to the TTF_RenderUNICODEglyph - the code should be added as + * part of arcan_ttf.c was with the 'wavy' underline in alt color */ + if ( + cell->ucs4 && + cell->attr & (CATTR_STRIKETHROUGH | CATTR_UNDERLINE)) + { + linehint( + ctx, cell, vidp, pitch, x, y, maxx, maxy, + cell->attr & CATTR_STRIKETHROUGH, + cell->attr & CATTR_UNDERLINE + ); + } + + drawborder_edge(ctx, cell, vidp, pitch, x, y, maxx, maxy, cell->attr_ext); + if (draw_cursor){ + drawcursor_px(ctx, vidp, pitch, x, y, maxx, maxy, ctx->cc); + } + + return ctx->cell_w; +} + +static int raster_tobuf( + struct tui_raster_context* ctx, shmif_pixel* vidp, size_t pitch, + size_t max_w, size_t max_h, + uint16_t* x1, uint16_t* y1, uint16_t* x2, uint16_t* y2, + uint8_t* buf, size_t buf_sz) +{ + struct tui_raster_header hdr; + if (!buf_sz || buf_sz < sizeof(struct tui_raster_header)) + return -1; + + bool update = false; + memcpy(&hdr, buf, sizeof(struct tui_raster_header)); + bool extcursor = !!(hdr.cursor_state & CURSOR_EXTHDRv1); + +/* the caller might provide a larger input buffer than what the header sets, + * and that will still clamp/drop-out etc. but mismatch between the header + * fields is, of course, not permitted. */ + size_t hdr_ver_sz = hdr.lines * raster_line_sz + + hdr.cells * raster_cell_sz + raster_hdr_sz + + extcursor * 3; + + if (hdr.data_sz > buf_sz || hdr.data_sz != hdr_ver_sz){ + return -1; + } + + buf_sz -= sizeof(struct tui_raster_header); + buf += sizeof(struct tui_raster_header); + + if (extcursor){ + tui_raster_cursor_color(ctx, buf); + buf_sz -= 3; + buf += 3; + } + + shmif_pixel bgc = SHMIF_RGBA(hdr.bgc[0], hdr.bgc[1], hdr.bgc[2], hdr.bgc[3]); + +/* dframe, set 'always replaced' region */ + if (hdr.flags & RPACK_DFRAME){ + update = true; + *y1 = max_h; + *y2 = 0; + *x1 = max_w; + *x2 = 0; + +/* early out empty dframe */ + if (!hdr.lines) + return -1; + } +/* full-frame: pre-clear the pad region */ + else { + *x1 = 0; + *y1 = 0; + *x2 = max_w; + *y2 = max_h; + + size_t pad_w = max_w % ctx->cell_w; + size_t pad_h = max_h % ctx->cell_h; + + if (pad_w){ + size_t start = max_w - pad_w; + draw_box_px(vidp, pitch, max_w, max_h, start, 0, pad_w, max_h, bgc); + } + if (pad_h){ + size_t start = max_h - pad_h; + draw_box_px(vidp, pitch, max_w, max_h, 0, start, max_w, pad_h, bgc); + } + } + + ctx->cursor_state = hdr.cursor_state & (~CURSOR_EXTHDRv1); + + ssize_t cur_y = -1; + size_t last_line = 0; + size_t draw_y = 0; + + for (size_t i = 0; i < hdr.lines && buf_sz; i++){ + if (buf_sz < sizeof(struct tui_raster_line)) + return -1; + +/* read / unpack line metadata */ + struct tui_raster_line line; + + memcpy(&line, buf, sizeof(struct tui_raster_line)); + buf += sizeof(line); + +/* remember the lower line we were at, these are not always ordered */ + if (line.start_line > last_line) + last_line = line.start_line; + +/* respecting scrolling will need another drawing routine, as we need clipping + * etc. and multiple lines can be scrolled, and that's better fixed when we + * have an atlas to work from */ + if (update && cur_y == -1){ + *y1 = line.start_line * ctx->cell_h; + } + +/* skip omitted lines */ + if (cur_y != line.start_line){ +/* for full draw we fill in the skipped space with the background color */ + cur_y = line.start_line; + } + draw_y = cur_y * ctx->cell_h; + +/* the line- raster routine isn't right, we actually need to unpack each line + * into a local buffer, make note of actual offsets and width, and then two-pass + * with bg first and then blend the glyphs on top of that - otherwise kerning, + * shapes etc. looks bad. */ + if (draw_y < *y1){ + *y1 = draw_y; + } + +/* Shaping, BiDi, ... missing here now while we get the rest in place */ + size_t draw_x = line.offset * ctx->cell_w; + + if (draw_x < *x1){ + *x1 = draw_x; + } + + for (size_t i = line.offset; line.ncells && buf_sz >= raster_cell_sz; i++){ + line.ncells--; + +/* extract each cell */ + struct cell cell; + unpack_cell(buf, &cell, hdr.bgc[3]); + buf += raster_cell_sz; + buf_sz -= raster_cell_sz; + +/* outsource cursor? then invoke external - for more custom cursors that cover + * a larger area or multiple cursors on the same buffer, these need to be + * queued separately and drawn in another pass - though that queueing can be + * handled in the ext_cursor handler */ + if ((cell.attr & CATTR_CURSOR) && ctx->ext_cursor){ + uint8_t rgba[4]; + SHMIF_RGBA_DECOMP(ctx->cc, &rgba[0], &rgba[1], &rgba[2], &rgba[3]); + ctx->ext_cursor(ctx, + i, cur_y, draw_x, draw_y, ctx->cell_w, ctx->cell_h, + ctx->cursor_state, rgba, NULL + ); + + cell.attr &= ~CATTR_CURSOR; + } + +/* skip bit is set, note that for a shaped line, this means that + * we need to have an offset- map to advance correctly */ + if (cell.attr & CATTR_SKIP){ + draw_x += ctx->cell_w; + continue; + } + +/* blit or discard if OOB */ + if (draw_x + ctx->cell_w <= max_w && draw_y + ctx->cell_h <= max_h){ + draw_x += drawglyph(ctx, &cell, vidp, pitch, draw_x, draw_y, max_w, max_h); + } + else + continue; + + uint16_t next_x = draw_x + ctx->cell_w; + if (*x2 < next_x && next_x <= max_w){ + *x2 = next_x; + } + } + + cur_y++; + } + + *y2 = (last_line + 1) * ctx->cell_h; + + return 1; +} + +int tui_raster_render(struct tui_raster_context* ctx, + struct arcan_shmif_cont* dst, uint8_t* buf, size_t buf_sz) +{ + if (!ctx || !dst || !ctx->fonts[0] || buf_sz < sizeof(struct tui_raster_header)) + return -1; + +/* pixel- rasterization over shmif should work with one big BB until we have + * chain-mode. server-side, the vertex buffer slicing will just stream so not + * much to care about there */ + uint16_t x1, y1, x2, y2; + if (-1 == raster_tobuf(ctx, dst->vidp, dst->pitch, + dst->w, dst->h, &x1, &y1, &x2, &y2, buf, buf_sz)) + return -1; + + if (x2 > dst->w) + x2 = dst->w; + + arcan_shmif_dirty(dst, x1, y1, x2, y2, 0); + return 1; +} + +void tui_raster_offset( + struct tui_raster_context* ctx, size_t px_x, size_t row, size_t* offset) +{ + if (ctx->cell_w) + *offset = px_x; + else + *offset = px_x; +} + +/* + * Synch the raster state into the agp_store + * + * This is an intermediate step in doing this properly, i.e. just offloading + * the raster to the server side and go from there. The context still need to + * be built to handle / register fonts within though. + * + * A 'special' option here would be to return the offsets and widths into the + * buf during processing, as it will guaranteed fit - and the client side + * becomes easier as those won't need to be 'predicted'. + */ +#ifndef NO_ARCAN_AGP +int tui_raster_renderagp(struct tui_raster_context* ctx, + struct agp_vstore* dst, uint8_t* buf, size_t buf_sz, + struct stream_meta* out) +{ + if (!ctx || !dst || buf_sz < sizeof(struct tui_raster_header)) + return -1; + + uint16_t x1, y1, x2, y2; + + if (-1 == raster_tobuf(ctx, dst->vinf.text.raw, dst->w, + dst->w, dst->h, &x1, &y1, &x2, &y2, buf, buf_sz)){ + *out = (struct stream_meta){0}; + return -1; + } + else { + *out = (struct stream_meta){ + .buf = dst->vinf.text.raw, + .x1 = x1, .y1 = y1, .w = x2 - x1, .h = y2 - y1, + .dirty = true + }; + } + return 0; +} +#endif + +/* + * Free any buffers and resources bound to the raster + */ +void tui_raster_free(struct tui_raster_context* ctx) +{ + if (!ctx) + return; + + free(ctx); +} diff --git a/src/engine/arcan_vr.c b/src/engine/arcan_vr.c index cf05c1fa1..901ef3642 100644 --- a/src/engine/arcan_vr.c +++ b/src/engine/arcan_vr.c @@ -55,7 +55,7 @@ struct limb_ent { }; struct arcan_vr_ctx { - arcan_evctx* ctx; + struct arcan_evctx* ctx; arcan_frameserver* connection; uint64_t map; struct limb_ent limb_map[LIMB_LIM+1]; diff --git a/src/frameserver/avfeed/default/avfeed.c b/src/frameserver/avfeed/default/avfeed.c index c9aa4e58d..2d291ccad 100644 --- a/src/frameserver/avfeed/default/avfeed.c +++ b/src/frameserver/avfeed/default/avfeed.c @@ -47,7 +47,7 @@ int afsrv_avfeed(struct arcan_shmif_cont* con, struct arg_arr* args) return EXIT_FAILURE; } - update_frame(&shms, RGBA(0xff, 0xff, 0xff, 0xff)); + update_frame(&shms, SHMIF_RGBA(0xff, 0xff, 0xff, 0xff)); arcan_event ev; while(1) @@ -59,7 +59,7 @@ int afsrv_avfeed(struct arcan_shmif_cont* con, struct arg_arr* args) } else { static int red; - update_frame(&shms, RGBA(red++, 0x00, 0x00, 0xff)); + update_frame(&shms, SHMIF_RGBA(red++, 0x00, 0x00, 0xff)); } } } diff --git a/src/frameserver/decode/default/decode.h b/src/frameserver/decode/default/decode.h index 99fbcfdd5..59a07995c 100644 --- a/src/frameserver/decode/default/decode.h +++ b/src/frameserver/decode/default/decode.h @@ -1,3 +1,5 @@ +#include "frameserver.h" + /* dump the shared help and set the last_words for the context */ int show_use(struct arcan_shmif_cont* cont, const char* msg); diff --git a/src/frameserver/decode/default/decode_av.c b/src/frameserver/decode/default/decode_av.c index d105f96bc..2aec2f4a4 100644 --- a/src/frameserver/decode/default/decode_av.c +++ b/src/frameserver/decode/default/decode_av.c @@ -193,11 +193,11 @@ static void generate_frame() * data-channel and new context */ for (int j=0; j #include #include "arcan_tuisym.h" +#include "frameserver.h" enum pack_format { PACK_MONO = 0, diff --git a/src/frameserver/decode/default/decode_text.c b/src/frameserver/decode/default/decode_text.c index efeaf0cd0..28013f436 100644 --- a/src/frameserver/decode/default/decode_text.c +++ b/src/frameserver/decode/default/decode_text.c @@ -8,6 +8,7 @@ #include #include +#include #include "decode.h" diff --git a/src/frameserver/encode/default/a12.c b/src/frameserver/encode/default/a12.c index a6d1860da..ae49adf84 100644 --- a/src/frameserver/encode/default/a12.c +++ b/src/frameserver/encode/default/a12.c @@ -6,6 +6,7 @@ #include #include +#include "frameserver.h" #include "a12.h" diff --git a/src/frameserver/encode/default/img.c b/src/frameserver/encode/default/img.c index 52fc91f7c..004dd21af 100644 --- a/src/frameserver/encode/default/img.c +++ b/src/frameserver/encode/default/img.c @@ -1,5 +1,8 @@ /* for png- output mode */ #include + +typedef uint32_t av_pixel; +typedef int8_t arcan_errc; #include "arcan_img.h" void png_stream_run(struct arg_arr* args, struct arcan_shmif_cont cont) diff --git a/src/frameserver/encode/default/ocr.c b/src/frameserver/encode/default/ocr.c index 0590750d1..d282f91c9 100644 --- a/src/frameserver/encode/default/ocr.c +++ b/src/frameserver/encode/default/ocr.c @@ -1,6 +1,9 @@ #include #include #include + +#include +#include "frameserver.h" #include "util/utf8.c" static void repack_run(struct arcan_shmif_cont* cont, TessBaseAPI* handle) diff --git a/src/frameserver/encode/default/v4l.c b/src/frameserver/encode/default/v4l.c index 96761b175..ebcd6777c 100644 --- a/src/frameserver/encode/default/v4l.c +++ b/src/frameserver/encode/default/v4l.c @@ -17,6 +17,7 @@ #include #include #include +#include "frameserver.h" extern void arcan_timesleep(unsigned long); static int try_device(struct arcan_shmif_cont* C, int number, struct v4l2_format* fmt) diff --git a/src/frameserver/encode/default/vnc.c b/src/frameserver/encode/default/vnc.c index 312435349..71bb5fb9a 100644 --- a/src/frameserver/encode/default/vnc.c +++ b/src/frameserver/encode/default/vnc.c @@ -17,6 +17,7 @@ #include #include +#include "frameserver.h" #define DEFINE_XKB #include "xsymconv.h" diff --git a/src/frameserver/frameserver.h b/src/frameserver/frameserver.h index 72348f2fe..281d605ee 100644 --- a/src/frameserver/frameserver.h +++ b/src/frameserver/frameserver.h @@ -81,6 +81,13 @@ int afsrv_avfeed(struct arcan_shmif_cont*, struct arg_arr*); int afsrv_netcl(struct arcan_shmif_cont*, struct arg_arr*); int afsrv_netsrv(struct arcan_shmif_cont*, struct arg_arr*); +#ifndef COUNT_OF +#define COUNT_OF(x) \ + ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) +#endif + +unsigned long long arcan_timemillis(); + #ifndef LOG #define LOG(...) (fprintf(stderr, __VA_ARGS__)) #endif diff --git a/src/frameserver/game/default/libretro.c b/src/frameserver/game/default/libretro.c index 479715baa..53d3f87a1 100644 --- a/src/frameserver/game/default/libretro.c +++ b/src/frameserver/game/default/libretro.c @@ -5,6 +5,7 @@ */ #define AGP_ENABLE_UNPURE 1 +#define BADFD -1 #include #include @@ -21,14 +22,9 @@ #include #include -#ifdef FRAMESERVER_LIBRETRO_3D -#ifdef ENABLE_RETEXTURE -#include "retexture.h" -#endif +#define WANT_ARCAN_SHMIF_HELPER #include "video_platform.h" #include "platform.h" -#define WANT_ARCAN_SHMIF_HELPER -#endif #include #include @@ -216,8 +212,8 @@ retro_proc_address_t libretro_requirefun(const char* sym) return dlsym(lastlib, sym); } -static bool write_handle(const void* const data, - size_t sz_data, file_handle dst, bool finalize) +static bool write_handle( + const void* const data, size_t sz_data, int dst, bool finalize) { bool rv = false; @@ -375,7 +371,7 @@ static void libretro_rgb565_rgba(const uint16_t* data, shmif_pixel* outp, if (retro.ntscconv) *interm++ = RGB565(r, g, b); else - *outp++ = RGBA(r, g, b, 0xff); + *outp++ = SHMIF_RGBA(r, g, b, 0xff); } data += pitch >> 1; } @@ -400,7 +396,7 @@ static void libretro_xrgb888_rgba(const uint32_t* data, uint32_t* outp, if (retro.ntscconv) *interm++ = RGB565(quad[2], quad[1], quad[0]); else - *outp++ = RGBA(quad[2], quad[1], quad[0], 0xff); + *outp++ = SHMIF_RGBA(quad[2], quad[1], quad[0], 0xff); } data += pitch >> 2; @@ -429,7 +425,7 @@ static void libretro_rgb1555_rgba(const uint16_t* data, uint32_t* outp, if (postfilter) *interm++ = RGB565(r, g, b); else - *outp++ = RGBA(r, g, b, 0xff); + *outp++ = SHMIF_RGBA(r, g, b, 0xff); } data += pitch >> 1; diff --git a/src/frameserver/net/default/net.c b/src/frameserver/net/default/net.c index ddec7e77b..72589286e 100644 --- a/src/frameserver/net/default/net.c +++ b/src/frameserver/net/default/net.c @@ -10,11 +10,6 @@ #include #define KEYSTORE_ERRMSG "couldn't open keystore" -#ifndef COUNT_OF -#define COUNT_OF(x) \ - ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) -#endif - #include #include #include @@ -23,12 +18,14 @@ #include #include #include +#include #include "a12.h" #include "a12_int.h" #include "net/a12_helper.h" #include "../../util/anet_helper.h" #include "net/directory.h" +#include "frameserver.h" enum trust { TRUST_KNOWN, diff --git a/src/frameserver/terminal/default/cli_builtin.c b/src/frameserver/terminal/default/cli_builtin.c index 78d1511b9..ff35e7732 100644 --- a/src/frameserver/terminal/default/cli_builtin.c +++ b/src/frameserver/terminal/default/cli_builtin.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "cli_builtin.h" struct cmd_state { diff --git a/src/frameserver/terminal/default/cli_lua.c b/src/frameserver/terminal/default/cli_lua.c index 4a6138378..5c140fcf2 100644 --- a/src/frameserver/terminal/default/cli_lua.c +++ b/src/frameserver/terminal/default/cli_lua.c @@ -6,10 +6,13 @@ #include #include #include +#include #include "tui_lua.h" #include "lash.h" +unsigned long long arcan_timemillis(); + /* * notes: * diff --git a/src/frameserver/util/anet_keystore_naive.c b/src/frameserver/util/anet_keystore_naive.c index 4e25c3ba2..083a5491b 100644 --- a/src/frameserver/util/anet_keystore_naive.c +++ b/src/frameserver/util/anet_keystore_naive.c @@ -27,8 +27,8 @@ #endif #include "anet_helper.h" - #include "external/x25519.h" +void arcan_random(uint8_t* dst, size_t sz); struct key_ent; diff --git a/src/frameserver/util/sync_plot.c b/src/frameserver/util/sync_plot.c index 9cfc0e5bc..121a659b4 100644 --- a/src/frameserver/util/sync_plot.c +++ b/src/frameserver/util/sync_plot.c @@ -20,6 +20,8 @@ #define GRAPH_BUFFER_SIZE 160 #endif +unsigned long long arcan_timemillis(); + struct graph_int { struct arcan_shmif_cont* cont; @@ -35,7 +37,7 @@ struct graph_int { #define stepmsg(ctx, x, yv) \ draw_box(ctx, 0, yv, fontw * strlen(x),\ - fonth, RGBA(0x00, 0x00, 0x00, 0xff));\ + fonth, SHMIF_RGBA(0x00, 0x00, 0x00, 0xff));\ draw_text(ctx, x, 0, yv, 0xffffffff);\ yv += fonth; @@ -64,8 +66,8 @@ static bool f_update(struct synch_graphing* ctx, float period, const char* msg) * with the next intended frame, horizontal resolution is 2 px / ms */ size_t dw = priv->cont->addr->w; - draw_box(priv->cont, 0, yv, dw, fonth * 2, RGBA(0x00, 0x00, 0x00, 0xff)); - draw_box(priv->cont, 0, yv + fonth, dw, 1, RGBA(0x99, 0x99, 0x99, 0xff)); + draw_box(priv->cont, 0, yv, dw, fonth * 2, SHMIF_RGBA(0x00, 0x00, 0x00, 0xff)); + draw_box(priv->cont, 0, yv + fonth, dw, 1, SHMIF_RGBA(0x99, 0x99, 0x99, 0xff)); /* first, ideal deadlines, now() is at the end of the X scale */ int stepc = 0; @@ -76,7 +78,7 @@ static bool f_update(struct synch_graphing* ctx, float period, const char* msg) while ( startp - (stepc * period) >= minp ){ draw_box(priv->cont, startp - (stepc * period) - minp, - yv, 1, fonth-1, RGBA(0x00, 0xff, 0x00, 0xff)); + yv, 1, fonth-1, SHMIF_RGBA(0x00, 0xff, 0x00, 0xff)); stepc++; } @@ -92,14 +94,14 @@ static bool f_update(struct synch_graphing* ctx, float period, const char* msg) while (true){ if (priv->frametimes[ofs] >= minp) draw_box(priv->cont, current - priv->frametimes[ofs], - yv + 1, 1, fonth - 1, RGBA(0xff, 0xff, 0x00, 0xff)); + yv + 1, 1, fonth - 1, SHMIF_RGBA(0xff, 0xff, 0x00, 0xff)); else break; ofs = STEPBACK(ofs); if (priv->frametimes[ofs] >= minp) draw_box(priv->cont, current - priv->frametimes[ofs], - yv + 1, 1, fonth - 1, RGBA(0xaa, 0xaa, 0x00, 0xff)); + yv + 1, 1, fonth - 1, SHMIF_RGBA(0xaa, 0xaa, 0x00, 0xff)); else break; @@ -111,7 +113,7 @@ static bool f_update(struct synch_graphing* ctx, float period, const char* msg) while (priv->framedrops[ofs] >= minp){ draw_box(priv->cont, current- priv->framedrops[ofs], - yv + 1, 1, fonth - 1, RGBA(0xff, 0x00, 0x00, 0xff)); + yv + 1, 1, fonth - 1, SHMIF_RGBA(0xff, 0x00, 0x00, 0xff)); ofs = STEPBACK(ofs); } @@ -134,7 +136,7 @@ static bool f_update(struct synch_graphing* ctx, float period, const char* msg) float yscale = (float)(fonth * 2) / (float) maxv; ofs = STEPBACK(priv->ofs_xfer); count = 0; - draw_box(priv->cont, 0, yv, dw, fonth * 2, RGBA(0x00, 0x00, 0x00, 0xff)); + draw_box(priv->cont, 0, yv, dw, fonth * 2, SHMIF_RGBA(0x00, 0x00, 0x00, 0xff)); while (count < dw){ int sample = priv->xfercosts[ofs]; @@ -142,11 +144,11 @@ static bool f_update(struct synch_graphing* ctx, float period, const char* msg) if (sample > -1){ size_t lineh = yscale * sample; draw_box(priv->cont, dw - count - 1, - yv + fonth * 2 - lineh, 1, lineh, RGBA(0x00, 0xff, 0x00, 0xff)); + yv + fonth * 2 - lineh, 1, lineh, SHMIF_RGBA(0x00, 0xff, 0x00, 0xff)); } else{ draw_box(priv->cont, dw - count - 1, yv, - 1, fonth * 2, RGBA(0x00, 0x00, 0xff, 0xff)); + 1, fonth * 2, SHMIF_RGBA(0x00, 0x00, 0xff, 0xff)); } ofs = STEPBACK(ofs); diff --git a/src/platform/agp/stub.c b/src/platform/agp/stub.c index ae7ce4570..fd09a431f 100644 --- a/src/platform/agp/stub.c +++ b/src/platform/agp/stub.c @@ -1,4 +1,4 @@ - * License: 3-Clause BSD, see COPYING file in arcan source repository. +/* License: 3-Clause BSD, see COPYING file in arcan source repository. * Reference: http://arcan-fe.com */ @@ -9,9 +9,8 @@ #include #include -#include "../platform_types.h" #include "../video_platform.h" -#include "../platform.h" +#include PLATFORM_HEADER #include "arcan_math.h" #include "arcan_general.h" @@ -141,9 +140,36 @@ void agp_activate_vstore_multi(struct agp_vstore** backing, size_t n) { } +struct agp_vstore* + agp_rendertarget_swap(struct agp_rendertarget* dst, bool* swap) +{ + return NULL; +} + +void agp_rendertarget_allocator(struct agp_rendertarget* tgt, bool (*handler)( + struct agp_rendertarget*, struct agp_vstore*, int action, void* tag), void* tag) +{ +} + +struct agp_fenv* agp_env() +{ + return NULL; +} + +void agp_vstore_copyreg( + struct agp_vstore* restrict src, struct agp_vstore* restrict dst, + size_t x1, size_t y1, size_t x2, size_t y2) +{ +} + +bool agp_rendertarget_swapstore( + struct agp_rendertarget* tgt, struct agp_vstore* vstore) +{ + return false; +} + void agp_update_vstore(struct agp_vstore* s, bool copy) { - FLAG_DIRTY(); } void agp_prepare_stencil() diff --git a/src/platform/arcan/video.c b/src/platform/arcan/video.c index 49ea43322..0bfeba476 100644 --- a/src/platform/arcan/video.c +++ b/src/platform/arcan/video.c @@ -33,6 +33,7 @@ #include #include #include +#include extern jmp_buf arcanmain_recover_state; @@ -98,6 +99,8 @@ static struct egl_env agp_eglenv; #define verbose_print #endif +struct arcan_evctx; + static char* input_envopts[] = { NULL }; @@ -146,7 +149,7 @@ struct display { } disp[MAX_DISPLAYS] = {0}; static struct arg_arr* shmarg; -static bool event_process_disp(arcan_evctx* ctx, struct display* d, size_t i); +static bool event_process_disp(struct arcan_evctx* ctx, struct display* d, size_t i); static struct { uint64_t magic; @@ -1086,8 +1089,8 @@ const char* platform_event_devlabel(int devid) * The better option is to expose them as _adopt handlers, similar * to how we do stdin/stdout mapping. */ -static void map_window( - struct arcan_shmif_cont* seg, arcan_evctx* ctx, int kind, const char* key) +static void map_window(struct arcan_shmif_cont* seg, + struct arcan_evctx* ctx, int kind, const char* key) { if (kind != SEGID_MEDIA) return; @@ -1298,7 +1301,8 @@ static bool scan_subseg(arcan_tgtevent* ev, bool ok) * return true if the segment has expired */ extern struct arcan_luactx* main_lua_context; -static bool event_process_disp(arcan_evctx* ctx, struct display* d, size_t did) +static bool event_process_disp( + struct arcan_evctx* ctx, struct display* d, size_t did) { if (!d->conn.addr) return true; @@ -1494,7 +1498,7 @@ static bool event_process_disp(arcan_evctx* ctx, struct display* d, size_t did) return false; } -void platform_event_keyrepeat(arcan_evctx* ctx, int* period, int* delay) +void platform_event_keyrepeat(struct arcan_evctx* ctx, int* period, int* delay) { *period = 0; *delay = 0; @@ -1503,7 +1507,7 @@ void platform_event_keyrepeat(arcan_evctx* ctx, int* period, int* delay) * keyboard device (track per devid) and emit that every oh so often */ } -void platform_event_process(arcan_evctx* ctx) +void platform_event_process(struct arcan_evctx* ctx) { bool locked = primary_udata.signal_pending; primary_udata.signal_pending = false; @@ -1547,7 +1551,7 @@ void platform_event_process(arcan_evctx* ctx) } } -void platform_event_rescan_idev(arcan_evctx* ctx) +void platform_event_rescan_idev(struct arcan_evctx* ctx) { } @@ -1560,11 +1564,11 @@ enum PLATFORM_EVENT_CAPABILITIES platform_event_capabilities(const char** out) ACAP_POSITION | ACAP_ORIENTATION; } -void platform_key_repeat(arcan_evctx* ctx, unsigned int rate) +void platform_key_repeat(struct arcan_evctx* ctx, unsigned int rate) { } -void platform_event_deinit(arcan_evctx* ctx) +void platform_event_deinit(struct arcan_evctx* ctx) { TRACE_MARK_ONESHOT("event", "event-platform-deinit", TRACE_SYS_DEFAULT, 0, 0, "lwa"); } @@ -1577,7 +1581,7 @@ void platform_video_recovery() }; TRACE_MARK_ONESHOT("video", "video-platform-recovery", TRACE_SYS_DEFAULT, 0, 0, "lwa"); - arcan_evctx* evctx = arcan_event_defaultctx(); + struct arcan_evctx* evctx = arcan_event_defaultctx(); arcan_event_enqueue(evctx, &ev); for (size_t i = 0; i < MAX_DISPLAYS; i++){ @@ -1588,7 +1592,7 @@ void platform_video_recovery() } } -void platform_event_reset(arcan_evctx* ctx) +void platform_event_reset(struct arcan_evctx* ctx) { TRACE_MARK_ONESHOT("event", "event-platform-reset", TRACE_SYS_DEFAULT, 0, 0, "lwa"); platform_event_deinit(ctx); @@ -1598,7 +1602,7 @@ void platform_device_lock(int devind, bool state) { } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { TRACE_MARK_ONESHOT("event", "event-platform-init", TRACE_SYS_DEFAULT, 0, 0, "lwa"); } diff --git a/src/platform/egl-dri/video.c b/src/platform/egl-dri/video.c index f3bfa7c35..71919c5a3 100644 --- a/src/platform/egl-dri/video.c +++ b/src/platform/egl-dri/video.c @@ -3273,7 +3273,7 @@ void platform_video_recovery() .vid.ledctrl = egl_dri.ledid }; debug_print("video_recovery, injecting 'added' for mapped displays"); - arcan_evctx* evctx = arcan_event_defaultctx(); + struct arcan_evctx* evctx = arcan_event_defaultctx(); arcan_event_enqueue(evctx, &ev); for (size_t i = 0; i < MAX_DISPLAYS; i++){ diff --git a/src/platform/egl-gles/video.c b/src/platform/egl-gles/video.c index 0a1c80c70..70abd32c2 100644 --- a/src/platform/egl-gles/video.c +++ b/src/platform/egl-gles/video.c @@ -431,6 +431,18 @@ bool PLATFORM_SYMBOL(_video_get_display_gamma)(platform_display_id did, return false; } +bool PLATFORM_SYMBOL(_video_map_buffer)( + struct agp_vstore* vs, struct agp_buffer_plane* planes, size_t n_planes) +{ + return false; +} + +size_t PLATFORM_SYMBOL(_video_export_vstore)( + struct agp_vstore* vs, struct agp_buffer_plane* planes, size_t n) +{ + return 0; +} + void PLATFORM_SYMBOL(_video_prepare_external) () {} void PLATFORM_SYMBOL(_video_restore_external) () {} void PLATFORM_SYMBOL(_video_shutdown) () diff --git a/src/platform/evdev/event.c b/src/platform/evdev/event.c index ff8328e17..0f94d05dd 100644 --- a/src/platform/evdev/event.c +++ b/src/platform/evdev/event.c @@ -2101,7 +2101,7 @@ void platform_event_preinit() { } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { uintptr_t tag; diff --git a/src/platform/event_platform.h b/src/platform/event_platform.h index e5a86a174..51359417c 100644 --- a/src/platform/event_platform.h +++ b/src/platform/event_platform.h @@ -1,5 +1,7 @@ #ifndef HAVE_EVENT_PLATFORM #define HAVE_EVENT_PLATFORM +#include "../shmif/arcan_shmif_event.h" +#include "../shmif/platform/shmif_platform.h" /* * get a NULL terminated list of input- platform specific environment options diff --git a/src/platform/headless/event.c b/src/platform/headless/event.c index 0a661c436..f76a41993 100644 --- a/src/platform/headless/event.c +++ b/src/platform/headless/event.c @@ -56,16 +56,16 @@ int platform_event_device_request(int space, const char* path) } extern int headless_flush_encode_events(); -void platform_event_process(arcan_evctx* ctx) +void platform_event_process(struct arcan_evctx* ctx) { headless_flush_encode_events(); } -void platform_event_keyrepeat(arcan_evctx* ctx, int* rate, int* del) +void platform_event_keyrepeat(struct arcan_evctx* ctx, int* rate, int* del) { } -void platform_event_rescan_idev(arcan_evctx* ctx) +void platform_event_rescan_idev(struct arcan_evctx* ctx) { } @@ -83,11 +83,11 @@ const char** platform_event_envopts() return (const char**) envopts; } -void platform_event_deinit(arcan_evctx* ctx) +void platform_event_deinit(struct arcan_evctx* ctx) { } -void platform_event_reset(arcan_evctx* ctx) +void platform_event_reset(struct arcan_evctx* ctx) { platform_event_deinit(ctx); } @@ -100,6 +100,6 @@ void platform_event_preinit() { } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { } diff --git a/src/platform/platform.h b/src/platform/platform.h index 8f0c46803..a7617afc7 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -12,6 +12,7 @@ #ifndef HAVE_PLATFORM_HEADER #define HAVE_PLATFORM_HEADER +#include #include "platform_types.h" #include "agp_platform.h" #include "video_platform.h" diff --git a/src/platform/posix/frameserver.c b/src/platform/posix/frameserver.c index ce2078ee7..e02ac3052 100644 --- a/src/platform/posix/frameserver.c +++ b/src/platform/posix/frameserver.c @@ -31,6 +31,9 @@ #include #include +#include "../shmif/arcan_shmif_event.h" +#include "../shmif/platform/shmif_platform.h" + #include #include #include @@ -39,6 +42,7 @@ #include #include + #define INCR(X, C) ( ( (X) = ( (X) + 1) % (C)) ) #ifndef FORCE_SYNCH @@ -141,9 +145,9 @@ static size_t shmpage_size(size_t w, size_t h, static void fsrv_setevqs( struct arcan_shmif_page* dst, sem_handle esem, - arcan_evctx* inq, arcan_evctx* outq) + struct arcan_evctx* inq, struct arcan_evctx* outq) { - arcan_evctx* tmp = inq; + struct arcan_evctx* tmp = inq; inq = outq; outq = tmp; diff --git a/src/platform/posix/fsrv_guard.c b/src/platform/posix/fsrv_guard.c index fa3b0e8c4..fa637f1f6 100644 --- a/src/platform/posix/fsrv_guard.c +++ b/src/platform/posix/fsrv_guard.c @@ -4,38 +4,22 @@ * Reference: http://arcan-fe.com */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "arcan_shmif.h" +#include PLATFORM_HEADER -#include -#include -#include -#include -#include -#include -#include -#include +#include "platform/shmif_platform.h" +#include "arcan_shmif_server.h" -#include #include -#include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include +#include "arcan_math.h" +#include "arcan_general.h" +#include "arcan_frameserver.h" static struct arcan_frameserver* tag; static sigjmp_buf recover; diff --git a/src/platform/sdl/SDLMain.h b/src/platform/sdl/SDLMain.h deleted file mode 100644 index 4683df57a..000000000 --- a/src/platform/sdl/SDLMain.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - -@interface SDLMain : NSObject -@end diff --git a/src/platform/sdl/SDLmain.m b/src/platform/sdl/SDLmain.m deleted file mode 100644 index 2434f81aa..000000000 --- a/src/platform/sdl/SDLmain.m +++ /dev/null @@ -1,381 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#include "SDL.h" -#include "SDLMain.h" -#include /* for MAXPATHLEN */ -#include - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - const NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface NSApplication (SDLApplication) -@end - -@implementation NSApplication (SDLApplication) -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { - chdir(parentdir); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [NSApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [NSApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/src/platform/sdl/event.c b/src/platform/sdl/event.c deleted file mode 100644 index b6c8ebc79..000000000 --- a/src/platform/sdl/event.c +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Copyright 2003-2016, Björn Ståhl - * License: 3-Clause BSD, see COPYING file in arcan source repository. - * Reference: http://arcan-fe.com - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -static const char* envopts[] = -{ - NULL -}; - -const char** platform_event_envopts() -{ - return (const char**) envopts; -} - -struct axis_opts { -/* none, avg, drop */ - enum ARCAN_ANALOGFILTER_KIND mode; - enum ARCAN_ANALOGFILTER_KIND oldmode; - - int lower, upper, deadzone; - -/* we won't get access to a good range distribution - * if we don't emit the first / last sample that got - * into the drop range */ - bool inlzone, inuzone, indzone; - - int kernel_sz; - int kernel_ofs; - int32_t flt_kernel[64]; -}; - -static struct { - struct axis_opts mx, my, mx_r, my_r; - bool sticks_init; - unsigned short n_joy; - struct arcan_stick* joys; -} iodev = {0}; - -struct arcan_stick { -/* if we can get a repeatable identifier to expose - * to higher layers in order to retain / track settings - * for a certain device, put that here */ - char label[256]; - bool tagged; - - SDL_Joystick* handle; - - unsigned long hashid; - - unsigned short devnum; - unsigned short axis; - -/* these map to digital events */ - unsigned short buttons; - unsigned short balls; - - unsigned* hattbls; - unsigned short hats; - - struct axis_opts* adata; -}; - -static int find_devind(int devnum) -{ - for (int i = 0; i < iodev.n_joy; i++){ - if (iodev.joys[i].devnum == devnum){ - return i; - } - } - return -1; -} - -static inline bool process_axis(arcan_evctx* ctx, - struct axis_opts* daxis, int16_t samplev, int16_t* outv) -{ - if (daxis->mode == ARCAN_ANALOGFILTER_NONE) - return false; - - if (daxis->mode == ARCAN_ANALOGFILTER_PASS) - goto accept_sample; - -/* quickfilter deadzone */ - if (abs(samplev) < daxis->deadzone){ - if (!daxis->indzone){ - samplev = 0; - daxis->indzone = true; - } - else - return false; - } - else - daxis->indzone = false; - -/* quickfilter out controller edgenoise */ - if (samplev < daxis->lower){ - if (!daxis->inlzone){ - samplev = daxis->lower; - daxis->inlzone = true; - daxis->inuzone = false; - } - else - return false; - } - else if (samplev > daxis->upper){ - if (!daxis->inuzone){ - samplev = daxis->upper; - daxis->inuzone = true; - daxis->inlzone = false; - } - else - return false; - } - else - daxis->inlzone = daxis->inuzone = false; - - daxis->flt_kernel[ daxis->kernel_ofs++ ] = samplev; - -/* don't proceed until the kernel is filled */ - if (daxis->kernel_ofs < daxis->kernel_sz) - return false; - - if (daxis->kernel_sz > 1){ - int32_t tot = 0; - - if (daxis->mode == ARCAN_ANALOGFILTER_ALAST){ - samplev = daxis->flt_kernel[daxis->kernel_sz - 1]; - } - else { - for (int i = 0; i < daxis->kernel_sz; i++) - tot += daxis->flt_kernel[i]; - - samplev = tot != 0 ? tot / daxis->kernel_sz : 0; - } - - } - else; - daxis->kernel_ofs = 0; - -accept_sample: - *outv = samplev; - return true; -} - -static inline void process_axismotion(arcan_evctx* ctx, - const SDL_JoyAxisEvent* const ev) -{ - int devid = ev->which; - - if (!iodev.joys || iodev.joys[devid].axis < ev->axis) - return; - - struct axis_opts* daxis = &iodev.joys[devid].adata[ev->axis]; - int16_t dstv; - - if (process_axis(ctx, daxis, ev->value, &dstv)){ - arcan_event newevent = { - .category = EVENT_IO, - .io.kind = EVENT_IO_AXIS_MOVE, - .io.devid = iodev.joys[devid].devnum, - .io.subid = ev->axis, - .io.datatype = EVENT_IDATATYPE_ANALOG, - .io.devkind = EVENT_IDEVKIND_GAMEDEV, - .io.input.analog.gotrel = false, - .io.input.analog.nvalues = 1, - .io.input.analog.axisval[0] = dstv - }; - arcan_event_enqueue(ctx, &newevent); - } -} - -void platform_event_samplebase(int devid, float xyz[3]) -{ - if (0 == devid) - SDL_WarpMouse(xyz[0], xyz[1]); -} - -static inline void process_mousemotion(arcan_evctx* ctx, - const SDL_MouseMotionEvent* const ev) -{ - int16_t dstv, dstv_r; - arcan_event nev = { - .category = EVENT_IO, - .io.label = "MOUSE\0", - .io.kind = EVENT_IO_AXIS_MOVE, - .io.datatype = EVENT_IDATATYPE_ANALOG, - .io.devkind = EVENT_IDEVKIND_MOUSE, - .io.devid = 0, - .io.input.analog.gotrel = false, - .io.input.analog.nvalues = 2 - }; - - snprintf(nev.io.label, sizeof(nev.io.label) - 1, "mouse"); - - if (process_axis(ctx, &iodev.mx, ev->x, &dstv) && - process_axis(ctx, &iodev.mx_r, ev->xrel, &dstv_r)){ - nev.io.subid = 0; - nev.io.input.analog.axisval[0] = dstv; - nev.io.input.analog.axisval[1] = dstv_r; - arcan_event_enqueue(ctx, &nev); - } - - if (process_axis(ctx, &iodev.my, ev->y, &dstv) && - process_axis(ctx, &iodev.my_r, ev->yrel, &dstv_r)){ - nev.io.subid = 1; - nev.io.input.analog.axisval[0] = dstv; - nev.io.input.analog.axisval[1] = dstv_r; - arcan_event_enqueue(ctx, &nev); - } -} - -static void set_analogstate(struct axis_opts* dst, - int lower_bound, int upper_bound, int deadzone, - int kernel_size, enum ARCAN_ANALOGFILTER_KIND mode) -{ - dst->lower = lower_bound; - dst->upper = upper_bound; - dst->deadzone = deadzone; - dst->kernel_sz = kernel_size; - dst->mode = mode; - dst->kernel_ofs = 0; -} - -arcan_errc platform_event_analogstate(int devid, int axisid, - int* lower_bound, int* upper_bound, int* deadzone, - int* kernel_size, enum ARCAN_ANALOGFILTER_KIND* mode) -{ -/* special case, mouse */ - if (devid == -1){ - if (axisid == 0){ - *lower_bound = iodev.mx.lower; - *upper_bound = iodev.mx.upper; - *deadzone = iodev.mx.deadzone; - *kernel_size = iodev.mx.kernel_sz; - *mode = iodev.mx.mode; - } - else if (axisid == 1){ - *lower_bound = iodev.my.lower; - *upper_bound = iodev.my.upper; - *deadzone = iodev.my.deadzone; - *kernel_size = iodev.my.kernel_sz; - *mode = iodev.my.mode; - } - else - return ARCAN_ERRC_BAD_RESOURCE; - - return true; - } - - int jind = find_devind(devid); - - if (devid < 0 || -1 == jind) - return ARCAN_ERRC_NO_SUCH_OBJECT; - - - if (!iodev.joys || axisid >= iodev.joys[jind].axis) - return ARCAN_ERRC_BAD_RESOURCE; - - struct axis_opts* daxis = &iodev.joys[jind].adata[axisid]; - *mode = daxis->mode; - *lower_bound = daxis->lower; - *upper_bound = daxis->upper; - *deadzone = daxis->deadzone; - *kernel_size = daxis->kernel_sz; - - return ARCAN_OK; -} - -void platform_event_analogall(bool enable, bool mouse) -{ - if (mouse){ - if (enable){ - iodev.mx.mode = iodev.mx.oldmode; - iodev.my.mode = iodev.my.oldmode; - iodev.mx_r.mode = iodev.mx_r.oldmode; - iodev.my_r.mode = iodev.my_r.oldmode; - } else { - iodev.mx.oldmode = iodev.mx.mode; - iodev.mx.mode = ARCAN_ANALOGFILTER_NONE; - iodev.my.oldmode = iodev.mx.mode; - iodev.my.mode = ARCAN_ANALOGFILTER_NONE; - iodev.mx_r.oldmode = iodev.mx.mode; - iodev.mx_r.mode = ARCAN_ANALOGFILTER_NONE; - iodev.my_r.oldmode = iodev.mx.mode; - iodev.my_r.mode = ARCAN_ANALOGFILTER_NONE; - } - } - - if (iodev.joys){ - for (int i = 0; i < iodev.n_joy; i++) - for (int j = 0; j < iodev.joys[i].axis; j++) - if (enable){ - if (iodev.joys[i].adata[j].oldmode == ARCAN_ANALOGFILTER_NONE) - iodev.joys[i].adata[j].mode = ARCAN_ANALOGFILTER_AVG; - else - iodev.joys[i].adata[j].mode = iodev.joys[i].adata[j].oldmode; - } - else { - iodev.joys[i].adata[j].oldmode = iodev.joys[i].adata[j].mode; - iodev.joys[i].adata[j].mode = ARCAN_ANALOGFILTER_NONE; - } - } -} - -void platform_event_analogfilter(int devid, - int axisid, int lower_bound, int upper_bound, int deadzone, - int buffer_sz, enum ARCAN_ANALOGFILTER_KIND kind) -{ - struct axis_opts opt; - int kernel_lim = sizeof(opt.flt_kernel) / sizeof(opt.flt_kernel[0]); - - if (buffer_sz > kernel_lim) - buffer_sz = kernel_lim; - - if (buffer_sz <= 0) - buffer_sz = 1; - - if (devid == -1) - goto setmouse; - - int jind = find_devind(devid); - - if (devid < 0 || -1 == jind) - return; - - if (axisid < 0 || axisid >= iodev.joys[jind].axis) - return; - - struct axis_opts* daxis = &iodev.joys[jind].adata[axisid]; - - if (0){ -setmouse: - if (axisid == 0){ - set_analogstate(&iodev.mx, lower_bound, - upper_bound, deadzone, buffer_sz, kind); - set_analogstate(&iodev.mx_r, lower_bound, - upper_bound, deadzone, buffer_sz, kind); - } - else if (axisid == 1){ - set_analogstate(&iodev.my, lower_bound, - upper_bound, deadzone, buffer_sz, kind); - set_analogstate(&iodev.my_r, lower_bound, - upper_bound, deadzone, buffer_sz, kind); - } - return; - } - - set_analogstate(daxis, lower_bound, - upper_bound, deadzone, buffer_sz, kind); -} - -static unsigned long djb_hash(const char* str) -{ - unsigned long hash = 5381; - int c; - - while ((c = *(str++))) - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - - return hash; -} -static char* to_utf8(uint16_t utf16, uint8_t out[4]) -{ - int count = 1, ofs = 0; - uint32_t mask = 0x800; - - if (utf16 >= 0x80) - count++; - - for(size_t i=0; i < 5; i++){ - if ( (uint32_t) utf16 >= mask ) - count++; - - mask <<= 5; - } - - if (count == 1){ - out[0] = (char) utf16; - out[1] = 0x00; - } - else { - for (int i = (count-1 > 4 ? 4 : count - 1); i >= 0; i--){ - unsigned char ch = ( utf16 >> (6 * i)) & 0x3f; - ch |= 0x80; - if (i == count-1) - ch |= 0xff << (8-count); - out[ofs++] = ch; - } - out[ofs++] = 0x00; - } - - return (char*) out; -} - -static inline void process_hatmotion(arcan_evctx* ctx, unsigned devid, - unsigned hatid, unsigned value) -{ - if (!iodev.joys) - return; - - static unsigned hattbl[4] = {SDL_HAT_UP, SDL_HAT_DOWN, - SDL_HAT_LEFT, SDL_HAT_RIGHT}; - - assert(iodev.n_joy > devid); - assert(iodev.joys[devid].hats > hatid); - - arcan_event newevent = { - .category = EVENT_IO, - .io.kind = EVENT_IO_BUTTON, - .io.datatype = EVENT_IDATATYPE_DIGITAL, - .io.devkind = EVENT_IDEVKIND_GAMEDEV, - .io.devid = iodev.joys[devid].devnum, - .io.subid = 128 + (hatid * 4) - }; - -/* shouldn't really ever be the same, but not trusting SDL */ - if (iodev.joys[devid].hattbls[ hatid ] != value){ - unsigned oldtbl = iodev.joys[devid].hattbls[hatid]; - - for (int i = 0; i < 4; i++){ - if ( (oldtbl & hattbl[i]) != (value & hattbl[i]) ){ - newevent.io.subid = (hatid * 4) + i; - newevent.io.input.digital.active = - (value & hattbl[i]) > 0; - arcan_event_enqueue(ctx, &newevent); - } - } - - iodev.joys[devid].hattbls[hatid] = value; - } -} - -const char* platform_event_devlabel(int devid) -{ - if (devid == -1) - return "mouse"; - - devid = find_devind(devid); - - if (devid < 0 || devid >= iodev.n_joy) - return "no device"; - - return iodev.joys && strlen(iodev.joys[devid].label) == 0 ? - "no identifier" : iodev.joys[devid].label; -} - -void platform_event_process(arcan_evctx* ctx) -{ - SDL_Event event; -/* other fields will be set upon enqueue */ - arcan_event newevent = {.category = EVENT_IO}; - - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_MOUSEBUTTONDOWN: - newevent.io.kind = EVENT_IO_BUTTON; - newevent.io.datatype = EVENT_IDATATYPE_DIGITAL; - newevent.io.devkind = EVENT_IDEVKIND_MOUSE; - switch(event.button.button){ - case SDL_BUTTON_LEFT: newevent.io.subid = 1; break; - case SDL_BUTTON_MIDDLE: newevent.io.subid = 3; break; - case SDL_BUTTON_RIGHT: newevent.io.subid = 2; break; - default: - newevent.io.subid = event.button.button; - break; - } - newevent.io.devid = event.button.which; - newevent.io.input.digital.active = true; - snprintf(newevent.io.label, sizeof(newevent.io.label) - 1, "mouse%i", - event.motion.which); - arcan_event_enqueue(ctx, &newevent); - break; - - case SDL_MOUSEBUTTONUP: - newevent.io.kind = EVENT_IO_BUTTON; - newevent.io.datatype = EVENT_IDATATYPE_DIGITAL; - newevent.io.devkind = EVENT_IDEVKIND_MOUSE; - newevent.io.devid = event.button.which; - newevent.io.subid = event.button.button; - newevent.io.input.digital.active = false; - snprintf(newevent.io.label, sizeof(newevent.io.label) - 1, "mouse%i", - event.motion.which); - arcan_event_enqueue(ctx, &newevent); - break; - - case SDL_MOUSEMOTION: - process_mousemotion(ctx, &event.motion); - break; - - case SDL_JOYAXISMOTION: - process_axismotion(ctx, &event.jaxis); - break; - - case SDL_KEYDOWN: - newevent.io.datatype = EVENT_IDATATYPE_TRANSLATED; - newevent.io.devkind = EVENT_IDEVKIND_KEYBOARD; - newevent.io.input.translated.active = true; - newevent.io.input.translated.keysym = event.key.keysym.sym; - newevent.io.input.translated.modifiers = event.key.keysym.mod; - newevent.io.input.translated.scancode = event.key.keysym.scancode; - newevent.io.subid = event.key.keysym.unicode; - - if (!((event.key.keysym.mod & (ARKMOD_LCTRL | ARKMOD_RCTRL)) > 0)) - to_utf8(event.key.keysym.unicode, newevent.io.input.translated.utf8); - arcan_event_enqueue(ctx, &newevent); - break; - - case SDL_KEYUP: - newevent.io.datatype = EVENT_IDATATYPE_TRANSLATED; - newevent.io.devkind = EVENT_IDEVKIND_KEYBOARD; - newevent.io.input.translated.active = false; - newevent.io.input.translated.keysym = event.key.keysym.sym; - newevent.io.input.translated.modifiers = event.key.keysym.mod; - newevent.io.input.translated.scancode = event.key.keysym.scancode; - newevent.io.subid = event.key.keysym.unicode; - arcan_event_enqueue(ctx, &newevent); - break; - - case SDL_JOYBUTTONDOWN: - newevent.io.kind = EVENT_IO_BUTTON; - newevent.io.datatype = EVENT_IDATATYPE_DIGITAL; - newevent.io.devkind = EVENT_IDEVKIND_GAMEDEV; - newevent.io.devid = iodev.joys[event.jbutton.which].devnum; - newevent.io.subid = event.jbutton.button; - newevent.io.input.digital.active = true; - snprintf(newevent.io.label, sizeof(newevent.io.label)-1, - "joystick%i", event.jbutton.which); - arcan_event_enqueue(ctx, &newevent); - break; - - case SDL_JOYBUTTONUP: - newevent.io.kind = EVENT_IO_BUTTON; - newevent.io.datatype = EVENT_IDATATYPE_DIGITAL; - newevent.io.devkind = EVENT_IDEVKIND_GAMEDEV; - newevent.io.devid = iodev.joys[event.jbutton.which].devnum; - newevent.io.subid = event.jbutton.button; - newevent.io.input.digital.active = false; - snprintf(newevent.io.label, sizeof(newevent.io.label)-1, "joystick%i", - event.jbutton.which); - arcan_event_enqueue(ctx, &newevent); - break; - -/* don't got any devices that actually use this to test with, - * but should really just be translated into analog/digital events */ - case SDL_JOYBALLMOTION: - break; - - case SDL_JOYHATMOTION: - process_hatmotion(ctx, event.jhat.which, event.jhat.hat, event.jhat.value); - break; - - case SDL_ACTIVEEVENT: -//newevent.io.kind = (MOUSEFOCUS, INPUTFOCUS, APPACTIVE(0 = icon, 1 = restored) -//if (event->active.state & SDL_APPINPUTFOCUS){ -// SDL_SetModState(KMOD_NONE); - break; - - case SDL_QUIT: - newevent.category = EVENT_SYSTEM; - newevent.sys.kind = EVENT_SYSTEM_EXIT; - arcan_event_enqueue(ctx, &newevent); - break; - - case SDL_SYSWMEVENT: - break; -/* - * currently ignoring these events (and a resizeable window frame isn't yet - * supported, although the video- code is capable of handling a rebuild/reinit, - * the lua- scripts themselves all depend quite a bit on VRESH/VRESW, one - * option would be to just calculate a scale factor for the newvresh, newvresw - * and apply that as a translation step when passing the lua<->core border. - * - * Recently, changes in the egl-dri and arcan_lwa platforms makes this possible - * so maybe it is time to update a little here ;-) - case SDL_VIDEORESIZE: - break; - - case SDL_VIDEOEXPOSE: - break; - - case SDL_ACTIVEEVENT: - break; - - case SDL_ */ - } - } -} - -/* just separate chain on hid until no collision */ -static unsigned gen_devid(unsigned hid) -{ - for (int i = 0; i < iodev.n_joy; i++){ - if (iodev.joys[i].devnum == hid){ - hid += 257; - i = 0; - } - } - return hid; -} - -int platform_event_translation( - int devid, int action, const char** names, const char** err) -{ - *err = "Unsupported"; - return false; -} - -int platform_event_device_request(int space, const char* path) -{ - return -1; -} - -void drop_joytbl(struct arcan_evctx* ctx) -{ - for(int i=0; i < iodev.n_joy; i++){ - if (!iodev.joys[i].tagged){ - struct arcan_event remev = { - .category = EVENT_IO, - .io.kind = EVENT_IO_STATUS, - .io.devid = iodev.joys[i].devnum, - .io.devkind = EVENT_IDEVKIND_STATUS, - .io.input.status.devkind = EVENT_IDEVKIND_GAMEDEV, - .io.input.status.action = EVENT_IDEV_REMOVED - }; - - snprintf((char*) &remev.io.label, sizeof(remev.io.label) / - sizeof(remev.io.label[0]), "%s", iodev.joys[i].label); - arcan_event_enqueue(ctx, &remev); - - free(iodev.joys[i].adata); - free(iodev.joys[i].hattbls); - } - else - iodev.joys[i].tagged = false; - - free(iodev.joys); - iodev.joys = NULL; - iodev.n_joy = 0; - } -} - -enum PLATFORM_EVENT_CAPABILITIES platform_event_capabilities(const char** out) -{ - if (out) - *out = "sdl"; - - return ACAP_TRANSLATED | ACAP_MOUSE | ACAP_GAMING; -} - -void platform_event_rescan_idev(arcan_evctx* ctx) -{ - if (iodev.sticks_init) - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - - SDL_Init(SDL_INIT_JOYSTICK); - SDL_JoystickEventState(SDL_ENABLE); - - int n_joys = SDL_NumJoysticks(); - iodev.sticks_init = true; - - if (n_joys == 0){ - drop_joytbl(ctx); - return; - } - -/* - * (Re) scan/open all joysticks, - * look for matching / already present devices - * and copy their settings. - */ - size_t jsz = sizeof(struct arcan_stick) * n_joys; - struct arcan_stick* joys = malloc(jsz); - memset(joys, '\0', jsz); - - for (int i = 0; i < n_joys; i++) { - struct arcan_stick* dj = &joys[i]; - struct arcan_stick* sj = NULL; - unsigned long hashid = djb_hash(SDL_JoystickName(i)); - -/* find existing */ - if (iodev.joys){ - for (int j = 0; j < iodev.n_joy; j++){ - if (iodev.joys[j].hashid == hashid){ - sj = &iodev.joys[j]; - break; - } - } - -/* if found, copy to new table */ - if (sj){ - memcpy(dj, sj, sizeof(struct arcan_stick)); - if (dj->hats){ - dj->hattbls = malloc(dj->hats * sizeof(unsigned)); - memcpy(dj->hattbls, sj->hattbls, sizeof(unsigned) * sj->hats); - } - - if (dj->axis){ - dj->adata = malloc(dj->axis * sizeof(struct axis_opts)); - memcpy(dj->adata, sj->adata, sizeof(struct axis_opts) * sj->axis); - } - - dj->handle = SDL_JoystickOpen(i); - continue; - } - } - -/* otherwise add as new entry */ - strncpy(dj->label, SDL_JoystickName(i), 255); - dj->hashid = djb_hash(SDL_JoystickName(i)); - dj->handle = SDL_JoystickOpen(i); - dj->devnum = gen_devid(dj->hashid); - - dj->axis = SDL_JoystickNumAxes(joys[i].handle); - dj->buttons = SDL_JoystickNumButtons(joys[i].handle); - dj->balls = SDL_JoystickNumBalls(joys[i].handle); - dj->hats = SDL_JoystickNumHats(joys[i].handle); - - if (dj->hats > 0){ - size_t dst_sz = joys[i].hats * sizeof(unsigned); - dj->hattbls = malloc(dst_sz); - memset(joys[i].hattbls, 0, dst_sz); - } - - if (dj->axis > 0){ - size_t ad_sz = sizeof(struct axis_opts) * dj->axis; - dj->adata = malloc(ad_sz); - memset(dj->adata, '\0', ad_sz); - for (int i = 0; i < dj->axis; i++){ - dj->adata[i].mode = ARCAN_ANALOGFILTER_AVG; -/* these values are sortof set - * based on the SixAxis (common enough, and noisy enough) */ - dj->adata[i].lower = -32765; - dj->adata[i].deadzone = 5000; - dj->adata[i].upper = 32768; - dj->adata[i].kernel_sz = 1; - } - } - -/* notify the rest of the system about the added device */ - struct arcan_event addev = { - .category = EVENT_IO, - .io.kind = EVENT_IO_STATUS, - .io.devkind = EVENT_IDEVKIND_STATUS, - .io.devid = dj->devnum, - .io.input.status.devkind = EVENT_IDEVKIND_GAMEDEV, - .io.input.status.action = EVENT_IDEV_ADDED - }; - snprintf((char*) &addev.io.label, sizeof(addev.io.label) / - sizeof(addev.io.label[0]), "%s", dj->label); - arcan_event_enqueue(ctx, &addev); - } - - iodev.n_joy = n_joys; - iodev.joys = joys; -} - -void platform_event_keyrepeat(arcan_evctx* ctx, int* rate, int* delay) -{ -/* sdl repeat start disabled */ - static int cur_rep, cur_del; - bool upd = false; - - if (*rate < 0){ - *rate = cur_rep; - } - else{ - int tmp = *rate; - *rate = cur_rep; - cur_rep = tmp; - upd = true; - } - - if (*delay < 0){ - *delay = cur_del; - } - else{ - int tmp = *delay; - *delay = cur_del; - cur_del = tmp; - upd = true; - } - - if (upd) - SDL_EnableKeyRepeat(cur_del, cur_rep); -} - -void platform_event_deinit(arcan_evctx* ctx) -{ - if (iodev.sticks_init){ - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - iodev.sticks_init = false; - } -} - -void platform_event_reset(arcan_evctx* ctx) -{ - platform_event_deinit(ctx); -} - -void platform_device_lock(int devind, bool state) -{ - SDL_WM_GrabInput( state ? SDL_GRAB_ON : SDL_GRAB_OFF ); -} - -void platform_event_preinit() -{ -} - -void platform_event_init(arcan_evctx* ctx) -{ - static bool first_init; - - SDL_EnableUNICODE(1); - -/* OSX hack */ - SDL_ShowCursor(0); - SDL_ShowCursor(1); - SDL_ShowCursor(0); - - if (!first_init){ - platform_event_analogfilter(-1, 0, - -32768, 32767, 0, 1, ARCAN_ANALOGFILTER_AVG); - platform_event_analogfilter(-1, 1, - -32768, 32767, 0, 1, ARCAN_ANALOGFILTER_AVG); - first_init = true; - int r = 0, d = 0; - platform_event_keyrepeat(ctx, &r, &d); - } -/* flush out initial storm, with safeguard against event loop issues */ - SDL_Event dummy[1]; - SDL_PumpEvents(); - int timeout = 1000; - while (timeout-- && - SDL_PeepEvents(dummy, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION)) > 0){ - } - - platform_event_rescan_idev(ctx); -} - diff --git a/src/platform/sdl/video.c b/src/platform/sdl/video.c deleted file mode 100644 index b0521ebd7..000000000 --- a/src/platform/sdl/video.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright 2003-2016, Björn Ståhl - * License: 3-Clause BSD, see COPYING file in arcan source repository. - * Reference: http://arcan-fe.com - */ - -#include -#include -#include -#include - -#include -#include - -#include "arcan_math.h" -#include "arcan_general.h" -#include "arcan_video.h" -#include "arcan_videoint.h" -#include "arcan_shmif.h" -#include "arcan_event.h" - -static struct { - SDL_Surface* screen; - int sdlarg; - size_t canvasw, canvash; - size_t draww, drawh, drawx, drawy; - arcan_vobj_id vid; - uint64_t last; - float txcos[8]; -} sdl; - -static char* envopts[] = { - "ARCAN_VIDEO_MULTISAMPLES=1", "attempt to enable multisampling", - NULL -}; - -void platform_video_shutdown() -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - SDL_GL_SwapBuffers(); - SDL_FreeSurface(sdl.screen); - SDL_QuitSubSystem(SDL_INIT_VIDEO); -} - -void platform_video_prepare_external() -{ - SDL_FreeSurface(sdl.screen); - if (arcan_video_display.fullscreen) - SDL_QuitSubSystem(SDL_INIT_VIDEO); -} - -void platform_video_restore_external() -{ - if (arcan_video_display.fullscreen) - SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); - - sdl.screen = SDL_SetVideoMode( - sdl.canvasw, sdl.canvash, sizeof(av_pixel), sdl.sdlarg); -} - -bool platform_video_auth(int cardn, unsigned token) -{ - return false; -} - -int platform_video_cardhandle(int cardn, - int* buffer_method, size_t* metadata_sz, uint8_t** metadata) -{ - return -1; -} - -size_t platform_video_decay() -{ - return 0; -} - -void platform_video_reset(int id, int swap) -{ -} - -bool platform_video_map_buffer( - struct agp_vstore* vs, struct agp_buffer_plane* planes, size_t n) -{ - return false; -} - -void* platform_video_gfxsym(const char* sym) -{ - return SDL_GL_GetProcAddress(sym); -} - -void platform_video_minimize() -{ - SDL_WM_IconifyWindow(); -} - -void platform_video_synch(uint64_t tick_count, float fract, - video_synchevent pre, video_synchevent post) -{ - if (pre) - pre(); - - arcan_vobject* vobj = arcan_video_getobject(sdl.vid); - if (!vobj){ - sdl.vid = ARCAN_VIDEO_WORLDID; - vobj = arcan_video_getobject(ARCAN_VIDEO_WORLDID); - } - -/* special case, lost WORLDID, draw direct on GL context */ - size_t nd; - if (sdl.vid == ARCAN_VIDEO_WORLDID && !arcan_vint_worldrt()){ - agp_shader_envv(PROJECTION_MATR, - arcan_video_display.default_projection, sizeof(float)*16); - arcan_bench_register_cost( arcan_vint_refresh(fract, &nd) ); - } - else { - arcan_bench_register_cost( arcan_vint_refresh(fract, &nd) ); - agp_shader_id shid = agp_default_shader(BASIC_2D); - agp_activate_rendertarget(NULL); - - if (vobj->program > 0) - shid = vobj->program; - - agp_shader_activate(shid); - agp_shader_envv(PROJECTION_MATR, - arcan_video_display.window_projection, sizeof(float)*16); - - if (sdl.vid == ARCAN_VIDEO_WORLDID){ - agp_activate_vstore(arcan_vint_world()); - } - else{ - agp_activate_vstore(vobj->vstore); - } - - agp_draw_vobj(sdl.drawx, sdl.drawy, sdl.draww, sdl.drawh, sdl.txcos, NULL); - } - - arcan_vint_drawcursor(false); - -/* - * NOTE: heuristic fix-point for direct- mapping dedicated source for - * low latency here when we fix up internal syncing paths. - */ - if (nd) - SDL_GL_SwapBuffers(); - -/* - * This is the 'legacy- approach' to synching and should be reworked - * to match the changes inside the conductor - */ - int delta = arcan_frametime() - sdl.last; - if (delta >= 0 && delta < 8){ - arcan_timesleep(16 - delta); - } - - sdl.last = arcan_frametime(); - if (post) - post(); -} - -const char** platform_video_envopts() -{ - return (const char**) envopts; -} - -size_t platform_video_displays(platform_display_id* dids, size_t* lim) -{ - if (dids && lim && *lim > 0){ - dids[0] = 0; - } - - if (lim) - *lim = 1; - - return 1; -} - -enum dpms_state platform_video_dpms( - platform_display_id disp, enum dpms_state state) -{ - return ADPMS_ON; -} - -bool platform_video_map_handle(struct agp_vstore* dst, int64_t handle) -{ - return false; -} - -void platform_video_query_displays() -{ -} - -void platform_video_recovery() -{ -} - -bool platform_video_display_edid(platform_display_id did, - char** out, size_t* sz) -{ - *out = NULL; - *sz = 0; - return false; -} - -bool platform_video_set_display_gamma(platform_display_id did, - size_t n_ramps, uint16_t* r, uint16_t* g, uint16_t* b) -{ - return false; -} - -bool platform_video_get_display_gamma(platform_display_id did, - size_t* n_ramps, uint16_t** outb) -{ - return false; -} - -bool platform_video_specify_mode(platform_display_id disp, - struct monitor_mode mode) -{ - return false; -} - -bool platform_video_set_mode(platform_display_id disp, - platform_mode_id mode, struct platform_mode_opts opts) -{ - return disp == 0 && mode == 0; -} - -void platform_video_invalidate_map( - struct agp_vstore* vstore, struct agp_region region) -{ -/* NOP for the time being - might change for direct forwarding of client */ -} - -struct monitor_mode* platform_video_query_modes( - platform_display_id id, size_t* count) -{ - static struct monitor_mode mode = {}; - - mode.width = sdl.canvasw; - mode.height = sdl.canvash; - mode.depth = sizeof(av_pixel) * 8; - mode.refresh = 60; /* should be queried */ - - *count = 1; - return &mode; -} - -struct monitor_mode platform_video_dimensions() -{ - struct monitor_mode res = { - .width = sdl.canvasw, - .height = sdl.canvash, - }; - -/* any decent way to query for that value here? */ - res.phy_width = (float) res.width / ARCAN_SHMPAGE_DEFAULT_PPCM * 10.0; - res.phy_height = (float) res.height / ARCAN_SHMPAGE_DEFAULT_PPCM * 10.0; - - return res; -} - -bool platform_video_map_display( - arcan_vobj_id vid, platform_display_id id, enum blitting_hint hint) -{ - struct display_layer_cfg cfg = { - .opacity = 1.0, - .hint = hint - }; - - return platform_video_map_display_layer(vid, id, 0, cfg) >= 0; -} - -ssize_t platform_video_map_display_layer(arcan_vobj_id id, - platform_display_id disp, size_t layer_index, struct display_layer_cfg cfg) -{ - if (disp != 0 || layer_index) - return false; - - enum blitting_hint hint = cfg.hint; - - arcan_vobject* vobj = arcan_video_getobject(id); - bool isrt = arcan_vint_findrt(vobj) != NULL; - - if (vobj && vobj->vstore->txmapped != TXSTATE_TEX2D){ - arcan_warning("platform_video_map_display(), attempted to map a " - "video object with an invalid backing store"); - return false; - } - -/* - * The constant problem of what are we drawing and how are we drawing it - * (rts were initially used for 3d models, vobjs were drawin with inverted ys - * and world normally etc. a huge mess) - */ - size_t iframes = 0; - if (isrt){ - arcan_vint_applyhint(vobj, hint, vobj->txcos ? vobj->txcos : - arcan_video_display.default_txcos, sdl.txcos, - &sdl.drawx, &sdl.drawy, - &sdl.draww, &sdl.drawh, - &iframes); - } -/* direct VOBJ mapping, prepared for indirect drawying so flip yhint */ - else { - arcan_vint_applyhint(vobj, - (hint & HINT_YFLIP) ? (hint & (~HINT_YFLIP)) : (hint | HINT_YFLIP), - vobj->txcos ? vobj->txcos : arcan_video_display.default_txcos, sdl.txcos, - &sdl.drawx, &sdl.drawy, - &sdl.draww, &sdl.drawh, - &iframes); - } - arcan_video_display.ignore_dirty += iframes; - sdl.vid = id; - return true; -} - -bool platform_video_display_id(platform_display_id id, - platform_mode_id mode_id, struct monitor_mode mode) -{ - return false; -} - -const char* platform_video_capstr() -{ - static char* capstr; - - if (!capstr){ - const char* vendor = (const char*) glGetString(GL_VENDOR); - const char* render = (const char*) glGetString(GL_RENDERER); - const char* version = (const char*) glGetString(GL_VERSION); - const char* shading = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); - const char* exts = (const char*) glGetString(GL_EXTENSIONS); - - size_t interim_sz = 64 * 1024; - char* interim = malloc(interim_sz); - size_t nw = snprintf(interim, interim_sz, "Video Platform (SDL)\n" - "Vendor: %s\nRenderer: %s\nGL Version: %s\n" - "GLSL Version: %s\n\n Extensions Supported: \n%s\n\n", - vendor, render, version, shading, exts - ) + 1; - - if (nw < (interim_sz >> 1)){ - capstr = malloc(nw); - memcpy(capstr, interim, nw); - free(interim); - } - else - capstr = interim; - } - - return capstr; -} - -void platform_video_preinit() -{ -} - -bool platform_video_init(uint16_t width, uint16_t height, uint8_t bpp, - bool fs, bool frames, const char* capt) -{ - char caption[64] = {0}; - SDL_Init(SDL_INIT_VIDEO); - - const SDL_VideoInfo* vi = SDL_GetVideoInfo(); - if (!vi){ - arcan_fatal("SDL_GetVideoInfo() failed, broken display subsystem."); - } - - if (width == 0) - width = vi->current_w; - - if (height == 0) - height = vi->current_h; - - sdl.canvasw = width; - sdl.canvash = height; - sdl.draww = width; - sdl.drawh = height; - arcan_video_display.ignore_dirty += 2; - - arcan_warning("Notice: [SDL] Video Info: %i, %i, hardware acceleration: %s, " - "window manager: %s, MSAA: %i\n", - vi->current_w, vi->current_h, vi->hw_available ? "yes" : "no", - vi->wm_available ? "yes" : "no", - arcan_video_display.msasamples); - -/* some GL attributes have to be set before creating the video-surface */ - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - - int msasamples = 0; - - const char* msenv; - if ( (msenv = getenv("ARCAN_VIDEO_MULTISAMPLES")) ){ - msasamples = (int) strtol(msenv, NULL, 10); - } - - if (msasamples > 0){ - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msasamples); - } - - snprintf(caption, 63, "%s", capt); - SDL_WM_SetCaption(caption, "Arcan"); - - arcan_video_display.fullscreen = fs; - sdl.sdlarg = (fs ? SDL_FULLSCREEN : 0) | - SDL_OPENGL | (frames ? SDL_NOFRAME : 0); - sdl.screen = SDL_SetVideoMode(width, height, bpp, sdl.sdlarg); - - if (msasamples && !sdl.screen){ - arcan_warning("arcan_video_init(), Couldn't open OpenGL display," - "attempting without MSAA\n"); - setenv("ARCAN_VIDEO_MULTISAMPLES", "0", 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); - sdl.screen = SDL_SetVideoMode(width, height, bpp, sdl.sdlarg); - } - - if (!sdl.screen) - return false; - - glViewport(0, 0, width, height); - sdl.vid = ARCAN_VIDEO_WORLDID; - memcpy(sdl.txcos, arcan_video_display.mirror_txcos, sizeof(float) * 8); - - sdl.last = arcan_frametime(); - return true; -} diff --git a/src/platform/sdl2/event.c b/src/platform/sdl2/event.c index 682620137..d5c583b6d 100644 --- a/src/platform/sdl2/event.c +++ b/src/platform/sdl2/event.c @@ -109,7 +109,7 @@ static int find_devind_from_joyid(SDL_JoystickID id) return -1; } -static inline bool process_axis(arcan_evctx* ctx, +static inline bool process_axis(struct arcan_evctx* ctx, struct axis_opts* daxis, int16_t samplev, int16_t* outv) { if (daxis->mode == ARCAN_ANALOGFILTER_NONE) @@ -181,7 +181,7 @@ static inline bool process_axis(arcan_evctx* ctx, } static inline void process_axismotion( - arcan_evctx* ctx, const SDL_JoyAxisEvent* const ev) + struct arcan_evctx* ctx, const SDL_JoyAxisEvent* const ev) { int devind = find_devind_from_joyid(ev->which); @@ -228,7 +228,7 @@ int platform_event_device_request(int space, const char* path) return -1; } -static inline void process_mousemotion(arcan_evctx* ctx, +static inline void process_mousemotion(struct arcan_evctx* ctx, const SDL_MouseMotionEvent* const ev) { arcan_event nev = { @@ -424,8 +424,8 @@ static unsigned long djb_hash(const char* str, size_t n) return hash; } -static inline void process_hatmotion(arcan_evctx* ctx, unsigned devid, - unsigned hatid, unsigned value) +static inline void process_hatmotion( + struct arcan_evctx* ctx, unsigned devid, unsigned hatid, unsigned value) { int devind = find_devind_from_joyid(devid); if (devind == -1) @@ -581,7 +581,7 @@ uint16_t sdl2_sym_to_12sym(uint32_t insym) return 0; } -void platform_event_process(arcan_evctx* ctx) +void platform_event_process(struct arcan_evctx* ctx) { int canary = 0xf00f; SDL_Event event; @@ -885,7 +885,7 @@ enum PLATFORM_EVENT_CAPABILITIES platform_event_capabilities(const char** out) return ACAP_TRANSLATED | ACAP_MOUSE | ACAP_GAMING; } -void platform_event_rescan_idev(arcan_evctx* ctx) +void platform_event_rescan_idev(struct arcan_evctx* ctx) { if (iodev.sticks_init) SDL_QuitSubSystem(SDL_INIT_JOYSTICK); @@ -994,7 +994,7 @@ void platform_event_rescan_idev(arcan_evctx* ctx) iodev.joys = joys; } -void platform_event_keyrepeat(arcan_evctx* ctx, int* rate, int* delay) +void platform_event_keyrepeat(struct arcan_evctx* ctx, int* rate, int* delay) { /* sdl repeat start disabled */ static int cur_rep, cur_del; @@ -1027,7 +1027,7 @@ void platform_event_keyrepeat(arcan_evctx* ctx, int* rate, int* delay) } } -void platform_event_deinit(arcan_evctx* ctx) +void platform_event_deinit(struct arcan_evctx* ctx) { if (iodev.sticks_init){ SDL_QuitSubSystem(SDL_INIT_JOYSTICK); @@ -1035,7 +1035,7 @@ void platform_event_deinit(arcan_evctx* ctx) } } -void platform_event_reset(arcan_evctx* ctx) +void platform_event_reset(struct arcan_evctx* ctx) { platform_event_deinit(ctx); } @@ -1051,7 +1051,7 @@ void platform_event_preinit() { } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { static bool first_init; diff --git a/src/platform/stub/event.c b/src/platform/stub/event.c index a00139ca8..1dc0d0d2d 100644 --- a/src/platform/stub/event.c +++ b/src/platform/stub/event.c @@ -55,15 +55,15 @@ void platform_event_analogfilter(int devid, { } -void platform_event_process(arcan_evctx* ctx) +void platform_event_process(struct arcan_evctx* ctx) { } -void platform_event_keyrepeat(arcan_evctx* ctx, int* rate, int* del) +void platform_event_keyrepeat(struct arcan_evctx* ctx, int* rate, int* del) { } -void platform_event_rescan_idev(arcan_evctx* ctx) +void platform_event_rescan_idev(struct arcan_evctx* ctx) { } @@ -81,11 +81,11 @@ const char** platform_event_envopts() return (const char**) envopts; } -void platform_event_deinit(arcan_evctx* ctx) +void platform_event_deinit(struct arcan_evctx* ctx) { } -void platform_event_reset(arcan_evctx* ctx) +void platform_event_reset(struct arcan_evctx* ctx) { platform_event_deinit(ctx); } @@ -98,6 +98,6 @@ void platform_event_preinit() { } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { } diff --git a/src/platform/syscons/event.c b/src/platform/syscons/event.c index 65bd390a1..9b4015192 100644 --- a/src/platform/syscons/event.c +++ b/src/platform/syscons/event.c @@ -355,12 +355,12 @@ static int mod_to_ind(uint16_t modmask) return ind; } -static void do_touchp(arcan_evctx* ctx, struct devnode* node) +static void do_touchp(struct arcan_evctx* ctx, struct devnode* node) { /* see man psm and the MOUSE_SYN_GETHWINFO etc. for synaptics */ } -static inline void check_btn(arcan_evctx* ctx, +static inline void check_btn(struct arcan_evctx* ctx, int oldstate, int newstate, int fl, int ind) { if (!((oldstate & fl) ^ (newstate & fl))) @@ -378,7 +378,7 @@ static inline void check_btn(arcan_evctx* ctx, arcan_event_enqueue(ctx, &ev); } -static void wheel_ev(arcan_evctx* ctx, int idofs, int val) +static void wheel_ev(struct arcan_evctx* ctx, int idofs, int val) { arcan_event aev = { .category = EVENT_IO, @@ -420,7 +420,7 @@ static void wheel_ev(arcan_evctx* ctx, int idofs, int val) arcan_event_enqueue(ctx, &dev); } -static void do_mouse(arcan_evctx* ctx, struct devnode* node) +static void do_mouse(struct arcan_evctx* ctx, struct devnode* node) { size_t pkt_sz = node->mouse.mode.packetsize; uint8_t buf[pkt_sz]; @@ -515,7 +515,7 @@ static void do_mouse(arcan_evctx* ctx, struct devnode* node) } } -static void do_keyb(arcan_evctx* ctx, struct devnode* node) +static void do_keyb(struct arcan_evctx* ctx, struct devnode* node) { uint8_t n, code; ssize_t count = read(evctx.tty, &n, 1); @@ -557,7 +557,7 @@ static void do_keyb(arcan_evctx* ctx, struct devnode* node) arcan_event_enqueue(ctx, &ev); } -void platform_event_process(arcan_evctx* ctx) +void platform_event_process(struct arcan_evctx* ctx) { /* KEYBOARD format: * 1. Lookup code according to the current map which will yield @@ -610,7 +610,7 @@ void platform_event_samplebase(int devid, float xyz[3]) * int_operttion, union { struct data, mode, event } */ } -void platform_event_keyrepeat(arcan_evctx* ctx, int* period, int* delay) +void platform_event_keyrepeat(struct arcan_evctx* ctx, int* period, int* delay) { struct keyboard_repeat rep; if (-1 == ioctl(evctx.keyb.fd, KDGETREPEAT, &rep)) @@ -637,7 +637,7 @@ enum PLATFORM_EVENT_CAPABILITIES platform_event_capabilities(const char** out) return ACAP_TRANSLATED | ACAP_MOUSE | ACAP_TOUCH; } -void platform_event_rescan_idev(arcan_evctx* ctx) +void platform_event_rescan_idev(struct arcan_evctx* ctx) { } @@ -657,7 +657,7 @@ const char** platform_event_envopts() return (const char**) envopts; } -void platform_event_deinit(arcan_evctx* ctx) +void platform_event_deinit(struct arcan_evctx* ctx) { /* this is also performed in psep_open */ if (-1 != evctx.tty){ @@ -675,7 +675,7 @@ void platform_event_preinit() { } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { /* save TTY settings, explicit for devices as we want kbd- access even * when testing from a remote shell */ @@ -763,7 +763,7 @@ void platform_event_init(arcan_evctx* ctx) } } -void platform_event_reset(arcan_evctx* ctx) +void platform_event_reset(struct arcan_evctx* ctx) { platform_event_deinit(ctx); platform_event_init(ctx); diff --git a/src/platform/wscons/event.c b/src/platform/wscons/event.c index 321ff3a2e..36284bc0c 100644 --- a/src/platform/wscons/event.c +++ b/src/platform/wscons/event.c @@ -169,7 +169,7 @@ static void apply_modifiers(int value, struct arcan_event* ev) #define TS_MS(X) ((X).tv_sec * 1000 + (X).tv_nsec / 1.0e6) -void platform_event_process(arcan_evctx* ctx) +void platform_event_process(struct arcan_evctx* ctx) { struct wscons_event events[64]; int type; @@ -278,7 +278,7 @@ void platform_event_process(arcan_evctx* ctx) } } -void platform_event_keyrepeat(arcan_evctx* ctx, int* period, int* delay) +void platform_event_keyrepeat(struct arcan_evctx* ctx, int* period, int* delay) { bool upd = false; @@ -331,7 +331,7 @@ int platform_event_device_request(int space, const char* path) return -1; } -void platform_event_rescan_idev(arcan_evctx* ctx) +void platform_event_rescan_idev(struct arcan_evctx* ctx) { } @@ -349,7 +349,7 @@ const char** platform_event_envopts() return (const char**) envopts; } -void platform_event_deinit(arcan_evctx* ctx) +void platform_event_deinit(struct arcan_evctx* ctx) { if (-1 != evctx.kbd.fd){ int option = WSKBD_TRANSLATED; @@ -365,7 +365,7 @@ void platform_event_deinit(arcan_evctx* ctx) } } -void platform_event_reset(arcan_evctx* ctx) +void platform_event_reset(struct arcan_evctx* ctx) { } @@ -385,7 +385,7 @@ void platform_event_preinit() } } -void platform_event_init(arcan_evctx* ctx) +void platform_event_init(struct arcan_evctx* ctx) { evctx.kbd.fd = platform_device_open("/dev/wskbd", O_RDONLY | O_NONBLOCK | O_EXCL); diff --git a/src/shmif/CMakeLists.txt b/src/shmif/CMakeLists.txt index 3bf6c3db0..852638e06 100644 --- a/src/shmif/CMakeLists.txt +++ b/src/shmif/CMakeLists.txt @@ -145,8 +145,6 @@ if (NOT TUI_RASTER_NO_TTF) SHMIF_TUI_SOURCES ${ASD}/engine/arcan_ttf.c ) - set_property(SOURCE ${ASD}/engine/arcan_ttf.c - APPEND PROPERTY COMPILE_DEFINITIONS SHMIF_TTF) else() list(APPEND SHMIF_TUI_SOURCES @@ -205,7 +203,10 @@ set(TUI_LIBRARIES arcan_shmif) add_library(arcan_tui SHARED ${SHMIF_TUI_SOURCES}) if (NOT TUI_RASTER_NO_TTF) list(APPEND TUI_LIBRARIES ${FREETYPE_LIBRARIES}) + target_compile_definitions(arcan_tui PRIVATE SHMIF_TTF) endif() +target_compile_definitions(arcan_tui PRIVATE NO_ARCAN_AGP) + target_link_libraries(arcan_tui PRIVATE ${STDLIB} ${TUI_LIBRARIES}) set_target_properties(arcan_tui PROPERTIES VERSION ${ASHMIF_MAJOR}.${ASHMIF_MINOR}) diff --git a/src/shmif/arcan_shmif_a11y.c b/src/shmif/arcan_shmif_a11y.c index fe434b62d..0fddaa57c 100644 --- a/src/shmif/arcan_shmif_a11y.c +++ b/src/shmif/arcan_shmif_a11y.c @@ -1,4 +1,5 @@ #include "arcan_shmif.h" +#include "platform/shmif_platform.h" #include "arcan_shmif_interop.h" #include "shmif_defimpl.h" #include "shmif_privint.h" diff --git a/src/shmif/arcan_shmif_control.c b/src/shmif/arcan_shmif_control.c index 464030177..446e8686c 100644 --- a/src/shmif/arcan_shmif_control.c +++ b/src/shmif/arcan_shmif_control.c @@ -28,11 +28,10 @@ #include #include "arcan_shmif.h" +#include "platform/shmif_platform.h" #include "shmif_privext.h" #include "shmif_privint.h" - #include "shmif_defimpl.h" -#include "platform/shmif_platform.h" #include #include @@ -49,6 +48,8 @@ ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) #endif +#define BADFD -1 + /* * a bit clunky, but some scenarios that we want debug-builds but without the * debug logging spam for external projects, and others where we want to @@ -1385,7 +1386,7 @@ static bool get_shmkey_from_socket(int sock, char* wbuf, size_t sz) } char* arcan_shmif_connect( - const char* connpath, const char* connkey, file_handle* conn_ch) + const char* connpath, const char* connkey, int* conn_ch) { struct sockaddr_un dst = { .sun_family = AF_UNIX @@ -2655,7 +2656,7 @@ enum shmif_migrate_status arcan_shmif_migrate( if (!pthread_equal(P->primary_id, pthread_self())) return SHMIF_MIGRATE_BAD_SOURCE; - file_handle dpipe; + int dpipe; char* keyfile = NULL; if (-1 != a12_cp(newpath, NULL)) @@ -3159,7 +3160,7 @@ struct arcan_shmif_cont arcan_shmif_open_ext(enum ARCAN_FLAGS flags, struct arg_arr** outarg, struct shmif_open_ext ext, size_t ext_sz) { struct arcan_shmif_cont ret = {0}; - file_handle dpipe; + int dpipe; uint64_t ts = arcan_timemillis(); if (!g_epoch) diff --git a/src/shmif/arcan_shmif_control.h b/src/shmif/arcan_shmif_control.h index fec3df598..9b57e210d 100644 --- a/src/shmif/arcan_shmif_control.h +++ b/src/shmif/arcan_shmif_control.h @@ -290,14 +290,14 @@ struct arcan_shmif_cont { * the event handle is provided and used for signal event delivery * in order to allow multiplexation with other input/output sources */ - file_handle epipe; + int epipe; /* * Maintain a connection to the shared memory handle in order to handle * resizing (on platforms that support it, otherwise define * ARCAN_SHMIF_OVERCOMMIT which will only recalc pointers on resize */ - file_handle shmh; + int shmh; size_t shmsize; /* @@ -547,8 +547,8 @@ size_t arcan_shmif_initial(struct arcan_shmif_cont*, * suitable for shmkey, along with a file descriptor to the * connected socket in *conn_ch */ -char* arcan_shmif_connect(const char* connpath, - const char* connkey, file_handle* conn_ch); +char* arcan_shmif_connect( + const char* connpath, const char* connkey, int* conn_ch); /* * This is used to migrate a current connection, authoritative or not, @@ -1104,7 +1104,7 @@ struct arcan_shmif_page { * if the parent process is still alive (used internally by GUARDTHREAD). * Can also be updated in relation to a RESET event. */ - process_handle parent; + int parent; /* * [FSRV-OR-ARCAN-SET] diff --git a/src/shmif/arcan_shmif_event.h b/src/shmif/arcan_shmif_event.h index ea7eea312..35fc76872 100644 --- a/src/shmif/arcan_shmif_event.h +++ b/src/shmif/arcan_shmif_event.h @@ -1803,10 +1803,6 @@ typedef enum { ARKMOD_LIMIT = INT_MAX } key_modifiers; -#ifdef PLATFORM_HEADER -#include PLATFORM_HEADER -#endif - struct arcan_event_trigger { union { int fd; @@ -1816,49 +1812,4 @@ struct arcan_event_trigger { uint64_t tag; }; -struct arcan_evctx { -/* time and mask- tracking, only used parent-side */ - int32_t c_ticks; - uint32_t mask_cat_inp; - -/* only used for local queues */ - uint32_t state_fl; - int exit_code; - bool (*drain)(arcan_event*, int); - uint8_t eventbuf_sz; - - arcan_event* eventbuf; - -/* offsets into the eventbuf queue, parent will always % ARCAN_SHMPAGE_QUEUE_SZ - * to prevent nasty surprises. these were set before we had access to _Atomic - * in the standard fashion, and the codebase should be refactored to take that - * into account */ - volatile uint8_t* volatile front; - volatile uint8_t* volatile back; - - int8_t local; - -/* - * When the child (!local flag) wants the parent to wake it up, - * the sem_handle (by default, 1) is set to 0 and calls sem_wait. - * - * When the parent pushes data on the event-queue it checks the - * state if this sem_handle. If it's 0, and some internal - * dynamic heuristic (if the parent knows multiple- connected - * events are enqueued, it can wait a bit before waking the child) - * and if that heuristic is triggered, the semaphore is posted. - * - * This is also used by the guardthread (that periodically checks - * if the parent is still alive, and if not, unlocks a batch - * of semaphores). - */ - struct { - volatile uint8_t* killswitch; - sem_handle handle; - } synch; - -}; - -typedef struct arcan_evctx arcan_evctx; - #endif diff --git a/src/shmif/arcan_shmif_interop.h b/src/shmif/arcan_shmif_interop.h index bfd532202..23e9c3927 100644 --- a/src/shmif/arcan_shmif_interop.h +++ b/src/shmif/arcan_shmif_interop.h @@ -43,33 +43,6 @@ #define ASHMIF_VERSION_MAJOR 0 #define ASHMIF_VERSION_MINOR 17 -#ifndef LOG -#define LOG(X, ...) (fprintf(stderr, "[%lld]" X, arcan_timemillis(), ## __VA_ARGS__)) -#endif - -/* - * For porting the shmpage interface, these functions need to be implemented - * and pulled in, shouldn't be more complicated than mapping to the - * corresponding platform/ functions. In the longer scope, these should be - * factored out and replaced as well. - */ -#ifndef PLATFORM_HEADER - -#define BADFD -1 -#include -#include -#include -typedef int file_handle; -typedef pid_t process_handle; -typedef sem_t* sem_handle; - -long long int arcan_timemillis(void); -int arcan_sem_post(sem_handle sem); -int arcan_sem_wait(sem_handle sem); -int arcan_sem_trywait(sem_handle sem); -int arcan_fdscan(int** listout); -#endif - struct arcan_shmif_cont; struct arcan_event; struct arcan_ioevent; diff --git a/src/shmif/arcan_shmif_server.c b/src/shmif/arcan_shmif_server.c index be4e3bd51..6e1961bb5 100644 --- a/src/shmif/arcan_shmif_server.c +++ b/src/shmif/arcan_shmif_server.c @@ -1,5 +1,9 @@ #include "arcan_shmif.h" +#include PLATFORM_HEADER + +#include "platform/shmif_platform.h" #include "arcan_shmif_server.h" + #include #include #include @@ -17,11 +21,9 @@ * we should share all the code between the engine- side and the server lib - * no reason for the two implementations. */ -typedef int shm_handle; #include "arcan_math.h" #include "arcan_general.h" #include "arcan_frameserver.h" -#include "platform/shmif_platform.h" /* * wrap the normal structure as we need to pass it to the platform frameserver diff --git a/src/shmif/platform/eventqueue.c b/src/shmif/platform/eventqueue.c index fd5cefd50..98634f2d7 100644 --- a/src/shmif/platform/eventqueue.c +++ b/src/shmif/platform/eventqueue.c @@ -4,9 +4,9 @@ #include #include +#include "arcan_shmif.h" #include "shmif_platform.h" #include "arcan_shmif_event.h" -#include "arcan_shmif.h" void shmif_platform_setevqs( struct arcan_shmif_page* dst, diff --git a/src/shmif/platform/exec.c b/src/shmif/platform/exec.c index 3dd85755d..63e4b3294 100644 --- a/src/shmif/platform/exec.c +++ b/src/shmif/platform/exec.c @@ -1,11 +1,7 @@ -#include -#include +#include "arcan_shmif.h" +#include "shmif_platform.h" #include -#include #include -#include - -#include "shmif_platform.h" extern char** environ; diff --git a/src/shmif/platform/shmif_platform.h b/src/shmif/platform/shmif_platform.h index 0ae90c6ef..340712483 100644 --- a/src/shmif/platform/shmif_platform.h +++ b/src/shmif/platform/shmif_platform.h @@ -4,6 +4,12 @@ struct arcan_evctx; struct arcan_shmif_page; #include +#include + +#ifndef LOG +unsigned long long arcan_timemillis(); +#define LOG(X, ...) (fprintf(stderr, "[%lld]" X, arcan_timemillis(), ## __VA_ARGS__)) +#endif /* shmif extensions to src/platform, * @@ -13,6 +19,48 @@ struct arcan_shmif_page; * */ +struct arcan_evctx { +/* time and mask- tracking, only used parent-side */ + int32_t c_ticks; + uint32_t mask_cat_inp; + +/* only used for local queues */ + uint32_t state_fl; + int exit_code; + bool (*drain)(arcan_event*, int); + uint8_t eventbuf_sz; + + arcan_event* eventbuf; + +/* offsets into the eventbuf queue, parent will always % ARCAN_SHMPAGE_QUEUE_SZ + * to prevent nasty surprises. these were set before we had access to _Atomic + * in the standard fashion, and the codebase should be refactored to take that + * into account */ + volatile uint8_t* volatile front; + volatile uint8_t* volatile back; + + int8_t local; + +/* + * When the child (!local flag) wants the parent to wake it up, + * the sem_handle (by default, 1) is set to 0 and calls sem_wait. + * + * When the parent pushes data on the event-queue it checks the + * state if this sem_handle. If it's 0, and some internal + * dynamic heuristic (if the parent knows multiple- connected + * events are enqueued, it can wait a bit before waking the child) + * and if that heuristic is triggered, the semaphore is posted. + * + * This is also used by the guardthread (that periodically checks + * if the parent is still alive, and if not, unlocks a batch + * of semaphores). + */ + struct { + volatile uint8_t* killswitch; + sem_t* handle; + } synch; +}; + enum platform_execve_opts { EXECVE_NONE = 0, EXECVE_DETACH_PROCESS = 1, @@ -85,4 +133,11 @@ bool shmif_platform_pushfd(int fd, int sockout); */ int shmif_platform_fetchfd(int sockin, bool blocking, bool (*alive_check)(void*), void*); +unsigned long long arcan_timemillis(void); +int arcan_sem_post(sem_t* sem); +int arcan_sem_wait(sem_t* sem); +int arcan_sem_trywait(sem_t* sem); +int arcan_fdscan(int** listout); +void arcan_timesleep(unsigned long); + #endif diff --git a/src/shmif/shmif_privint.h b/src/shmif/shmif_privint.h index 68998521b..cc125534e 100644 --- a/src/shmif/shmif_privint.h +++ b/src/shmif/shmif_privint.h @@ -20,7 +20,9 @@ struct shmif_hidden { struct arg_arr* args; char* last_words; - sem_handle vsem, asem, esem; + sem_t* vsem; + sem_t* asem; + sem_t* esem; shmif_trigger_hook_fptr video_hook; void* video_hook_data; @@ -119,7 +121,7 @@ struct shmif_hidden { bool gotev, consumed; bool handedover; arcan_event ev; - file_handle fd; + int fd; } pev; /* When a NEWSEGMENT event has been provided (and descriptor- paired) the caller @@ -147,8 +149,8 @@ struct shmif_hidden { /* Fringe-wise, we need two DMSes, one set in shmpage and another using the * guard-thread, then both need to be checked after every semaphore lock */ _Atomic bool local_dms; - sem_handle semset[3]; - process_handle parent; + sem_t* semset[3]; + int parent; int parent_fd; volatile uint8_t* _Atomic volatile dms; pthread_mutex_t synch; diff --git a/src/shmif/stub/stub.c b/src/shmif/stub/stub.c index 05365405d..4f98e7cc3 100644 --- a/src/shmif/stub/stub.c +++ b/src/shmif/stub/stub.c @@ -1,6 +1,8 @@ #define WANT_ARCAN_SHMIF_HELPER #include "../arcan_shmif.h" #include "../shmif_privext.h" +#include "../platform/shmif_platform.h" +#include "video_platform.h" bool platform_video_map_buffer( struct agp_vstore* vs, struct agp_buffer_plane* planes, size_t n) diff --git a/src/shmif/tui/core/screen.c b/src/shmif/tui/core/screen.c index a8d2fb9aa..b71a2cd10 100644 --- a/src/shmif/tui/core/screen.c +++ b/src/shmif/tui/core/screen.c @@ -9,6 +9,8 @@ typedef void* TTF_Font; #include "../raster/raster.h" #include "../raster/draw.h" +unsigned long long arcan_timemillis(); + static void resize_cellbuffer(struct tui_context* tui) { if (tui->base){ diff --git a/src/shmif/tui/core/setup.c b/src/shmif/tui/core/setup.c index db9445c7c..8ee71480e 100644 --- a/src/shmif/tui/core/setup.c +++ b/src/shmif/tui/core/setup.c @@ -1,7 +1,9 @@ #include "../../arcan_shmif.h" +#include "../../platform/shmif_platform.h" #include "../../arcan_tui.h" #include "../tui_int.h" -#include "arcan_ttf.h" + +typedef void* TTF_Font; #include "../raster/raster.h" #include diff --git a/src/shmif/tui/lua/tui_lua.c b/src/shmif/tui/lua/tui_lua.c index a62ae86ec..4160fe19d 100644 --- a/src/shmif/tui/lua/tui_lua.c +++ b/src/shmif/tui/lua/tui_lua.c @@ -1464,11 +1464,14 @@ static int tui_mkdtemp(lua_State* L) size_t tries = 10; while (work && tries-- > 0){ - uint8_t rng[6]; - arcan_random(rng, 6); - - for (size_t i = 0; i < 6; i++) - work[len-1-i] = (char)(rng[i] % 24) + 'a'; + union { + uint32_t rv; + uint8_t rng[4]; + } rval; + rval.rv = arc4random(); + + for (size_t i = 0; i < 4; i++) + work[len-1-i] = (char)(rval.rng[i] % 24) + 'a'; int status = mkdirat(ib->cwd_fd, work, 0700); if (0 == status){ diff --git a/src/shmif/tui/raster/fontmgmt.c b/src/shmif/tui/raster/fontmgmt.c index acbe2a630..2c14d4c2d 100644 --- a/src/shmif/tui/raster/fontmgmt.c +++ b/src/shmif/tui/raster/fontmgmt.c @@ -8,9 +8,11 @@ * and for substitution tables. */ #include +#define BADFD -1 -struct agp_vstore; #include "../../arcan_shmif.h" +#include "../../shmif/platform/shmif_platform.h" + #include "../../arcan_tui.h" #include "arcan_ttf.h" #include "../tui_int.h" diff --git a/src/shmif/tui/tui_int.h b/src/shmif/tui/tui_int.h index df4c493a7..84aae38f7 100644 --- a/src/shmif/tui/tui_int.h +++ b/src/shmif/tui/tui_int.h @@ -7,6 +7,10 @@ ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) #endif +#ifndef LOG +#define LOG(X, ...) fprintf(stderr, X, ## __VA_ARGS__) +#endif + enum dirty_state { DIRTY_NONE = 0, DIRTY_CURSOR = 1, diff --git a/src/wayland/waybridge.c b/src/wayland/waybridge.c index b2787b2ec..762f2648a 100644 --- a/src/wayland/waybridge.c +++ b/src/wayland/waybridge.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,8 @@ struct comp_surf; struct seat; +unsigned long long arcan_timemillis(); + /* * shared allocation functions, find_client takes a reference to a * wl client and tries to locate its bridge_client structure, or alloc diff --git a/src/wayland/xwlwm/xwlwm.c b/src/wayland/xwlwm/xwlwm.c index 2f386d46f..b0ce621f8 100644 --- a/src/wayland/xwlwm/xwlwm.c +++ b/src/wayland/xwlwm/xwlwm.c @@ -29,6 +29,8 @@ #include "uthash.h" +unsigned long long arcan_timemillis(); + static pthread_mutex_t logout_synch = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t wm_synch = PTHREAD_MUTEX_INITIALIZER; static pid_t exec_child = -1;