222 lines
5.2 KiB
C
222 lines
5.2 KiB
C
#include"node.h"
|
|
|
|
#include<stdlib.h>
|
|
|
|
#include<X11/Xlib.h>
|
|
#include<X11/Xutil.h>
|
|
#include<sys/ipc.h>
|
|
#include<sys/shm.h>
|
|
#include<X11/extensions/XShm.h>
|
|
#include<tmmintrin.h>
|
|
#include<smmintrin.h>
|
|
|
|
#include<time.h>
|
|
|
|
#include<string.h>
|
|
|
|
#include"img.h"
|
|
|
|
#include"linearity.h"
|
|
|
|
#include"minitrace.h"
|
|
|
|
static Display *d;
|
|
static Window root;
|
|
|
|
static int find_window(Display *d, Window *w, const char *contains) {
|
|
if(contains) {
|
|
int found = 0;
|
|
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
Atom actualType;
|
|
int format;
|
|
unsigned long numItems, bytesAfter;
|
|
|
|
Window *list;
|
|
XTextProperty windowName;
|
|
|
|
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
|
|
if(status >= Success) {
|
|
for(int i = 0; i < numItems; i++) {
|
|
status = XGetWMName(d, list[i], &windowName);
|
|
if(status >= Success) {
|
|
if(windowName.value && strstr(windowName.value, contains)) {
|
|
*w = list[i];
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
XFree(list);
|
|
|
|
return found;
|
|
} else {
|
|
*w = root;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
CHiPubNode pub;
|
|
|
|
Window xcache;
|
|
XImage *ximg;
|
|
XShmSegmentInfo shminfo;
|
|
|
|
CHiImage *vcache;
|
|
} CHiWindowNode;
|
|
|
|
static int window_perform(CHiPubNode *n) {
|
|
CHiWindowNode *w = (CHiWindowNode*) n;
|
|
|
|
MTR_BEGIN("CHi", "window_perform");
|
|
|
|
Window toshoot;
|
|
if(!find_window(d, &toshoot, CHi_Crawl(&n->sinks[0])->data.text)) return 0;
|
|
|
|
size_t stride;
|
|
if(!w->xcache || w->xcache != toshoot) {
|
|
w->xcache = toshoot;
|
|
|
|
XWindowAttributes attrs;
|
|
XGetWindowAttributes(d, toshoot, &attrs);
|
|
|
|
w->ximg = XShmCreateImage(d, attrs.visual, 32, ZPixmap, NULL, &w->shminfo, attrs.width, attrs.height);
|
|
stride = ((w->ximg->bytes_per_line + 15) & ~15);
|
|
w->shminfo.shmid = shmget(IPC_PRIVATE, stride * w->ximg->height, IPC_CREAT | 0777);
|
|
w->shminfo.shmaddr = w->ximg->data = shmat(w->shminfo.shmid, 0, 0);
|
|
w->shminfo.readOnly = False;
|
|
XShmAttach(d, &w->shminfo);
|
|
|
|
w->vcache = CHi_Image_New(2, 4, 8 * attrs.width, attrs.width, attrs.height, NULL);
|
|
} else {
|
|
stride = ((w->ximg->bytes_per_line + 15) & ~15);
|
|
}
|
|
|
|
XWindowAttributes toshootattrs;
|
|
XGetWindowAttributes(d, w->xcache, &toshootattrs);
|
|
|
|
XShmGetImage(d, w->xcache, w->ximg, 0, 0, AllPlanes);
|
|
|
|
// Turn u8 image to u16
|
|
#pragma omp parallel for
|
|
for(size_t y = 0; y < w->vcache->height; y++) {
|
|
for(size_t x = 0; x < w->vcache->width; x += 2) {
|
|
__m128i c = _mm_loadu_si128((__m128i*) ((uintptr_t) w->ximg->data + y * w->ximg->bytes_per_line + x * 4));
|
|
c = _mm_shuffle_epi8(c, _mm_set_epi8(7, -128, 6, -128, 5, -128, 4, -128, 3, -128, 2, -128, 1, -128, 0, -128));
|
|
c = apply_gamma_epi16(c, _mm_set_ps(1, 2.2f, 2.2f, 2.2f));
|
|
_mm_storeu_si128((__m128i*) ((uintptr_t) w->vcache->data16 + y * w->vcache->stride + x * 8), c);
|
|
}
|
|
}
|
|
|
|
n->sources[0].type = CUTIHI_VAL_SAMPLE;
|
|
n->sources[0].data.sample = w->vcache;
|
|
|
|
n->clean = 0;
|
|
|
|
MTR_END("CHi", "window_perform");
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void window_destroy(CHiPubNode *pubn) {
|
|
CHiWindowNode *n = (void*) pubn;
|
|
|
|
if(n->vcache) {
|
|
XShmDetach(d, &n->shminfo);
|
|
shmdt(n->shminfo.shmaddr);
|
|
XDestroyImage(n->ximg);
|
|
}
|
|
|
|
free(pubn);
|
|
}
|
|
|
|
CUTIVIS CHiPubNode *CHi_Window() {
|
|
if(!d) {
|
|
d = XOpenDisplay(NULL);
|
|
root = RootWindow(d, DefaultScreen(d));
|
|
}
|
|
|
|
CHiWindowNode *n = 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.clean = 0;
|
|
n->pub.sinkCount = 1;
|
|
n->pub.sinks = calloc(sizeof(*n->pub.sinks), 1);
|
|
n->pub.sourceCount = 1;
|
|
n->pub.sources = calloc(sizeof(*n->pub.sources), 1);
|
|
|
|
n->xcache = 0;
|
|
n->vcache = NULL;
|
|
|
|
return &n->pub;
|
|
}
|
|
|
|
// All of the following are ews
|
|
|
|
CUTIVIS size_t CHi_Window_GetSourceCount() {
|
|
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
Atom actualType;
|
|
int format;
|
|
unsigned long numItems, bytesAfter;
|
|
|
|
Window *list;
|
|
|
|
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
|
|
XFree(list);
|
|
|
|
return status >= Success ? numItems : 0;
|
|
}
|
|
|
|
CUTIVIS const char *CHi_Window_GetSourceName(size_t idx) {
|
|
int found = 0;
|
|
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
Atom actualType;
|
|
int format;
|
|
unsigned long numItems, bytesAfter;
|
|
|
|
Window *list;
|
|
XTextProperty windowName;
|
|
|
|
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
|
|
if(status >= Success) {
|
|
XFree(list);
|
|
|
|
status = XGetWMName(d, list[idx], &windowName);
|
|
if(status >= Success) {
|
|
found = 1;
|
|
}
|
|
}
|
|
|
|
return found ? strdup(windowName.value ? windowName.value : "") : NULL;
|
|
}
|
|
|
|
CUTIVIS uintptr_t CHi_Window_GetSourceData(size_t idx) {
|
|
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
Atom actualType;
|
|
int format;
|
|
unsigned long numItems, bytesAfter;
|
|
|
|
Window *list;
|
|
|
|
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
|
|
if(status >= Success) {
|
|
Window ret = list[idx];
|
|
XFree(list);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
CUTIVIS size_t CHi_Window_GetNextSource(size_t i) {
|
|
return i + 1;
|
|
}
|