void I_InitGraphics(void) { const char* displayname = NULL; int n; int pnum; int x=0; int y=0; { static int firsttime=1; if (!firsttime) { return; } firsttime = 0; } { // Check for screen enlargement char str[3] = { '-', 0, 0 }; for (n=1; n<4; n++) { str[1] = n + '0'; if (M_CheckParm(str)) multiply = n; } } X_width = SCREENWIDTH * multiply; X_height = SCREENHEIGHT * multiply; // check for command-line geometry if ( (pnum=M_CheckParm("-geom")) ? 1 : (pnum=M_CheckParm("-geometry"))) if (pnum+1 < myargc) { // check parm given // warning: char format, different type arg char xsign=' '; char ysign=' '; const char* pg = myargv[pnum+1]; pg += strcspn(pg, "+-"); // warning: char format, different type arg 3,5 n = sscanf(pg, "%c%d%c%d", &xsign, &x, &ysign, &y); if (n==2) x = y = 0; else if (n==4) { if (xsign == '-') x = -x; if (ysign == '-') y = -y; } else fprintf(stderr, "I_InitGraphics: bad -geom offsets \"%s\"\n", pg); } // check for command-line display name if ( (pnum=M_CheckParm("-disp")) ) // suggest parentheses around assignment displayname = myargv[pnum+1]; // CPhipps - support more standard -display param if ( (pnum=M_CheckParm("-display")) ) // ditto displayname = myargv[pnum+1]; // CPhipps - and -displayname as for xterm if ( (pnum=M_CheckParm("-displayname")) ) // ditto displayname = myargv[pnum+1]; // open the display if (!(X_display = XOpenDisplay(displayname))) { if (displayname) I_Error("Could not open display [%s]", displayname); else I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY")); } // use the default visual X_screen = DefaultScreen(X_display); X_deletewin = XInternAtom(X_display, "WM_DELETE_WINDOW", False); // check for the MITSHM extension // even if it's available, make sure it's a local connection lprintf(LO_INFO,"I_InitGraphics:"); #ifdef HAVE_LIBXXF86DGA if ((doDga = (M_CheckParm("-dga") && XF86DGAQueryExtension(X_display, &n, &n)) )) { lprintf(LO_INFO,"I_InitGraphics: found DGA extension\n"); if (M_CheckParm("-noaccel") || (X_opt & 1)) doDga = false; else lprintf(LO_INFO, "(using DGA)"); } else #endif #ifdef HAVE_LIBXEXT if ((doShm = XShmQueryExtension(X_display))) { if (!displayname) displayname = getenv("DISPLAY"); if (displayname) { // CPhipps - don't modify the original string, please. // - oops my code here was totally wrong // I have no idea exactly what should go here. if (M_CheckParm("-noaccel") || (X_opt & 1)) doShm = false; else lprintf(LO_INFO, "(using MITShm)"); } } else #endif if (devparm) fprintf(stderr, "No MITShm extension in server"); if (devparm) fputc('\n', stderr); if ((X_visual = I_FindMode(X_screen)) == NULL) I_Error("Unsupported visual"); // create the colormap X_cmap = XCreateColormap(X_display, RootWindow(X_display, X_screen), X_visual, true_color ? AllocNone : AllocAll); #ifdef HAVE_LIBXXF86DGA /* setup for DGA */ if(doDga) { char *fb; X_mainWindow=RootWindow(X_display, X_screen); XF86DGAGetViewPortSize(X_display, X_screen, &DGA_width, &DGA_height); XF86DGAGetVideo(X_display, X_screen, &fb, &DGA_real_width, &DGA_pagelen, &DGA_memlen); fprintf(stderr, "I_InitGraphics: DGA reports %dx%d scan=%d page=%d mem=%d\n", DGA_width,DGA_height,DGA_real_width,DGA_pagelen,DGA_memlen); out_buffer=(void*)fb; XF86DGADirectVideo(X_display, X_screen, XF86DGADirectGraphics); XF86DGASetVidPage(X_display, X_screen, 0); XF86DGAForkApp(X_screen); XSelectInput(X_display, X_mainWindow, KeyPressMask | KeyReleaseMask); fprintf(stderr,"DGA framebuffer @%p\n",fb); memset(fb,0,102400); } #endif #ifdef HAVE_LIBXXF86DGA if(!doDga) #endif { // setup attributes for main window unsigned long attribmask; XSetWindowAttributes attribs; attribmask = CWEventMask | CWColormap | CWBorderPixel; attribs.event_mask = KeyPressMask | KeyReleaseMask #ifdef MONITOR_VISIBILITY | VisibilityChangeMask #endif | ExposureMask; attribs.colormap = X_cmap; attribs.border_pixel = 0; // create the main window X_mainWindow = XCreateWindow( X_display, RootWindow(X_display, X_screen), x, y, X_width, X_height, 0, // borderwidth X_bpp, // depth InputOutput, X_visual, attribmask, &attribs ); } #ifdef HAVE_LIBXXF86DGA if(!doDga) #endif { XClassHint c_hint; XTextProperty x_name; XSizeHints s_hint; XWMHints wm_hint; char lcase_buf[10], ucase_buf[10]; char* str; strcpy(str = lcase_buf, lcase_lxdoom); XStringListToTextProperty(&str, 1, &x_name); s_hint.flags = PSize | PMinSize | PMaxSize; s_hint.min_width = s_hint.max_width = s_hint.base_width = X_width; s_hint.min_height = s_hint.max_height = s_hint.base_height = X_height; wm_hint.input = True; wm_hint.window_group = X_mainWindow; wm_hint.flags = InputHint | WindowGroupHint; strcpy(c_hint.res_name = lcase_buf, lcase_lxdoom); strcpy(c_hint.res_class = ucase_buf, ucase_lxdoom); XSetWMProtocols(X_display, X_mainWindow, &X_deletewin, 1); XSetWMProperties(X_display, X_mainWindow, &x_name, &x_name, (char**)myargv, myargc, &s_hint, &wm_hint, &c_hint); XFlush(X_display); } #ifdef HAVE_LIBXXF86DGA if(!doDga) #endif // Hide pointer while over this window XDefineCursor(X_display, X_mainWindow, I_XCreateNullCursor( X_display, X_mainWindow ) ); { // create the GC XGCValues xgcvalues; int valuemask; valuemask = GCGraphicsExposures; xgcvalues.graphics_exposures = False; X_gc = XCreateGC(X_display, X_mainWindow, valuemask, &xgcvalues); } #ifdef HAVE_LIBXXF86DGA if(!doDga) #endif { // name the window XStoreName(X_display, X_mainWindow, "lxdoom"); // map the window XMapWindow(X_display, X_mainWindow); } // wait until it is OK to draw #ifdef HAVE_LIBXXF86DGA if(!doDga) #endif do { XNextEvent(X_display, &X_event); } while (!(X_event.type == Expose && !X_event.xexpose.count)); #ifdef HAVE_LIBXXF86DGA if(doDga) {} else #endif #ifdef HAVE_LIBXEXT if (doShm) { X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion; // create the image image = XShmCreateImage( X_display, X_visual, X_bpp, ZPixmap, 0, &X_shminfo, X_width, X_height ); I_XShmGrabSharedMemory(image->bytes_per_line * image->height); if (!(out_buffer = (pval*)image->data)) { perror(""); I_Error("shmat() failed in I_InitGraphics()"); } // get the X server to attach to it if (!XShmAttach(X_display, &X_shminfo)) I_Error("XShmAttach() failed in InitGraphics()"); if (!expand_buffer) { // Render directly into MitSHM memory Z_Free(screens[0]); screens[0] = (unsigned char *) (image->data); } } else #endif { if (!expand_buffer) { // Very efficient, render directly into image out_buffer = (pval*)screens[0]; } else { // Will have to enlarge from rendering buffer // into image buffer out_buffer = (pval*)malloc (X_width * X_height * BYTESPP); } { /* hack to enable 15 bpp usage */ int bpp=X_bpp; if(bpp==15)bpp=16; image=XCreateImage( X_display, X_visual, X_bpp, ZPixmap, 0, (char*)out_buffer, X_width, X_height, bpp, 0); #ifdef NOT_NOW image=XCreateImage( X_display, X_visual, X_bpp, ZPixmap, 0, (char*)out_buffer, X_width, X_height, X_bpp, 0); #endif } if (!image) I_Error("XCreateImage: failed to create image %dx%d %d bpp", X_width, X_height, X_bpp); } atexit(I_ShutdownGraphics); I_XInitInputs(); }
static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) { int x_off, y_off; int wanted_width, wanted_height; static unsigned char *vo_dga_base; static int prev_width, prev_height; #ifdef HAVE_DGA2 // needed to change DGA video mode int mX = VO_DGA_INVALID_RES, mY = VO_DGA_INVALID_RES, mVBI = 100000, mMaxY = 0, i, j = 0; int dga_modenum; XDGAMode *modeline; XDGADevice *dgadevice; #else #ifdef HAVE_XF86VM unsigned int vm_event, vm_error; unsigned int vm_ver, vm_rev; int i, j = 0, have_vm = 0; int mX = VO_DGA_INVALID_RES, mY = VO_DGA_INVALID_RES, mVBI = 100000, mMaxY = 0, dga_modenum; #endif int bank, ram; #endif vo_dga_src_format = format; wanted_width = d_width; wanted_height = d_height; if (!wanted_height) wanted_height = height; if (!wanted_width) wanted_width = width; if (!vo_dbpp) { if ((format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { vo_dga_src_mode = vd_ModeValid(format & 0xff); } } else { vo_dga_src_mode = vd_ModeValid(vo_dbpp); } vo_dga_hw_mode = SRC_MODE.vdm_hw_mode; if (!vo_dga_src_mode) { mp_msg(MSGT_VO, MSGL_ERR, "vo_dga: unsupported video format!\n"); return 1; } vo_dga_vp_width = vo_screenwidth; vo_dga_vp_height = vo_screenheight; mp_msg(MSGT_VO, MSGL_V, "vo_dga: XServer res: %dx%d\n", vo_dga_vp_width, vo_dga_vp_height); // choose a suitable mode ... #ifdef HAVE_DGA2 // Code to change the video mode added by Michael Graffam // [email protected] mp_msg(MSGT_VO, MSGL_V, "vo_dga: vo_modelines=%p, vo_modecount=%d\n", vo_modelines, vo_modecount); if (vo_modelines == NULL) { mp_msg(MSGT_VO, MSGL_ERR, "vo_dga: can't get modelines\n"); return 1; } mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: DGA 2.0 available :-) Can switch resolution AND depth!\n"); for (i = 0; i < vo_modecount; i++) { if (vd_ModeEqual(vo_modelines[i].depth, vo_modelines[i].bitsPerPixel, vo_modelines[i].redMask, vo_modelines[i].greenMask, vo_modelines[i].blueMask, vo_dga_hw_mode)) { mp_msg(MSGT_VO, MSGL_V, "maxy: %4d, depth: %2d, %4dx%4d, ", vo_modelines[i].maxViewportY, vo_modelines[i].depth, vo_modelines[i].imageWidth, vo_modelines[i].imageHeight); if (check_res (i, wanted_width, wanted_height, vo_modelines[i].depth, vo_modelines[i].viewportWidth, vo_modelines[i].viewportHeight, (unsigned) vo_modelines[i].verticalRefresh, vo_modelines[i].maxViewportY, &mX, &mY, &mVBI, &mMaxY)) j = i; } } mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: Selected hardware mode %4d x %4d @ %3d Hz @ depth %2d, bitspp %2d.\n", mX, mY, mVBI, HW_MODE.vdm_depth, HW_MODE.vdm_bitspp); mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: Video parameters by codec: %3d x %3d, depth %2d, bitspp %2d.\n", width, height, SRC_MODE.vdm_depth, SRC_MODE.vdm_bitspp); vo_dga_vp_width = mX; vo_dga_vp_height = mY; if ((flags & VOFLAG_SWSCALE) || (flags & VOFLAG_FULLSCREEN)) { /* -zoom or -fs */ scale_dstW = (d_width + 7) & ~7; scale_dstH = d_height; scale_srcW = width; scale_srcH = height; aspect_save_screenres(mX, mY); aspect_save_orig(scale_srcW, scale_srcH); aspect_save_prescale(scale_dstW, scale_dstH); if (flags & VOFLAG_FULLSCREEN) /* -fs */ aspect(&scale_dstW, &scale_dstH, A_ZOOM); else if (flags & VOFLAG_SWSCALE) /* -fs */ aspect(&scale_dstW, &scale_dstH, A_NOZOOM); mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: Aspect corrected size for SwScaler: %4d x %4d.\n", scale_dstW, scale_dstH); /* XXX this is a hack, but I'm lazy ;-) :: atmos */ width = scale_dstW; height = scale_dstH; } vo_dga_width = vo_modelines[j].bytesPerScanline / HW_MODE.vdm_bytespp; dga_modenum = vo_modelines[j].num; modeline = vo_modelines + j; #else #ifdef HAVE_XF86VM mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: DGA 1.0 compatibility code: Using XF86VidMode for mode switching!\n"); if (XF86VidModeQueryExtension(mDisplay, &vm_event, &vm_error)) { XF86VidModeQueryVersion(mDisplay, &vm_ver, &vm_rev); mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: XF86VidMode Extension v%i.%i\n", vm_ver, vm_rev); have_vm = 1; } else { mp_msg(MSGT_VO, MSGL_ERR, "vo_dga: XF86VidMode Extension not available.\n"); } #define GET_VREFRESH(dotclk, x, y)( (((dotclk)/(x))*1000)/(y) ) if (have_vm) { int modecount; XF86VidModeGetAllModeLines(mDisplay, mScreen, &modecount, &vo_dga_vidmodes); if (vo_dga_vidmodes != NULL) { for (i = 0; i < modecount; i++) { if (check_res(i, wanted_width, wanted_height, vo_dga_modes[vo_dga_hw_mode].vdm_depth, vo_dga_vidmodes[i]->hdisplay, vo_dga_vidmodes[i]->vdisplay, GET_VREFRESH(vo_dga_vidmodes[i]->dotclock, vo_dga_vidmodes[i]->htotal, vo_dga_vidmodes[i]->vtotal), 0, &mX, &mY, &mVBI, &mMaxY)) j = i; } mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: Selected video mode %4d x %4d @ %3d Hz @ depth %2d, bitspp %2d, video %3d x %3d.\n", mX, mY, mVBI, vo_dga_modes[vo_dga_hw_mode].vdm_depth, vo_dga_modes[vo_dga_hw_mode].vdm_bitspp, width, height); } else { mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: XF86VidMode returned no screens - using current resolution.\n"); } dga_modenum = j; vo_dga_vp_width = mX; vo_dga_vp_height = mY; } #else mp_msg(MSGT_VO, MSGL_INFO, "vo_dga: Only have DGA 1.0 extension and no XF86VidMode :-(\n"); mp_msg(MSGT_VO, MSGL_INFO, " Thus, resolution switching is NOT possible.\n"); #endif #endif vo_dga_src_width = width; vo_dga_src_height = height; if (vo_dga_src_width > vo_dga_vp_width || vo_dga_src_height > vo_dga_vp_height) { mp_msg(MSGT_VO, MSGL_ERR, "vo_dga: Sorry, video larger than viewport is not yet supported!\n"); // ugly, do something nicer in the future ... #ifndef HAVE_DGA2 #ifdef HAVE_XF86VM if (vo_dga_vidmodes) { XFree(vo_dga_vidmodes); vo_dga_vidmodes = NULL; } #endif #endif return 1; } if (vo_dga_vp_width == VO_DGA_INVALID_RES) { mp_msg(MSGT_VO, MSGL_ERR, "vo_dga: Something is wrong with your DGA. There doesn't seem to be a\n" " single suitable mode!\n" " Please file a bug report (see DOCS/HTML/en/bugreports.html)\n"); #ifndef HAVE_DGA2 #ifdef HAVE_XF86VM if (vo_dga_vidmodes) { XFree(vo_dga_vidmodes); vo_dga_vidmodes = NULL; } #endif #endif return 1; } // now let's start the DGA thing if (!vo_config_count || width != prev_width || height != prev_height) { #ifdef HAVE_DGA2 if (!XDGAOpenFramebuffer(mDisplay, mScreen)) { mp_msg(MSGT_VO, MSGL_ERR, "vo_dga: Framebuffer mapping failed!!!\n"); return 1; } dgadevice = XDGASetMode(mDisplay, mScreen, dga_modenum); XDGASync(mDisplay, mScreen); vo_dga_base = dgadevice->data; XFree(dgadevice); XDGASetViewport(mDisplay, mScreen, 0, 0, XDGAFlipRetrace); #else #ifdef HAVE_XF86VM if (have_vm) { XF86VidModeLockModeSwitch(mDisplay, mScreen, 0); // Two calls are needed to switch modes on my ATI Rage 128. Why? // for riva128 one call is enough! XF86VidModeSwitchToMode(mDisplay, mScreen, vo_dga_vidmodes[dga_modenum]); XF86VidModeSwitchToMode(mDisplay, mScreen, vo_dga_vidmodes[dga_modenum]); } #endif XF86DGAGetViewPortSize(mDisplay, mScreen, &vo_dga_vp_width, &vo_dga_vp_height); XF86DGAGetVideo(mDisplay, mScreen, (char **) &vo_dga_base, &vo_dga_width, &bank, &ram); XF86DGADirectVideo(mDisplay, mScreen, XF86DGADirectGraphics | XF86DGADirectMouse | XF86DGADirectKeyb); XF86DGASetViewPort(mDisplay, mScreen, 0, 0); #endif } // do some more checkings here ... mp_msg(MSGT_VO, MSGL_V, "vo_dga: bytes/line: %d, screen res: %dx%d, depth: %d, base: %p, bpp: %d\n", vo_dga_width, vo_dga_vp_width, vo_dga_vp_height, HW_MODE.vdm_bytespp, vo_dga_base, HW_MODE.vdm_bitspp); x_off = (vo_dga_vp_width - vo_dga_src_width) >> 1; y_off = (vo_dga_vp_height - vo_dga_src_height) >> 1; vo_dga_bytes_per_line = vo_dga_src_width * HW_MODE.vdm_bytespp; vo_dga_lines = vo_dga_src_height; vo_dga_src_offset = 0; vo_dga_vp_offset = (y_off * vo_dga_width + x_off) * HW_MODE.vdm_bytespp; vo_dga_vp_skip = (vo_dga_width - vo_dga_src_width) * HW_MODE.vdm_bytespp; // todo mp_msg(MSGT_VO, MSGL_V, "vo_dga: vp_off=%d, vp_skip=%d, bpl=%d\n", vo_dga_vp_offset, vo_dga_vp_skip, vo_dga_bytes_per_line); XGrabKeyboard(mDisplay, DefaultRootWindow(mDisplay), True, GrabModeAsync, GrabModeAsync, CurrentTime); if (vo_grabpointer) XGrabPointer(mDisplay, DefaultRootWindow(mDisplay), True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); if (!vo_config_count || width != prev_width || height != prev_height) { init_video_buffers(vo_dga_base, vo_dga_vp_height, vo_dga_width * HW_MODE.vdm_bytespp, #ifdef HAVE_DGA2 modeline->maxViewportY, #else vo_dga_vp_height, #endif vo_doublebuffering); prev_width = width; prev_height = height; } mp_msg(MSGT_VO, MSGL_V, "vo_dga: Using %d frame buffer%s.\n", vo_dga_nr_video_buffers, vo_dga_nr_video_buffers == 1 ? "" : "s"); vo_dga_is_running = 1; return 0; }