diff --git a/renderdoccmd/Makefile b/renderdoccmd/Makefile index e8d0db556..94af9eff2 100644 --- a/renderdoccmd/Makefile +++ b/renderdoccmd/Makefile @@ -6,7 +6,7 @@ MACROS=-DLINUX \ -DGIT_COMMIT_HASH="\"$(COMMIT)\"" CFLAGS=-c -Wall -Werror -fPIC $(MACROS) -I../renderdoc/api/ CPPFLAGS=-std=c++11 -g -Wno-unused -Wno-unknown-pragmas -Wno-reorder -LDFLAGS=-L../renderdoc/ -lrenderdoc -lGL -lX11 -Wl,-rpath,'$$ORIGIN/' +LDFLAGS=-L../renderdoc/ -lrenderdoc -lGL -lxcb -Wl,-rpath,'$$ORIGIN/' OBJDIR=.obj OBJECTS=renderdoccmd.o renderdoccmd_linux.o diff --git a/renderdoccmd/renderdoccmd_linux.cpp b/renderdoccmd/renderdoccmd_linux.cpp index 717be9ef2..9076da509 100644 --- a/renderdoccmd/renderdoccmd_linux.cpp +++ b/renderdoccmd/renderdoccmd_linux.cpp @@ -28,10 +28,7 @@ #include #include -#include -#include -#include -#include +#include #include @@ -49,49 +46,58 @@ string GetUsername() void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay displayCfg) { - Display *dpy = XOpenDisplay(NULL); + int scr; - if(dpy == NULL) return; + xcb_connection_t *connection = xcb_connect(NULL, &scr); + const xcb_setup_t *setup = xcb_get_setup(connection); + xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); + while (scr-- > 0) xcb_screen_next(&iter); - static int visAttribs[] = { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DOUBLEBUFFER, True, - 0 - }; - int numCfgs = 0; - GLXFBConfig *fbcfg = glXChooseFBConfig(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); + xcb_screen_t *screen = iter.data; - if(fbcfg == NULL) - { - XCloseDisplay(dpy); - return; - } + uint32_t value_mask, value_list[32]; - XVisualInfo *vInfo = glXGetVisualFromFBConfig(dpy, fbcfg[0]); + xcb_window_t window = xcb_generate_id(connection); - XSetWindowAttributes swa = {0}; - swa.event_mask = StructureNotifyMask; - swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vInfo->screen), vInfo->visual, AllocNone); + value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + value_list[0] = screen->black_pixel; + value_list[1] = XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY; - Window win = XCreateWindow(dpy, RootWindow(dpy, vInfo->screen), 200, 200, 1280, 720, - 0, vInfo->depth, InputOutput, vInfo->visual, - CWBorderPixel | CWColormap | CWEventMask, &swa); + xcb_create_window(connection, + XCB_COPY_FROM_PARENT, + window, screen->root, + 0, 0, 1280, 720, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + value_mask, value_list); - XStoreName(dpy, win, "renderdoccmd"); - XMapWindow(dpy, win); + /* Magic code that will send notification when window is destroyed */ + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, 1, 12, + "WM_PROTOCOLS"); + xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(connection, cookie, 0); - //GLXWindow glwnd = glXCreateWindow(dpy, fbcfg[0], win, NULL); + xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(connection, 0, 16, "WM_DELETE_WINDOW"); + xcb_intern_atom_reply_t *atom_wm_delete_window = xcb_intern_atom_reply(connection, cookie2, 0); - //void *displayAndDrawable[] = { (void *)dpy, (void *)glwnd }; + xcb_change_property (connection, + XCB_PROP_MODE_REPLACE, + window, + XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, + 8, + sizeof ("renderdoccmd")-1, + "renderdoccmd" ); - void *displayAndDrawable[] = { (void *)dpy, (void *)win }; + xcb_change_property(connection, XCB_PROP_MODE_REPLACE, + window, (*reply).atom, 4, 32, 1, + &(*atom_wm_delete_window).atom); + free(reply); + + xcb_map_window(connection, window); + + void *displayAndDrawable[] = { (void *)connection, (void *)screen, (void *)(size_t)window }; ReplayOutput *out = ReplayRenderer_CreateOutput(renderer, displayAndDrawable); @@ -100,24 +106,50 @@ void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay displayCfg) ReplayOutput_SetOutputConfig(out, c); ReplayOutput_SetTextureDisplay(out, displayCfg); + xcb_flush(connection); + bool done = false; while(!done) { - while(XPending(dpy) > 0) + xcb_generic_event_t *event; + + event = xcb_poll_for_event(connection); + if (event) { - XEvent event = {0}; - XNextEvent(dpy, &event); - switch(event.type) + switch (event->response_type & 0x7f) { - case ButtonPress: done = true; - default: break; + case XCB_EXPOSE: + ReplayRenderer_SetFrameEvent(renderer, 0, 10000000+rand()%1000); + ReplayOutput_Display(out); + break; + case XCB_CLIENT_MESSAGE: + if((*(xcb_client_message_event_t*)event).data.data32[0] == + (*atom_wm_delete_window).atom) { + done = true; + } + break; + case XCB_KEY_RELEASE: + { + const xcb_key_release_event_t *key = + (const xcb_key_release_event_t *) event; + + if (key->detail == 0x9) + done = true; + } + break; + case XCB_DESTROY_NOTIFY: + done = true; + break; + default: + break; } + free(event); } ReplayRenderer_SetFrameEvent(renderer, 0, 10000000+rand()%1000); ReplayOutput_Display(out); - usleep(40000); + usleep(100000); } }