#include #include #include #include #include #include #include #include #include #include #include #include #include /** * GL Extensions */ PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR; PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR; PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC eglGetStreamFileDescriptorKHR; PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquireKHR; PFNEGLQUERYSTREAMKHRPROC eglQueryStreamKHR; PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC eglCreateStreamFromFileDescriptorKHR; PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR; /** * X11 Window and basic OpenGL */ char windowCaption[50]; const char windowCaptionTemplate[] = "OpenGL Skeleton Application (%.2f FPS)"; Display *display; Window rootWindow; XWindowAttributes xWindowsAttributes; Window mainWindow; XSetWindowAttributes xSetWindowsAttributes; XEvent xEvent; Atom wmDeleteWindow; XVisualInfo *xVisualInfo; GLint glAtt[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; GLXContext glXContext; GLuint videoTexture; Bool isFullscreen; Bool running; /** * EGLStream */ EGLDisplay eglDisplay; EGLStreamKHR eglStream; EGLint eglStreamAttr[] = { EGL_NONE }; /** * Time & FPS */ struct timeval startTime; float timeCounter; float lastFrameTime; float fps; float lastFpsUpdate; /** * Keyboard */ Bool keyStateShift; Bool keyStateCtrl; Bool keyStateAlt; Bool keyStateAltGr; void setupTimeFps(void) { lastFrameTime = 0.0; fps = 0.0; lastFpsUpdate = 0.0; gettimeofday(&startTime, NULL); } void setupKeyboard(void) { keyStateShift = False; keyStateCtrl = False; keyStateAlt = False; keyStateAltGr = False; } void setupEgl(void) { eglCreateStreamKHR = eglGetProcAddress("eglCreateStreamKHR"); eglStreamConsumerGLTextureExternalKHR = eglGetProcAddress("eglStreamConsumerGLTextureExternalKHR"); eglGetStreamFileDescriptorKHR = eglGetProcAddress("eglGetStreamFileDescriptorKHR"); eglStreamConsumerAcquireKHR = eglGetProcAddress("eglStreamConsumerAcquireKHR"); eglQueryStreamKHR = eglGetProcAddress("eglQueryStreamKHR"); eglCreateStreamFromFileDescriptorKHR = eglGetProcAddress("eglCreateStreamFromFileDescriptorKHR"); eglCreateStreamProducerSurfaceKHR = eglGetProcAddress("eglCreateStreamProducerSurfaceKHR"); eglDisplay = eglGetDisplay(display); int err = eglGetError(); if (eglDisplay == EGL_NO_DISPLAY) { printf("ERROR: Failed to get egl display (0x%04x)\n", eglGetError()); exit(1); } if (!eglInitialize(eglDisplay, NULL, NULL)) { printf("ERROR: Failed to initialize egl (0x%04x)\n", eglGetError()); exit(1); } eglStream = eglCreateStreamKHR(eglDisplay, eglStreamAttr); if (eglStream == EGL_NO_STREAM_KHR) { printf("ERROR: Failed to create egl stream (0x%04x)\n", eglGetError()); exit(1); } EGLint val; eglQueryStreamKHR(eglDisplay, eglStream, EGL_STREAM_STATE_KHR, &val); printf("Stream state: 0x%04x\n", val); if (!eglStreamConsumerGLTextureExternalKHR(eglDisplay, eglStream)) { printf("ERROR: Failed to bind texture (0x%04x)\n", eglGetError()); exit(1); } /* int eglStreamFD = eglGetStreamFileDescriptorKHR(eglDisplay, eglStreamConsumer); if (eglStreamFD == EGL_NO_FILE_DESCRIPTOR_KHR) { printf("ERROR: Couldn't get stream file descriptor (%i).\n", eglGetError()); exit(1); } /* if (!eglStreamConsumerAcquireKHR(eglDisplay, eglStream)) { EGLint state = 0; eglQueryStreamKHR(eglDisplay, eglStream, EGL_STREAM_STATE_KHR, &state); switch (state) { case EGL_STREAM_STATE_DISCONNECTED_KHR: printf("Lost connection with fd %d.\n", eglStreamFD); break; case EGL_STREAM_STATE_EMPTY_KHR: printf("Stream fd is empty %d.\n", eglStreamFD); break; case EGL_STREAM_STATE_CONNECTING_KHR: printf("Stream %d is connecting.\n", eglStreamFD); break; case EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR: printf("Stream %d new frame` available.\n", eglStreamFD); break; default: printf("Unexpected stream state: 0x%04x.\n", state); break; } exit(1); } */ /* eglStreamProducer = eglCreateStreamFromFileDescriptorKHR(eglDisplay, eglStreamFD); if (eglStreamProducer == NULL) { printf("ERROR: Failed to create egl stream from fd (0x%04x)\n", eglGetError()); exit(1); } */ /* char * ch; CUeglStreamConnection conn; CUresult r = cuEGLStreamProducerConnect(&conn, eglStream, 256, 256); cuGetErrorName(r, &ch); if (r != 0) { printf("ERROR: Failed to connect producer to the stream (0x%04x): %s\n", r, ch); exit(1); } */ /* void * buffer; cudaEglFrame * cudaEgl; cudaEgl = (cudaEglFrame *)malloc(sizeof(cudaEglFrame)); cudaEgl->frameType = cudaEglFrameTypePitch; cudaEgl->eglColorFormat = cudaEglColorFormatARGB; cudaEgl->planeCount = 1; cudaEgl->planeDesc[0].width = 256; cudaEgl->planeDesc[0].height = 256; cudaEgl->planeDesc[0].depth = 0; cudaEgl->planeDesc[0].numChannels = 4; cudaEgl->planeDesc[0].pitch = cudaEgl->planeDesc[0].width * cudaEgl->planeDesc[0].numChannels; cudaEgl->planeDesc[0].channelDesc.f = cudaChannelFormatKindUnsigned; cudaEgl->planeDesc[0].channelDesc.w = 8; cudaEgl->planeDesc[0].channelDesc.x = 8; cudaEgl->planeDesc[0].channelDesc.y = 8; cudaEgl->planeDesc[0].channelDesc.z = 8; size_t numElem = cudaEgl->planeDesc[0].pitch * cudaEgl->planeDesc[0].height; cudaMalloc(&buffer, numElem); if (cudaGetLastError() != 0) { printf("ERROR: Failed to create allocate cuda memory (0x%04x)\n", cudaGetLastError()); exit(1); } */ } /** * */ void setupX11OpenGL(void) { glXSwapIntervalEXT = glXGetProcAddressARB("glXSwapIntervalEXT"); display = XOpenDisplay(NULL); if (display == NULL) { printf("ERROR: Cannot connect to X server\n"); exit(1); } rootWindow = DefaultRootWindow(display); xVisualInfo = glXChooseVisual(display, 0, glAtt); if (xVisualInfo == NULL) { printf("ERROR: No appropriate visual found\n"); exit(2); } xSetWindowsAttributes.colormap = XCreateColormap(display, rootWindow, xVisualInfo, AllocNone); xSetWindowsAttributes.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask; mainWindow = XCreateWindow( display, rootWindow, 0, 0, 600, 600, 0, xVisualInfo->depth, InputOutput, xVisualInfo->visual, CWColormap | CWEventMask, &xSetWindowsAttributes ); XMapWindow(display, mainWindow); sprintf(windowCaption, windowCaptionTemplate, fps); XStoreName(display, mainWindow, windowCaption); glXContext = glXCreateContext(display, xVisualInfo, NULL, GL_TRUE); glXMakeCurrent(display, mainWindow, glXContext); glEnable(GL_DEPTH_TEST); wmDeleteWindow = XInternAtom(display, "WM_DELETE_WINDOW", False); XSetWMProtocols(display, mainWindow, &wmDeleteWindow, True); glGenTextures(1, &videoTexture); if (glGetError() != 0) { printf("Failed to generate texture (0x%04x)\n", glGetError()); exit(1); } videoTexture = -1; glBindTexture(GL_TEXTURE_EXTERNAL_OES, videoTexture); if (glGetError() != 0) { printf("Failed to bind ext oes texture (0x%04x)\n", glGetError()); exit(1); } glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); if (glGetError() != 0) { printf("Failed to set texturing params (0x%04x)\n", glGetError()); exit(1); } glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (glGetError() != 0) { printf("Failed to set texturing params (0x%04x)\n", glGetError()); exit(1); } glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (glGetError() != 0) { printf("Failed to set texturing params (0x%04x)\n", glGetError()); exit(1); } glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if (glGetError() != 0) { printf("Failed to set texturing params (0x%04x)\n", glGetError()); exit(1); } } /** * */ void cleanup(void) { glXMakeCurrent(display, None, NULL); glXDestroyContext(display, glXContext); XDestroyWindow(display, mainWindow); XCloseDisplay(display); } /** * */ void update(void) { struct timeval tv; gettimeofday(&tv, NULL); timeCounter = (float)(tv.tv_sec - startTime.tv_sec) + 0.000001 * ((float)(tv.tv_usec - startTime.tv_usec)); float frameDuration = timeCounter - lastFrameTime; fps = frameDuration < 1 ? (float)(1 / frameDuration) : 0.0; lastFrameTime = timeCounter; if (timeCounter - lastFpsUpdate > 1.0) { sprintf(windowCaption, windowCaptionTemplate, fps); XStoreName(display, mainWindow, windowCaption); lastFpsUpdate = timeCounter; } } /** * */ void render(void) { glClearColor(0.1, 0.1, 0.2, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glBegin(GL_QUADS); glColor3f(1.0, 0.0, 0.0); glVertex3f(-0.5, -0.5, 0.0); glColor3f(0.0, 1.0, 0.0); glVertex3f( 0.5, -0.5, 0.0); glColor3f(0.0, 0.0, 1.0); glVertex3f( 0.5, 0.5, 0.0); glColor3f(1.0, 1.0, 0.0); glVertex3f(-0.5, 0.5, 0.0); glEnd(); glXSwapBuffers(display, mainWindow); } /** * */ void toggleFullScreen(void) { Atom netWmState = XInternAtom(display, "_NET_WM_STATE", False); Atom netWmFullScreen = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", False); isFullscreen = !isFullscreen; memset(&xEvent, 0, sizeof(xEvent)); xEvent.type = ClientMessage; xEvent.xclient.window = mainWindow; xEvent.xclient.message_type = netWmState; xEvent.xclient.format = 32; xEvent.xclient.data.l[0] = isFullscreen; xEvent.xclient.data.l[1] = netWmFullScreen; xEvent.xclient.data.l[2] = 0; XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xEvent); if (glXSwapIntervalEXT != NULL) { glXSwapIntervalEXT(display, glXGetCurrentDrawable(), !isFullscreen); } } void handleKeyboardEvent(XEvent event) { switch (event.type) { case KeyPress: switch(XLookupKeysym(&event.xkey, 0)) { case XK_Shift_L: case XK_Shift_R: keyStateShift = True; break; case XK_Control_L: case XK_Control_R: keyStateCtrl = True; break; case XK_Alt_L: keyStateAlt = True; break; case XK_Alt_R: keyStateAltGr = True; break; case XK_Escape: running = False; break; case XK_Return: if (keyStateAlt) toggleFullScreen(); break; } break; case KeyRelease: switch(XLookupKeysym(&event.xkey, 0)) { case XK_Shift_L: case XK_Shift_R: keyStateShift = False; break; case XK_Control_L: case XK_Control_R: keyStateCtrl = False; break; case XK_Alt_L: keyStateAlt = False; break; case XK_Alt_R: keyStateAltGr = False; break; } break; } } /** * */ int main(int argc, char *argv[]) { setupX11OpenGL(); setupTimeFps(); setupKeyboard(); setupEgl(); isFullscreen = False; running = True; while(running) { if (XCheckWindowEvent(display, mainWindow, -1, &xEvent)) { switch (xEvent.type) { case Expose: XGetWindowAttributes(display, mainWindow, &xWindowsAttributes); glViewport(0, 0, xWindowsAttributes.width, xWindowsAttributes.height); break; case KeyPress: case KeyRelease: handleKeyboardEvent(xEvent); break; default: break; } } if (XCheckTypedWindowEvent(display, mainWindow, ClientMessage, &xEvent)) { if ((Atom)(xEvent.xclient.data.l[0]) == wmDeleteWindow) running = False; } if (running) { update(); render(); } } cleanup(); }