diff --git a/hi/img.c b/hi/img.c index 4d3b7bf..ad6af12 100644 --- a/hi/img.c +++ b/hi/img.c @@ -5,7 +5,7 @@ #include CUTIVIS CHiImage* CHi_Image_New(uint8_t bpc, uint8_t channels, uint16_t stride, uint16_t width, uint16_t height, void *data) { - CHiImage *img = malloc(sizeof(*img)); + CHiImage *img = calloc(1, sizeof(*img)); img->bpc = bpc; img->channels = channels; img->stride = stride; @@ -15,6 +15,8 @@ CUTIVIS CHiImage* CHi_Image_New(uint8_t bpc, uint8_t channels, uint16_t stride, else img->data16 = _mm_malloc(bpc * stride * height + 16, 16); img->owned = !data; + img->uuid = CHi_NextUUID(); + assert(stride % 16 == 0); return img; @@ -40,3 +42,8 @@ CUTIVIS void CHi_Restride(const void *oldbuf_, void *newbuf_, uint16_t oldStride memmove(&newbuf[newStride * row], &oldbuf[oldStride * row], oldStride); } } + +CUTIVIS size_t CHi_NextUUID() { + static size_t i = 0; + return i++; +} diff --git a/hi/img.h b/hi/img.h index b8fb0d8..f4ccf52 100644 --- a/hi/img.h +++ b/hi/img.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include"defs.h" @@ -18,6 +19,7 @@ typedef struct CHiImage { uint8_t *data8; }; uint8_t owned; + size_t uuid; } CHiImage; CUTIVIS CHiImage* CHi_Image_New(uint8_t bpc, uint8_t channels, uint16_t stride, uint16_t width, uint16_t height, void *data); @@ -25,6 +27,8 @@ CUTIVIS void CHi_Image_Free(CHiImage *img); CUTIVIS void CHi_Restride(const void *oldbuf, void *newbuf, uint16_t oldStride, uint16_t newStride, uint16_t rows); +CUTIVIS size_t CHi_NextUUID(); + #ifdef __cplusplus } #endif diff --git a/hi/node.c b/hi/node.c index dafb5ba..a17627c 100644 --- a/hi/node.c +++ b/hi/node.c @@ -522,14 +522,14 @@ typedef struct { CHiPubNode pubn; char *cachePath; CHiImage *cacheImg; -} ImageNode; +} ImageImpl; static int image_perform(CHiPubNode *node) { - ImageNode *internal = (ImageNode*) node; + ImageImpl *impl = node->impl; node->sources->type = CUTIHI_VAL_SAMPLE; const char *fn = node->sinks[CUTIHI_IMAGE_IN_FILE].data.text; - if(fn && (!internal->cachePath || strcmp(internal->cachePath, fn))) { + if(fn && (!impl->cachePath || strcmp(impl->cachePath, fn))) { if(node->sinks[CUTIHI_IMAGE_IN_FILE].type == CUTIHI_VAL_NONE) { return 1; } @@ -539,13 +539,13 @@ static int image_perform(CHiPubNode *node) { return 1; } - if(internal->cacheImg) { - CHi_Image_Free(internal->cacheImg); - internal->cacheImg = NULL; + if(impl->cacheImg) { + CHi_Image_Free(impl->cacheImg); + impl->cacheImg = NULL; } } - if(!internal->cacheImg) { + if(!impl->cacheImg) { size_t w = 0, h = 0, n = 4; float *data = stbi_loadf(fn, &w, &h, &n, 4); if(!data) { @@ -554,7 +554,7 @@ static int image_perform(CHiPubNode *node) { } CHiImage *img = CHi_Image_New(2, 4, (w * 8 + 15) & ~15, w, h, NULL); - internal->cacheImg = img; + impl->cacheImg = img; for(size_t y = 0; y < img->height; y++) { for(size_t x = 0; x < img->width; x++) { @@ -566,12 +566,12 @@ static int image_perform(CHiPubNode *node) { } } - free(internal->cachePath); - internal->cachePath = strdup(fn); + free(impl->cachePath); + impl->cachePath = strdup(fn); } if(CHi_Node_Active(node)) { - node->sources->data.sample = internal->cacheImg; + node->sources->data.sample = impl->cacheImg; } else { node->sources->data.sample = NULL; } @@ -579,15 +579,10 @@ static int image_perform(CHiPubNode *node) { return 1; } CUTIVIS CHiPubNode *CHi_Image() { - CHiPubNode *n = calloc(1, sizeof(ImageNode)); - n->type = CUTIHI_T('CIma','ge '); + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CIma','ge '), 1, 1, sizeof(ImageImpl)); n->Start = n->Stop = NULL; n->Perform = image_perform; - n->sinkCount = 1; - n->sinks = calloc(sizeof(*n->sinks), 1); - n->sourceCount = 1; - n->sources = calloc(sizeof(*n->sources), 1); - ((ImageNode*) n)->cachePath = strdup(""); + ((ImageImpl*) n->impl)->cachePath = strdup(""); return n; } @@ -638,32 +633,40 @@ static int embed_perform(CHiPubNode *node) { return 1; } CUTIVIS CHiPubNode *CHi_Embed() { - CHiPubNode *n = calloc(1, sizeof(*n)); - n->type = CUTIHI_T('CEmb','ed '); + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CEmb','ed '), 1 + 3 * CUTIHI_EMBED_MAX_SMALLS, 1, 0); n->Start = n->Stop = NULL; n->Perform = embed_perform; - n->sinks = calloc(sizeof(*n->sinks), n->sinkCount = 1 + 3 * CUTIHI_EMBED_MAX_SMALLS); - n->sources = calloc(sizeof(*n->sources), n->sourceCount = 1); return n; } +struct ConstantSampleImpl { + size_t cacheW; + size_t cacheH; + float cacheCol[4]; +}; static int constantsample_perform(CHiPubNode *node) { + struct ConstantSampleImpl *impl = node->impl; + node->sources[0].type = CUTIHI_VAL_SAMPLE; if(node->sources->data.sample) CHi_Image_Free(node->sources->data.sample); - CHiValue *sink = CHi_Crawl(&node->sinks[0]); + CHiValue *color = CHi_Crawl(&node->sinks[0]); CHiValue *sz = CHi_Crawl(&node->sinks[1]); size_t w = sz->data.vec4[0] < 1 ? 1 : sz->data.vec4[0]; size_t h = sz->data.vec4[1] < 1 ? 1 : sz->data.vec4[1]; + impl->cacheW = w; + impl->cacheH = h; + memcpy(impl->cacheCol, color->data.vec4, sizeof(impl->cacheCol)); + CHiImage *img = CHi_Image_New(2, 4, 8 * ((w + 1) & ~1), w, h, NULL); if(CHi_Node_Active(node)) { for(size_t y = 0; y < h; y++) { for(size_t x = 0; x < w; x++) { - img->data16[y * img->stride / 2 + x * 4 + 0] = sink->data.vec4[2] * 65535; - img->data16[y * img->stride / 2 + x * 4 + 1] = sink->data.vec4[1] * 65535; - img->data16[y * img->stride / 2 + x * 4 + 2] = sink->data.vec4[0] * 65535; + img->data16[y * img->stride / 2 + x * 4 + 0] = color->data.vec4[2] * 65535; + img->data16[y * img->stride / 2 + x * 4 + 1] = color->data.vec4[1] * 65535; + img->data16[y * img->stride / 2 + x * 4 + 2] = color->data.vec4[0] * 65535; img->data16[y * img->stride / 2 + x * 4 + 3] = 65535; } } @@ -673,18 +676,13 @@ static int constantsample_perform(CHiPubNode *node) { return 1; } CUTIVIS CHiPubNode *CHi_ConstantSample() { - CHiPubNode *n = calloc(1, sizeof(*n)); - n->type = CUTIHI_T('CCns','tCol'); + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CCns','tCol'), 2, 1, sizeof(struct ConstantSampleImpl)); n->Start = n->Stop = NULL; n->Perform = constantsample_perform; - n->sinkCount = 2; - n->sinks = calloc(sizeof(*n->sinks), n->sinkCount); - n->sourceCount = 1; - n->sources = calloc(sizeof(*n->sources), n->sourceCount); - n->sinks[0].type = CUTIHI_VAL_VEC4; - n->sinks[0].data.vec4[0] = 1280; - n->sinks[0].data.vec4[1] = 720; + n->sinks[1].type = CUTIHI_VAL_VEC4; + n->sinks[1].data.vec4[0] = 1280; + n->sinks[1].data.vec4[1] = 720; return n; } @@ -848,14 +846,9 @@ static int modulate_perform(CHiPubNode *node) { return 1; } CUTIVIS CHiPubNode *CHi_Modulate() { - CHiPubNode *n = calloc(1, sizeof(*n)); - n->type = CUTIHI_T('CMod','ulat'); + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CMod','ulat'), 4, 1, 0); n->Start = n->Stop = NULL; n->Perform = modulate_perform; - n->sinkCount = 4; - n->sinks = calloc(sizeof(*n->sinks), n->sinkCount); - n->sourceCount = 1; - n->sources = calloc(sizeof(*n->sources), n->sourceCount); n->sinks[0].type = CUTIHI_VAL_VEC4; n->sinks[0].data.vec4[0] = 1; @@ -885,14 +878,9 @@ CUTIVIS float CHi_Time_GetDelta(CHiNodeGraph *ng) { return ng->timedelta; } CUTIVIS CHiPubNode *CHi_Time() { - CHiPubNode *n = calloc(1, sizeof(*n)); - n->type = CUTIHI_T('CTim','e '); + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CTim','e '), 0, 1, 0); n->Start = n->Stop = NULL; n->Perform = time_perform; - n->sinkCount = 0; - n->sinks = NULL; - n->sourceCount = 1; - n->sources = calloc(sizeof(*n->sources), 1); return n; } @@ -1085,7 +1073,13 @@ CUTIVIS CHiPubNode *CHi_Preview() { return n; } +struct ChromaKeyImpl { + uint64_t cacheImg; + float cacheCol[4]; +}; static int chromakey_perform(CHiPubNode *n) { + struct ChromaKeyImpl *impl = n->impl; + CHiValue *sampleV = CHi_Crawl(&n->sinks[0]); CHiValue *colorV = CHi_Crawl(&n->sinks[1]); @@ -1099,6 +1093,9 @@ static int chromakey_perform(CHiPubNode *n) { CHi_Image_Free(n->sources[0].data.sample); } + impl->cacheImg = src->uuid; + memcpy(impl->cacheCol, colorV->data.vec4, sizeof(impl->cacheCol)); + n->sources[0].type = CUTIHI_VAL_SAMPLE; CHiImage *dst = n->sources[0].data.sample = CHi_Image_New(2, 4, (src->width * src->bpc * src->channels + 15) & ~15, src->width, src->height, NULL); @@ -1190,14 +1187,12 @@ static int chromakey_perform(CHiPubNode *n) { return 1; } CUTIVIS CHiPubNode *CHi_ChromaKey() { - CHiPubNode *n = calloc(1, sizeof(*n)); - n->type = CUTIHI_T('CChr','omaK'); + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CChr','omaK'), 2, 1, sizeof(struct ChromaKeyImpl)); n->Start = n->Stop = NULL; n->Perform = chromakey_perform; - n->sinks = calloc(sizeof(*n->sinks), n->sinkCount = 2); - n->sources = calloc(sizeof(*n->sources), n->sourceCount = 1); - n->sinks[1].type = CUTIHI_VAL_VEC4; // Default green + // Default green + n->sinks[1].type = CUTIHI_VAL_VEC4; n->sinks[1].data.vec4[0] = 0; n->sinks[1].data.vec4[1] = 1; n->sinks[1].data.vec4[2] = 0; @@ -1258,3 +1253,23 @@ CUTIVIS void CHi_AddError(CHiPubNode *node, const char *err, size_t sink) { } } } + +CUTIVIS CHiPubNode *CHi_AllocNode(uint64_t type, size_t sinkCount, size_t sourceCount, size_t implSize) { + CHiPubNode *n = calloc(1, sizeof(*n) + implSize); + if(!n) { + return NULL; + } + n->type = type; + n->sinks = calloc(n->sinkCount = sinkCount, sizeof(*n->sinks)); + if(!n->sinks) { + free(n); + return NULL; + } + n->sources = calloc(n->sourceCount = sourceCount, sizeof(*n->sources)); + if(!n->sources) { + free(n->sinks); + free(n); + return NULL; + } + return n; +} diff --git a/hi/node.h b/hi/node.h index d2461e3..26c8d65 100644 --- a/hi/node.h +++ b/hi/node.h @@ -84,8 +84,6 @@ typedef struct CHiPubNode { uint32_t flags; -#define CUTIHI_PERFORM_UPDATED 1 -#define CUTIHI_PERFORM_NOTUPDATED 0 int (*Perform)(struct CHiPubNode *node); int (*Start)(struct CHiPubNode *node); int (*Stop)(struct CHiPubNode *node); @@ -110,6 +108,8 @@ typedef struct CHiPubNode { } lifespan; char _dfsmark; + + uint8_t impl[]; } CHiPubNode; typedef enum { @@ -293,6 +293,8 @@ CUTIVIS void CHi_Node_Destroy(CHiPubNode*); CUTIVIS void CHi_AddError(CHiPubNode*, const char *err, size_t sink); +CUTIVIS CHiPubNode *CHi_AllocNode(uint64_t type, size_t sinkCount, size_t sourceCount, size_t implSize); + #ifdef __cplusplus } #endif diff --git a/hi/window_x11.cpp b/hi/window_x11.cpp index 4908f1d..5b830f9 100644 --- a/hi/window_x11.cpp +++ b/hi/window_x11.cpp @@ -20,8 +20,8 @@ #include"minitrace.h" -static Display *d; -static Window root; +static thread_local Display *d; +static thread_local Window root; static int find_window(Display *d, Window *w, const char *contains) { if(contains) { @@ -59,17 +59,20 @@ static int find_window(Display *d, Window *w, const char *contains) { } typedef struct { - CHiPubNode pub; - Window xcache; XImage *ximg; XShmSegmentInfo shminfo; CHiImage *vcache; -} CHiWindowNode; +} WindowImpl; static int window_perform(CHiPubNode *n) { - CHiWindowNode *w = (CHiWindowNode*) n; + auto *w = (WindowImpl*) n->impl; + + if(!d) { + d = XOpenDisplay(NULL); + root = RootWindow(d, DefaultScreen(d)); + } MTR_BEGIN("CHi", "window_perform"); @@ -100,7 +103,7 @@ static int window_perform(CHiPubNode *n) { XShmGetImage(d, w->xcache, w->ximg, 0, 0, AllPlanes); - bool ignoreAlpha = CHi_Crawl(&w->pub.sinks[1])->data.vec4[0] != 0; + bool ignoreAlpha = CHi_Crawl(&n->sinks[1])->data.vec4[0] != 0; // Turn u8 image to u16 #pragma omp parallel for @@ -125,7 +128,7 @@ static int window_perform(CHiPubNode *n) { } static void window_destroy(CHiPubNode *pubn) { - CHiWindowNode *n = (CHiWindowNode*) pubn; + auto *n = (WindowImpl*) pubn->impl; if(n->vcache) { XShmDetach(d, &n->shminfo); @@ -137,25 +140,11 @@ static void window_destroy(CHiPubNode *pubn) { } CUTIVIS CHiPubNode *CHi_Window() { - if(!d) { - d = XOpenDisplay(NULL); - root = RootWindow(d, DefaultScreen(d)); - } - - CHiWindowNode *n = (CHiWindowNode*) calloc(1, sizeof(*n)); - n->pub.type = CUTIHI_T('CWin','dow '); - n->pub.Start = n->pub.Stop = NULL; - n->pub.Perform = window_perform; - n->pub.Destroy = window_destroy; - n->pub.sinkCount = 1; - n->pub.sinks = (CHiValue*) calloc(sizeof(*n->pub.sinks), 2); - n->pub.sourceCount = 1; - n->pub.sources = (CHiValue*) calloc(sizeof(*n->pub.sources), 1); - - n->xcache = 0; - n->vcache = NULL; - - return &n->pub; + CHiPubNode *n = CHi_AllocNode(CUTIHI_T('CWin','dow '), 2, 1, sizeof(WindowImpl)); + n->Start = n->Stop = NULL; + n->Perform = window_perform; + n->Destroy = window_destroy; + return n; } // All of the following are ews @@ -165,6 +154,11 @@ struct WindowListDatum { char name[128]; }; CUTIVIS size_t CHi_Window_GetList(void **buf) { + if(!d) { + d = XOpenDisplay(NULL); + root = RootWindow(d, DefaultScreen(d)); + } + int found = 0; Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1); Atom actualType;