static void X11_ReleaseBackBuffer (GF_VideoOutput * vout) { X11VID (); #ifdef GPAC_HAS_X11_SHM if (xWindow->shmseginfo) XShmDetach (xWindow->display, xWindow->shmseginfo); if (xWindow->pixmap) { XFreePixmap(xWindow->display, xWindow->pixmap); xWindow->pixmap = 0L; xWindow->pwidth = xWindow->pheight = 0; } else { if (xWindow->surface) XDestroyImage(xWindow->surface); xWindow->surface = NULL; } if (xWindow->shmseginfo) { if (xWindow->shmseginfo->shmaddr) shmdt(xWindow->shmseginfo->shmaddr); if (xWindow->shmseginfo->shmid >= 0) shmctl (xWindow->shmseginfo->shmid, IPC_RMID, NULL); gf_free(xWindow->shmseginfo); xWindow->shmseginfo = NULL; } #endif if (xWindow->surface) { if (xWindow->surface->data) gf_free(xWindow->surface->data); XFree(xWindow->surface); xWindow->surface = NULL; } xWindow->is_init = 0; #ifdef GPAC_HAS_X11_XV X11_DestroyOverlay(xWindow); #endif }
/* Shutdown X11 */ void X11_Shutdown (struct _video_out *vout) { X11VID (); if (xWindow->output_3d_mode==1) { #ifdef GPAC_HAS_OPENGL X11_ReleaseGL(xWindow); #endif } else { X11_ReleaseBackBuffer (vout); } #ifdef GPAC_HAS_OPENGL if (xWindow->glx_visualinfo) XFree(xWindow->glx_visualinfo); xWindow->glx_visualinfo = NULL; #endif XFreeGC (xWindow->display, xWindow->the_gc); XUnmapWindow (xWindow->display, (Window) xWindow->wnd); XDestroyWindow (xWindow->display, (Window) xWindow->wnd); XDestroyWindow (xWindow->display, (Window) xWindow->full_wnd); #ifdef GPAC_HAS_OPENGL if (xWindow->gl_offscreen) glXDestroyGLXPixmap(xWindow->display, xWindow->gl_offscreen); if (xWindow->gl_pixmap) XFreePixmap(xWindow->display, xWindow->gl_pixmap); XUnmapWindow (xWindow->display, (Window) xWindow->gl_wnd); XDestroyWindow (xWindow->display, (Window) xWindow->gl_wnd); #endif /*restore xscreen saver*/ X11_XScreenSaverState(xWindow, 1); XCloseDisplay (xWindow->display); gf_free(xWindow); }
static void X11_ReleaseBackBuffer (GF_VideoOutput * vout) { X11VID (); if (xWindow->is_init == 1) { switch (xWindow->videoaccesstype) { #ifdef GPAC_HAS_X11_SHM case VIDEO_XI_SHMSTD: XShmDetach (xWindow->display, xWindow->shmseginfo); if (xWindow->surface) XDestroyImage(xWindow->surface); xWindow->surface = NULL; if (xWindow->shmseginfo->shmaddr) shmdt(xWindow->shmseginfo->shmaddr); if (xWindow->shmseginfo->shmid >= 0) shmctl (xWindow->shmseginfo->shmid, IPC_RMID, NULL); free (xWindow->shmseginfo); xWindow->shmseginfo = NULL; break; case VIDEO_XI_SHMPIXMAP: XShmDetach(xWindow->display, xWindow->shmseginfo); XFreePixmap(xWindow->display, xWindow->pixmap); if (xWindow->shmseginfo->shmaddr) shmdt (xWindow->shmseginfo->shmaddr); if (xWindow->shmseginfo->shmid >= 0) shmctl (xWindow->shmseginfo->shmid, IPC_RMID, NULL); free (xWindow->shmseginfo); xWindow->shmseginfo = NULL; break; #endif case VIDEO_XI_STANDARD: if (xWindow->back_buffer->buffer) free (xWindow->back_buffer->buffer); xWindow->back_buffer->buffer = NULL; if (xWindow->surface) XFree(xWindow->surface); xWindow->surface = NULL; break; } xWindow->is_init = 0; } }
/* * lock video mem */ GF_Err X11_LockBackBuffer(struct _video_out * vout, GF_VideoSurface * vi, u32 do_lock) { X11VID (); if (do_lock) { if (!vi) return GF_BAD_PARAM; if (xWindow->surface) { vi->width = xWindow->surface->width; vi->height = xWindow->surface->height; vi->pitch_x = xWindow->bpp; vi->pitch_y = xWindow->surface->width*xWindow->bpp; vi->pixel_format = xWindow->pixel_format; vi->video_buffer = xWindow->surface->data; } else { #ifdef GPAC_HAS_X11_SHM vi->width = xWindow->pwidth; vi->height = xWindow->pheight; vi->pitch_x = xWindow->bpp; vi->pitch_y = xWindow->pwidth*xWindow->bpp; vi->pixel_format = xWindow->pixel_format; vi->video_buffer = (unsigned char *) xWindow->shmseginfo->shmaddr; #endif } vi->is_hardware_memory = (xWindow->use_shared_memory) ? 1 : 0; return GF_OK; } else { return GF_OK; } }
/* * resize buffer: note we don't resize window here */ GF_Err X11_ResizeBackBuffer (struct _video_out *vout, u32 newWidth, u32 newHeight) { X11VID (); if ((newWidth != xWindow->back_buffer->width) || (newHeight != xWindow->back_buffer->height)) { if ((newWidth >= 32) && (newHeight >= 32)) return X11_InitBackBuffer (vout, newWidth, newHeight); } return GF_OK; }
GF_Err X11_ProcessEvent (struct _video_out * vout, GF_Event * evt) { X11VID (); if (!xWindow->setup_done) X11_SetupWindow(vout); if (evt) { switch (evt->type) { case GF_EVENT_SET_CURSOR: break; case GF_EVENT_SET_CAPTION: if (!xWindow->par_wnd) XStoreName (xWindow->display, xWindow->wnd, evt->caption.caption); break; case GF_EVENT_SHOWHIDE: break; case GF_EVENT_SIZE: /*if owning the window and not in fullscreen, resize it (initial scene size)*/ xWindow->w_width = evt->size.width; xWindow->w_height = evt->size.height; if (!xWindow->fullscreen) { if (xWindow->par_wnd) { XWindowAttributes pwa; XGetWindowAttributes(xWindow->display, xWindow->par_wnd, &pwa); XMoveResizeWindow(xWindow->display, xWindow->wnd, pwa.x, pwa.y, evt->size.width, evt->size.height); if (!xWindow->no_select_input) XSetInputFocus(xWindow->display, xWindow->wnd, RevertToNone, CurrentTime); } else { XResizeWindow (xWindow->display, xWindow->wnd, evt->size.width, evt->size.height); } } break; case GF_EVENT_VIDEO_SETUP: switch (evt->setup.opengl_mode){ #ifdef GPAC_HAS_OPENGL case 1: xWindow->output_3d_mode = 1; return X11_SetupGL(vout); case 2: xWindow->output_3d_mode = 2; return X11_SetupGLPixmap(vout, evt->setup.width, evt->setup.height); #endif case 0: xWindow->output_3d_mode = 0; return X11_ResizeBackBuffer(vout, evt->setup.width, evt->setup.height); default: return GF_NOT_SUPPORTED; } } } else { X11_HandleEvents(vout); } return GF_OK; }
/* * resize buffer: note we don't resize window here */ GF_Err X11_ResizeBackBuffer (struct _video_out *vout, u32 newWidth, u32 newHeight) { X11VID (); u32 w = xWindow->surface ? xWindow->surface->width : xWindow->pwidth; u32 h = xWindow->surface ? xWindow->surface->height : xWindow->pheight; if (!xWindow->is_init || (newWidth != w) || (newHeight != h)) { if ((newWidth >= 32) && (newHeight >= 32)) return X11_InitBackBuffer (vout, newWidth, newHeight); } return GF_OK; }
GF_Err X11_Setup(struct _video_out *vout, void *os_handle, void *os_display, u32 flags) { X11VID (); /*assign window if any, NEVER display*/ xWindow->par_wnd = (Window) os_handle; xWindow->init_flags = flags; /*OSMOZILLA HACK*/ if (os_display) xWindow->no_select_input = 1; /*the rest is done THROUGH THE MAIN RENDERER TRHEAD!!*/ return GF_OK; }
/* switch from/to full screen mode */ GF_Err X11_SetFullScreen (struct _video_out * vout, u32 bFullScreenOn, u32 * screen_width, u32 * screen_height) { X11VID (); xWindow->fullscreen = bFullScreenOn; #ifdef GPAC_HAS_OPENGL if (xWindow->output_3d_mode==1) X11_ReleaseGL(xWindow); #endif if (bFullScreenOn) { xWindow->store_width = *screen_width; xWindow->store_height = *screen_height; xWindow->w_width = vout->max_screen_width; xWindow->w_height = vout->max_screen_height; XFreeGC (xWindow->display, xWindow->the_gc); xWindow->the_gc = XCreateGC (xWindow->display, xWindow->full_wnd, 0, NULL); XMoveResizeWindow (xWindow->display, (Window) xWindow->full_wnd, 0, 0, vout->max_screen_width, vout->max_screen_height); *screen_width = xWindow->w_width; *screen_height = xWindow->w_height; XUnmapWindow (xWindow->display, xWindow->wnd); XMapWindow (xWindow->display, xWindow->full_wnd); XSetInputFocus(xWindow->display, xWindow->full_wnd, RevertToNone, CurrentTime); XRaiseWindow(xWindow->display, xWindow->full_wnd); XGrabKeyboard(xWindow->display, xWindow->full_wnd, True, GrabModeAsync, GrabModeAsync, CurrentTime); } else { *screen_width = xWindow->store_width; *screen_height = xWindow->store_height; XFreeGC (xWindow->display, xWindow->the_gc); xWindow->the_gc = XCreateGC (xWindow->display, xWindow->wnd, 0, NULL); XUnmapWindow (xWindow->display, xWindow->full_wnd); XMapWindow (xWindow->display, xWindow->wnd); XUngrabKeyboard(xWindow->display, CurrentTime); /*looks like this makes osmozilla crash*/ //if (xWindow->par_wnd) XSetInputFocus(xWindow->display, xWindow->wnd, RevertToNone, CurrentTime); /*backbuffer resize will be done right after this is called */ } #ifdef GPAC_HAS_OPENGL if (xWindow->output_3d_mode==1) X11_SetupGL(vout); #endif return GF_OK; }
/* * lock video mem */ GF_Err X11_LockBackBuffer(struct _video_out * vout, GF_VideoSurface * vi, u32 do_lock) { X11VID (); if (do_lock) { if (!vi) return GF_BAD_PARAM; vi->width = xWindow->back_buffer->width; vi->height = xWindow->back_buffer->height; vi->pitch = xWindow->back_buffer->pitch; vi->pixel_format = xWindow->pixel_format; vi->video_buffer = xWindow->back_buffer->buffer; vi->is_hardware_memory = (xWindow->videoaccesstype==VIDEO_XI_STANDARD) ? 0 : 1; return GF_OK; } else { return GF_OK; } }
/* Shutdown X11 */ void X11_Shutdown (struct _video_out *vout) { X11VID (); if (xWindow->is_3D_out) { #ifdef GPAC_HAS_OPENGL X11_ReleaseGL(xWindow); #endif } else { X11_ReleaseBackBuffer (vout); } free(xWindow->back_buffer); XFreeGC (xWindow->display, xWindow->the_gc); XUnmapWindow (xWindow->display, (Window) xWindow->wnd); XDestroyWindow (xWindow->display, (Window) xWindow->wnd); XDestroyWindow (xWindow->display, (Window) xWindow->full_wnd); XCloseDisplay (xWindow->display); free (xWindow); }
GF_Err X11_Setup(struct _video_out *vout, void *os_handle, void *os_display, u32 no_proc_override, GF_GLConfig * cfg) { X11VID (); /*assign window if any, NEVER display*/ xWindow->par_wnd = (Window) os_handle; /*OSMOZILLA HACK*/ if (os_display) xWindow->no_select_input = 1; if (cfg) { #ifdef GPAC_HAS_OPENGL xWindow->is_3D_out = 1; xWindow->gl_cfg = *cfg; #else return GF_NOT_SUPPORTED; #endif } else { xWindow->is_3D_out = 0; } /*the rest is done THROUGH THE MAIN RENDERER TRHEAD!!*/ return GF_OK; }
//===================================== GF_Err X11_Flush(struct _video_out *vout, GF_Window * dest) { Window cur_wnd; /* * write backbuffer to screen */ X11VID (); XSync(xWindow->display, False); if (!xWindow->is_init) return GF_OK; cur_wnd = xWindow->fullscreen ? xWindow->full_wnd : xWindow->wnd; if (xWindow->is_3D_out) { #ifdef GPAC_HAS_OPENGL glXSwapBuffers(xWindow->display, cur_wnd); #endif return GF_OK; } switch (xWindow->videoaccesstype) { #ifdef GPAC_HAS_X11_SHM case VIDEO_XI_SHMSTD: XShmPutImage (xWindow->display, cur_wnd, xWindow->the_gc, xWindow->surface, 0, 0, dest->x, dest->y, dest->w, dest->h, True); break; case VIDEO_XI_SHMPIXMAP: XClearWindow(xWindow->display, cur_wnd); break; #endif case VIDEO_XI_STANDARD: XRaiseWindow(xWindow->display, xWindow->wnd); XPutImage (xWindow->display, cur_wnd, xWindow->the_gc, xWindow->surface, 0, 0, dest->x, dest->y, dest->w, dest->h); break; } return GF_OK; }
/*Flush video */ GF_Err X11_Flush(struct _video_out *vout, GF_Window * dest) { Window cur_wnd; /* * write backbuffer to screen */ X11VID (); if (!xWindow->is_init) return GF_OK; cur_wnd = xWindow->fullscreen ? xWindow->full_wnd : xWindow->wnd; if (xWindow->output_3d_mode==1) { #ifdef GPAC_HAS_OPENGL XSync(xWindow->display, False); glFlush(); glXSwapBuffers(xWindow->display, cur_wnd); #endif return GF_OK; } #ifdef GPAC_HAS_X11_SHM if (xWindow->pixmap) { XClearWindow(xWindow->display, cur_wnd); XSync(xWindow->display, False); } else if (xWindow->use_shared_memory) { XSync(xWindow->display, False); XShmPutImage (xWindow->display, cur_wnd, xWindow->the_gc, xWindow->surface, 0, 0, dest->x, dest->y, dest->w, dest->h, True); } else #endif { XSync(xWindow->display, False); //XRaiseWindow(xWindow->display, xWindow->wnd); XPutImage (xWindow->display, cur_wnd, xWindow->the_gc, xWindow->surface, 0, 0, dest->x, dest->y, dest->w, dest->h); } return GF_OK; }
/* * init backbuffer */ GF_Err X11_InitBackBuffer (GF_VideoOutput * vout, u32 VideoWidth, u32 VideoHeight) { Window cur_wnd; u32 size; VideoWidth = VideoWidth > 32 ? VideoWidth : 32; VideoWidth = VideoWidth < 4096 ? VideoWidth : 4096; VideoHeight = VideoHeight > 32 ? VideoHeight : 32; VideoHeight = VideoHeight > 4096 ? 4096 : VideoHeight; X11VID (); if (!xWindow || !VideoWidth || !VideoHeight) return GF_BAD_PARAM; X11_ReleaseBackBuffer(vout); /*WATCHOUT seems we need even width when using shared memory extensions*/ if ((xWindow->videoaccesstype!=VIDEO_XI_STANDARD) && (VideoWidth%2)) VideoWidth++; xWindow->back_buffer->BPP = xWindow->bpp; xWindow->back_buffer->width = VideoWidth; xWindow->back_buffer->height = VideoHeight; xWindow->back_buffer->pitch = VideoWidth * xWindow->bpp; size = VideoWidth * VideoHeight * xWindow->bpp; cur_wnd = xWindow->fullscreen ? xWindow->full_wnd : xWindow->wnd; switch (xWindow->videoaccesstype) { #ifdef GPAC_HAS_X11_SHM case VIDEO_XI_SHMPIXMAP: GF_SAFEALLOC(xWindow->shmseginfo, XShmSegmentInfo); xWindow->shmseginfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); xWindow->shmseginfo->shmaddr = shmat(xWindow->shmseginfo->shmid, 0, 0); xWindow->back_buffer->buffer = (unsigned char *) xWindow->shmseginfo->shmaddr; xWindow->shmseginfo->readOnly = False; XShmAttach (xWindow->display, xWindow->shmseginfo); xWindow->pixmap = XShmCreatePixmap (xWindow->display, cur_wnd, xWindow->back_buffer->buffer, xWindow->shmseginfo, VideoWidth, VideoHeight, xWindow->depth); XSetWindowBackgroundPixmap (xWindow->display, cur_wnd, xWindow->pixmap); break; case VIDEO_XI_SHMSTD: GF_SAFEALLOC(xWindow->shmseginfo, XShmSegmentInfo); xWindow->surface = XShmCreateImage (xWindow->display, xWindow->visual, xWindow->depth, ZPixmap, NULL, xWindow->shmseginfo, VideoWidth, VideoHeight); xWindow->shmseginfo->shmid = shmget(IPC_PRIVATE, xWindow->surface->bytes_per_line * xWindow->surface->height, IPC_CREAT | 0777); xWindow->surface->data = xWindow->shmseginfo->shmaddr = shmat(xWindow->shmseginfo->shmid, NULL, 0); xWindow->back_buffer->buffer = (unsigned char *) xWindow->surface->data; xWindow->shmseginfo->readOnly = False; XShmAttach (xWindow->display, xWindow->shmseginfo); break; #endif case VIDEO_XI_STANDARD: xWindow->back_buffer->buffer = (char *) malloc(sizeof(char)*size); xWindow->surface = XCreateImage (xWindow->display, xWindow->visual, xWindow->depth, ZPixmap, 0, xWindow->back_buffer->buffer, VideoWidth, VideoHeight, xWindow->bpp*8, xWindow->back_buffer->pitch); } xWindow->is_init = 1; return GF_OK; }
/* * init backbuffer */ GF_Err X11_InitBackBuffer (GF_VideoOutput * vout, u32 VideoWidth, u32 VideoHeight) { Window cur_wnd; u32 size; VideoWidth = VideoWidth > 32 ? VideoWidth : 32; VideoWidth = VideoWidth < 4096 ? VideoWidth : 4096; VideoHeight = VideoHeight > 32 ? VideoHeight : 32; VideoHeight = VideoHeight > 4096 ? 4096 : VideoHeight; X11VID (); if (!xWindow || !VideoWidth || !VideoHeight) return GF_BAD_PARAM; X11_ReleaseBackBuffer(vout); /*WATCHOUT seems we need even width when using shared memory extensions*/ if (xWindow->use_shared_memory && (VideoWidth%2)) VideoWidth++; size = VideoWidth * VideoHeight * xWindow->bpp; cur_wnd = xWindow->fullscreen ? xWindow->full_wnd : xWindow->wnd; #ifdef GPAC_HAS_X11_SHM /*if we're using YUV blit to offscreen, we must use a pixmap*/ if (vout->hw_caps & GF_VIDEO_HW_HAS_YUV) { GF_SAFEALLOC(xWindow->shmseginfo, XShmSegmentInfo); xWindow->shmseginfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0776); xWindow->shmseginfo->shmaddr = shmat(xWindow->shmseginfo->shmid, 0, 0); xWindow->shmseginfo->readOnly = False; if (!XShmAttach (xWindow->display, xWindow->shmseginfo)) { GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Failed to attach shared memory!\n")); } xWindow->pixmap = XShmCreatePixmap(xWindow->display, cur_wnd, (unsigned char *) xWindow->shmseginfo->shmaddr, xWindow->shmseginfo, VideoWidth, VideoHeight, xWindow->depth); memset((unsigned char *) xWindow->shmseginfo->shmaddr, 0, sizeof(char)*size); XSetWindowBackgroundPixmap (xWindow->display, cur_wnd, xWindow->pixmap); xWindow->pwidth = VideoWidth; xWindow->pheight = VideoHeight; GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[X11] Using X11 Pixmap %08x\n", (u32)xWindow->pixmap)); } else if (xWindow->use_shared_memory) { GF_SAFEALLOC(xWindow->shmseginfo, XShmSegmentInfo); xWindow->surface = XShmCreateImage (xWindow->display, xWindow->visual, xWindow->depth, ZPixmap, NULL, xWindow->shmseginfo, VideoWidth, VideoHeight); xWindow->shmseginfo->shmid = shmget(IPC_PRIVATE, xWindow->surface->bytes_per_line * xWindow->surface->height, IPC_CREAT | 0777); xWindow->surface->data = xWindow->shmseginfo->shmaddr = shmat(xWindow->shmseginfo->shmid, NULL, 0); xWindow->shmseginfo->readOnly = False; XShmAttach (xWindow->display, xWindow->shmseginfo); } else #endif { char *data = (char *) gf_malloc(sizeof(char)*size); xWindow->surface = XCreateImage (xWindow->display, xWindow->visual, xWindow->depth, ZPixmap, 0, data, VideoWidth, VideoHeight, xWindow->bpp*8, xWindow->bpp*VideoWidth); if (!xWindow->surface) { gf_free(data); return GF_IO_ERR; } } xWindow->is_init = 1; return GF_OK; }
/* * Setup X11 wnd System */ void X11_SetupWindow (GF_VideoOutput * vout) { X11VID (); const char *sOpt; xWindow->display = XOpenDisplay (NULL); xWindow->screennum = DefaultScreen (xWindow->display); xWindow->screenptr = DefaultScreenOfDisplay (xWindow->display); xWindow->visual = DefaultVisualOfScreen (xWindow->screenptr); xWindow->depth = DefaultDepth (xWindow->display, xWindow->screennum); switch (xWindow->depth) { case 8: xWindow->pixel_format = GF_PIXEL_GREYSCALE; break; case 16: xWindow->pixel_format = GF_PIXEL_RGB_565; break; case 24: xWindow->pixel_format = GF_PIXEL_RGB_32; break; default: xWindow->pixel_format = GF_PIXEL_GREYSCALE; break; } xWindow->bpp = xWindow->depth / 8; xWindow->bpp = xWindow->bpp == 3 ? 4 : xWindow->bpp; vout->max_screen_width = DisplayWidth(xWindow->display, xWindow->screennum); vout->max_screen_height = DisplayHeight(xWindow->display, xWindow->screennum); /* * Full screen wnd */ xWindow->full_wnd = XCreateWindow (xWindow->display, RootWindowOfScreen (xWindow->screenptr), 0, 0, vout->max_screen_width, vout->max_screen_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XSelectInput(xWindow->display, xWindow->full_wnd, FocusChangeMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask); if (!xWindow->par_wnd) { xWindow->w_width = 320; xWindow->w_height = 20; xWindow->wnd = XCreateWindow (xWindow->display, RootWindowOfScreen(xWindow->screenptr), 0, 0, xWindow->w_width, xWindow->w_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XMapWindow (xWindow->display, (Window) xWindow->wnd); } else { XWindowAttributes pwa; XGetWindowAttributes(xWindow->display, xWindow->par_wnd, &pwa); xWindow->w_width = pwa.width; xWindow->w_height = pwa.height; xWindow->wnd = XCreateWindow (xWindow->display, xWindow->par_wnd, pwa.x, pwa.y, xWindow->w_width, xWindow->w_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XMapWindow (xWindow->display, (Window) xWindow->wnd); } XSync(xWindow->display, False); XUnmapWindow (xWindow->display, (Window) xWindow->wnd); XSync(xWindow->display, False); old_handler = XSetErrorHandler(X11_BadAccess_ByPass); selectinput_err = 0; XSelectInput(xWindow->display, xWindow->wnd, FocusChangeMask | StructureNotifyMask | PropertyChangeMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask); XSync(xWindow->display, False); XSetErrorHandler(old_handler); if (selectinput_err) { XSelectInput(xWindow->display, xWindow->wnd, StructureNotifyMask | PropertyChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask); GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Cannot select input focus\n")); } XSync(xWindow->display, False); XMapWindow (xWindow->display, (Window) xWindow->wnd); XSizeHints *Hints = XAllocSizeHints (); Hints->flags = PSize | PMinSize; Hints->min_width = 32; Hints->min_height = 32; Hints->max_height = 4096; Hints->max_width = 4096; if (!xWindow->par_wnd) { XSetWMNormalHints (xWindow->display, xWindow->wnd, Hints); XStoreName (xWindow->display, xWindow->wnd, "GPAC X11 Output"); } Hints->x = 0; Hints->y = 0; Hints->flags |= USPosition; XSetWMNormalHints (xWindow->display, xWindow->full_wnd, Hints); XFree (Hints); xWindow->the_gc = XCreateGC (xWindow->display, xWindow->wnd, 0, NULL); xWindow->videoaccesstype = VIDEO_XI_STANDARD; #ifdef GPAC_HAS_X11_SHM sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "UseHardwareMemory"); if (sOpt && !strcmp(sOpt, "yes")) { int XShmMajor, XShmMinor; Bool XShmPixmaps; if (XShmQueryVersion(xWindow->display, &XShmMajor, &XShmMinor, &XShmPixmaps)) { /*this is disabled due to flip pb (we cannot reposition backbuffer)*/ if (0 && XShmPixmaps && (XShmPixmapFormat(xWindow->display) == ZPixmap)) { xWindow->videoaccesstype = VIDEO_XI_SHMPIXMAP; } else { xWindow->videoaccesstype = VIDEO_XI_SHMSTD; GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Using X11 Hardware Blit\n")); } } } #endif GF_SAFEALLOC(xWindow->back_buffer, X11WrapSurface); xWindow->back_buffer->id = -1; XSetWindowAttributes xsw; xsw.border_pixel = WhitePixel (xWindow->display, xWindow->screennum); xsw.background_pixel = BlackPixel (xWindow->display, xWindow->screennum); xsw.win_gravity = NorthWestGravity; XChangeWindowAttributes (xWindow->display, xWindow->wnd, CWBackPixel | CWWinGravity, &xsw); xsw.override_redirect = True; XChangeWindowAttributes(xWindow->display, xWindow->full_wnd, CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWWinGravity, &xsw); if (!xWindow->par_wnd) { xWindow->WM_DELETE_WINDOW = XInternAtom (xWindow->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(xWindow->display, xWindow->wnd, &xWindow->WM_DELETE_WINDOW, 1); } { XEvent ev; long mask; memset (&ev, 0, sizeof (ev)); ev.xclient.type = ClientMessage; ev.xclient.window = RootWindowOfScreen (xWindow->screenptr); ev.xclient.message_type = XInternAtom (xWindow->display, "KWM_KEEP_ON_TOP", False); ev.xclient.format = 32; ev.xclient.data.l[0] = xWindow->full_wnd; ev.xclient.data.l[1] = CurrentTime; mask = SubstructureRedirectMask; XSendEvent (xWindow->display,RootWindowOfScreen (xWindow->screenptr), False, mask, &ev); } #ifdef GPAC_HAS_OPENGL if (xWindow->is_3D_out) { int attribs[64]; int i; i=0; attribs[i++] = GLX_RGBA; attribs[i++] = GLX_RED_SIZE; attribs[i++] = 5; attribs[i++] = GLX_GREEN_SIZE; attribs[i++] = 5; attribs[i++] = GLX_BLUE_SIZE; attribs[i++] = 5; attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = 16; if (xWindow->gl_cfg.double_buffered) attribs[i++] = GLX_DOUBLEBUFFER; attribs[i++] = None; xWindow->glx_visualinfo = glXChooseVisual(xWindow->display, xWindow->screennum, attribs); if (!xWindow->glx_visualinfo) { GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Error selecting GL display\n")); } } #endif xWindow->setup_done = 1; }
/* * handle X11 events * here we handle key, mouse, repaint and window sizing events */ static void X11_HandleEvents(GF_VideoOutput *vout) { GF_Event evt; Window the_window; XComposeStatus state; X11VID(); unsigned char keybuf[32]; XEvent xevent; the_window = xWindow->fullscreen ? xWindow->full_wnd : xWindow->wnd; XSync(xWindow->display, False); while (X11_Pending(xWindow->display)) { XNextEvent(xWindow->display, &xevent); if (xevent.xany.window!=the_window) continue; switch (xevent.type) { /* * X11 window resized event * must inform GPAC */ case ConfigureNotify: if ((unsigned int) xevent.xconfigure.width != xWindow->w_width || (unsigned int) xevent.xconfigure.height != xWindow->w_height) { evt.type = GF_EVENT_SIZE; xWindow->w_width = evt.size.width = xevent.xconfigure.width; xWindow->w_height = evt.size.height = xevent.xconfigure.height; vout->on_event(vout->evt_cbk_hdl, &evt); } else { evt.type = GF_EVENT_MOVE; evt.move.x = xevent.xconfigure.x; evt.move.y = xevent.xconfigure.y; vout->on_event(vout->evt_cbk_hdl, &evt); } break; /* * Windows need repaint */ case Expose: if (xevent.xexpose.count > 0) break; evt.type = GF_EVENT_REFRESH; vout->on_event (vout->evt_cbk_hdl, &evt); break; /* Have we been requested to quit (or another client message?) */ case ClientMessage: if ( (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == xWindow->WM_DELETE_WINDOW) ) { evt.type = GF_EVENT_QUIT; vout->on_event(vout->evt_cbk_hdl, &evt); } break; case KeyPress: case KeyRelease: x11_translate_key(XKeycodeToKeysym (xWindow->display, xevent.xkey.keycode, 0), &evt.key); evt.type = (xevent.type ==KeyPress) ? GF_EVENT_KEYDOWN : GF_EVENT_KEYUP; vout->on_event (vout->evt_cbk_hdl, &evt); if (xevent.type ==KeyPress) { s32 len; len = XLookupString (&xevent.xkey, (char *) keybuf, sizeof(keybuf), NULL, &state); if ((len>0) && (len<5)) { utf8_to_ucs4 (& evt.character.unicode_char, len, keybuf); evt.type = GF_EVENT_TEXTINPUT; vout->on_event (vout->evt_cbk_hdl, &evt); } } break; case ButtonPress: if (!xWindow->fullscreen && !xWindow->has_focus) { xWindow->has_focus = 1; XSetInputFocus(xWindow->display, xWindow->wnd, RevertToParent, CurrentTime); } case ButtonRelease: // last_mouse_move = xevent.xbutton.time; evt.mouse.x = xevent.xbutton.x; evt.mouse.y = xevent.xbutton.y; evt.type = (xevent.type == ButtonRelease) ? GF_EVENT_MOUSEUP : GF_EVENT_MOUSEDOWN; switch (xevent.xbutton.button) { case Button1: evt.mouse.button = GF_MOUSE_LEFT; vout->on_event (vout->evt_cbk_hdl, &evt); break; case Button2: evt.mouse.button = GF_MOUSE_MIDDLE; vout->on_event (vout->evt_cbk_hdl, &evt); break; case Button3: evt.mouse.button = GF_MOUSE_RIGHT; vout->on_event (vout->evt_cbk_hdl, &evt); break; case Button4: evt.type = GF_EVENT_MOUSEWHEEL; evt.mouse.wheel_pos = FIX_ONE; vout->on_event(vout->evt_cbk_hdl, &evt); break; case Button5: evt.type = GF_EVENT_MOUSEWHEEL; evt.mouse.wheel_pos = -FIX_ONE; vout->on_event(vout->evt_cbk_hdl, &evt); break; } if (!xWindow->fullscreen && (xevent.type==ButtonPress) ) XSetInputFocus(xWindow->display, xWindow->wnd, RevertToNone, CurrentTime); break; case MotionNotify: evt.type = GF_EVENT_MOUSEMOVE; evt.mouse.x = xevent.xmotion.x; evt.mouse.y = xevent.xmotion.y; vout->on_event (vout->evt_cbk_hdl, &evt); break; case PropertyNotify: break; case MapNotify: break; case CirculateNotify: break; case UnmapNotify: break; case ReparentNotify: break; case FocusOut: if (!xWindow->fullscreen) xWindow->has_focus = 0; break; case FocusIn: if (!xWindow->fullscreen) xWindow->has_focus = 1; break; case DestroyNotify: evt.type = GF_EVENT_QUIT; vout->on_event(vout->evt_cbk_hdl, &evt); break; default: break; } } }
/* * Setup X11 wnd System */ void X11_SetupWindow (GF_VideoOutput * vout) { X11VID (); const char *sOpt; Bool autorepeat, supported; xWindow->display = XOpenDisplay (NULL); xWindow->screennum = DefaultScreen (xWindow->display); xWindow->screenptr = DefaultScreenOfDisplay (xWindow->display); xWindow->visual = DefaultVisualOfScreen (xWindow->screenptr); xWindow->depth = DefaultDepth (xWindow->display, xWindow->screennum); { Float screenWidth = (Float)XWidthOfScreen(xWindow->screenptr); Float screenWidthIn = (Float)XWidthMMOfScreen(xWindow->screenptr) / 25.4f; Float screenHeight = (Float)XHeightOfScreen(xWindow->screenptr); Float screenHeightIn = (Float)XHeightMMOfScreen(xWindow->screenptr) / 25.4f; vout->dpi_x = (u32)(screenWidth / screenWidthIn); vout->dpi_y = (u32)(screenHeight / screenHeightIn); } switch (xWindow->depth) { case 8: xWindow->pixel_format = GF_PIXEL_GREYSCALE; break; case 16: xWindow->pixel_format = GF_PIXEL_RGB_565; break; case 24: xWindow->pixel_format = GF_PIXEL_RGB_32; break; default: xWindow->pixel_format = GF_PIXEL_GREYSCALE; break; } xWindow->bpp = xWindow->depth / 8; xWindow->bpp = xWindow->bpp == 3 ? 4 : xWindow->bpp; xWindow->screennum=0; vout->max_screen_width = DisplayWidth(xWindow->display, xWindow->screennum); vout->max_screen_height = DisplayHeight(xWindow->display, xWindow->screennum); /* * Full screen wnd */ xWindow->full_wnd = XCreateWindow (xWindow->display, RootWindowOfScreen (xWindow->screenptr), 0, 0, vout->max_screen_width, vout->max_screen_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XSelectInput(xWindow->display, xWindow->full_wnd, FocusChangeMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask); if (!xWindow->par_wnd) { xWindow->w_width = 320; xWindow->w_height = 240; xWindow->wnd = XCreateWindow (xWindow->display, RootWindowOfScreen(xWindow->screenptr), 0, 0, xWindow->w_width, xWindow->w_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XMapWindow (xWindow->display, (Window) xWindow->wnd); } else { XWindowAttributes pwa; XGetWindowAttributes(xWindow->display, xWindow->par_wnd, &pwa); xWindow->w_width = pwa.width; xWindow->w_height = pwa.height; xWindow->wnd = XCreateWindow (xWindow->display, xWindow->par_wnd, pwa.x, pwa.y, xWindow->w_width, xWindow->w_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XMapWindow (xWindow->display, (Window) xWindow->wnd); } XSync(xWindow->display, False); XUnmapWindow (xWindow->display, (Window) xWindow->wnd); XSync(xWindow->display, False); old_handler = XSetErrorHandler(X11_BadAccess_ByPass); selectinput_err = 0; XSelectInput(xWindow->display, xWindow->wnd, FocusChangeMask | StructureNotifyMask | PropertyChangeMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask); XSync(xWindow->display, False); XSetErrorHandler(old_handler); if (selectinput_err) { XSelectInput(xWindow->display, xWindow->wnd, StructureNotifyMask | PropertyChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask); GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Cannot select input focus\n")); } XSync(xWindow->display, False); XMapWindow (xWindow->display, (Window) xWindow->wnd); XSizeHints *Hints = XAllocSizeHints (); Hints->flags = PSize | PMinSize; Hints->min_width = 64; Hints->min_height = 64; Hints->max_height = 4096; Hints->max_width = 4096; if (!xWindow->par_wnd) { XSetWMNormalHints (xWindow->display, xWindow->wnd, Hints); XStoreName (xWindow->display, xWindow->wnd, "GPAC X11 Output"); } Hints->x = 0; Hints->y = 0; Hints->flags |= USPosition; XSetWMNormalHints (xWindow->display, xWindow->full_wnd, Hints); autorepeat = 1; XkbSetDetectableAutoRepeat(xWindow->display, autorepeat, &supported); if (xWindow->init_flags & GF_TERM_WINDOW_NO_DECORATION) { #define PROP_MOTIF_WM_HINTS_ELEMENTS 5 #define MWM_HINTS_DECORATIONS (1L << 1) struct { unsigned long flags; unsigned long functions; unsigned long decorations; long inputMode; unsigned long status; } hints = {2, 0, 0, 0, 0}; hints.flags = MWM_HINTS_DECORATIONS; hints.decorations = 0; XChangeProperty(xWindow->display, xWindow->wnd, XInternAtom(xWindow->display,"_MOTIF_WM_HINTS", False), XInternAtom(xWindow->display, "_MOTIF_WM_HINTS", False), 32, PropModeReplace, (unsigned char *)&hints, PROP_MOTIF_WM_HINTS_ELEMENTS); } xWindow->the_gc = XCreateGC (xWindow->display, xWindow->wnd, 0, NULL); xWindow->use_shared_memory = 0; #ifdef GPAC_HAS_X11_SHM sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "UseHardwareMemory"); if (sOpt && !strcmp(sOpt, "yes")) { int XShmMajor, XShmMinor; Bool XShmPixmaps; if (XShmQueryVersion(xWindow->display, &XShmMajor, &XShmMinor, &XShmPixmaps)) { xWindow->use_shared_memory = 1; GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Using X11 Shared Memory\n")); if ((XShmPixmaps==True) && (XShmPixmapFormat(xWindow->display)==ZPixmap)) { GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] X11 Shared Memory Pixmaps available\n")); } } } #endif #ifdef GPAC_HAS_X11_XV sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "DisableColorKeying"); if (sOpt && !strcmp(sOpt, "yes")) { xWindow->xvport = X11_GetXVideoPort(vout, GF_PIXEL_I420, 0); } else { xWindow->xvport = X11_GetXVideoPort(vout, GF_PIXEL_I420, 1); if (xWindow->xvport<0) { GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Hardware has no color keying\n")); vout->overlay_color_key = 0; xWindow->xvport = X11_GetXVideoPort(vout, GF_PIXEL_I420, 0); } else { GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Hardware uses color key %08x\n", vout->overlay_color_key)); } } if (xWindow->xvport>=0) { XvUngrabPort(xWindow->display, xWindow->xvport, CurrentTime ); xWindow->xvport = -1; vout->yuv_pixel_format = X11_GetPixelFormat(xWindow->xv_pf_format); vout->Blit = X11_Blit; vout->hw_caps |= GF_VIDEO_HW_HAS_YUV_OVERLAY; GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Using XV YUV Overlays\n")); #ifdef GPAC_HAS_X11_SHM /*if user asked for YUV->RGB on offscreen, do it (it may crash the system)*/ sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "EnableOffscreenYUV"); if (sOpt && !strcmp(sOpt, "yes")) { vout->hw_caps |= GF_VIDEO_HW_HAS_YUV; GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Using XV Offscreen YUV2RGB acceleration\n")); } #endif } #endif XSetWindowAttributes xsw; xsw.border_pixel = WhitePixel (xWindow->display, xWindow->screennum); xsw.background_pixel = BlackPixel (xWindow->display, xWindow->screennum); xsw.win_gravity = NorthWestGravity; XChangeWindowAttributes (xWindow->display, xWindow->wnd, CWBackPixel | CWWinGravity, &xsw); xsw.override_redirect = True; XChangeWindowAttributes(xWindow->display, xWindow->full_wnd, CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWWinGravity, &xsw); if (!xWindow->par_wnd) { xWindow->WM_DELETE_WINDOW = XInternAtom (xWindow->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(xWindow->display, xWindow->wnd, &xWindow->WM_DELETE_WINDOW, 1); } { XEvent ev; long mask; memset (&ev, 0, sizeof (ev)); ev.xclient.type = ClientMessage; ev.xclient.window = RootWindowOfScreen (xWindow->screenptr); ev.xclient.message_type = XInternAtom (xWindow->display, "KWM_KEEP_ON_TOP", False); ev.xclient.format = 32; ev.xclient.data.l[0] = xWindow->full_wnd; ev.xclient.data.l[1] = CurrentTime; mask = SubstructureRedirectMask; XSendEvent (xWindow->display,RootWindowOfScreen (xWindow->screenptr), False, mask, &ev); } /*openGL setup*/ #ifdef GPAC_HAS_OPENGL { int attribs[64]; int i, nb_bits; sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "GLNbBitsPerComponent"); /* Most outputs are 24/32 bits these days, use 8 bits per channel instead of 5, works better on MacOS X */ nb_bits = sOpt ? atoi(sOpt) : 8; if (!sOpt){ gf_modules_set_option((GF_BaseInterface *)vout, "Video", "GLNbBitsPerComponent", "8"); } i=0; attribs[i++] = GLX_RGBA; attribs[i++] = GLX_RED_SIZE; attribs[i++] = nb_bits; attribs[i++] = GLX_GREEN_SIZE; attribs[i++] = nb_bits; attribs[i++] = GLX_BLUE_SIZE; attribs[i++] = nb_bits; sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "GLNbBitsDepth"); nb_bits = sOpt ? atoi(sOpt) : 16; if (!sOpt){ gf_modules_set_option((GF_BaseInterface *)vout, "Video", "GLNbBitsDepth", "16"); } if (nb_bits) { attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = nb_bits; } sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "UseGLDoubleBuffering"); if (!sOpt){ gf_modules_set_option((GF_BaseInterface *)vout, "Video", "UseGLDoubleBuffering", "yes"); } if (!sOpt || !strcmp(sOpt, "yes")) attribs[i++] = GLX_DOUBLEBUFFER; attribs[i++] = None; xWindow->glx_visualinfo = glXChooseVisual(xWindow->display, xWindow->screennum, attribs); if (!xWindow->glx_visualinfo) { GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Error selecting GL display\n")); } } xWindow->gl_wnd = XCreateWindow (xWindow->display, RootWindowOfScreen (xWindow->screenptr), 0, 0, 200, 200, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XSync(xWindow->display, False); XUnmapWindow(xWindow->display, (Window) xWindow->gl_wnd); XSync(xWindow->display, False); sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "X113DOffscreenMode"); if (!sOpt) gf_modules_set_option((GF_BaseInterface *)vout, "Video", "X113DOffscreenMode", "Pixmap"); if (sOpt && !strcmp(sOpt, "Window")) { xWindow->offscreen_type = 1; } else if (sOpt && !strcmp(sOpt, "VisibleWindow")) { xWindow->offscreen_type = 2; XSetWMNormalHints (xWindow->display, xWindow->gl_wnd, Hints); } else if (sOpt && !strcmp(sOpt, "Pixmap")) { xWindow->offscreen_type = 0; } else { xWindow->offscreen_type = 0; } #endif /*turn off xscreensaver*/ X11_XScreenSaverState(xWindow, 0); xWindow->setup_done = 1; XFree (Hints); }