static int vopen( video_desc_t *vm ) { XDGADevice *dev; int mask; if( dga.is_open ) return 1; if( !XDGAOpenFramebuffer( x11.disp, x11.screen ) ) { printm("XDGAOpenFramebuffer failed\n"); return 1; } if( !(dev=XDGASetMode( x11.disp, x11.screen, (int)vm->module_data )) ) { printf("XDGASetMode failure\n"); XDGACloseFramebuffer( x11.disp, x11.screen ); return 1; } printm("%d x %d: %d (%08x/%x)\n", vm->w, vm->h, vm->depth, (int)dev->data, vm->rowbytes ); vm->lvbase = (char *)dev->data; vm->mmu_flags = get_bool_res("use_fb_cache")? MAPPING_FORCE_CACHE : MAPPING_MACOS_CONTROLS_CACHE; vm->map_base = 0; XFree( dev ); dga.is_open = 1; use_hw_cursor(0); mask = KeyPressMask | KeyReleaseMask; if( mouse_activate(1) ) mask |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask; XDGASelectInput( x11.disp, x11.screen, mask ); return 0; }
int xf86_dga2_init(void) { int i,j ; xf86ctx.screen = DefaultScreen(display); if(!XDGAQueryVersion(display, &i, &j)) fprintf(stderr,"XDGAQueryVersion failed\n"); else if (i < 2) fprintf(stderr,"This driver requires DGA 2.0 or newer\n"); else if(!XDGAQueryExtension(display, &i, &j)) fprintf(stderr,"XDGAQueryExtension failed\n"); else { /* Dumping core while DirectVideo is active causes an X-server freeze with kernel 2.6, so don't dump core! */ struct rlimit limit = { 0, 0 }; if(setrlimit(RLIMIT_CORE, &limit)) perror("rlimit"); else if(!XDGAOpenFramebuffer(display,xf86ctx.screen)) fprintf(stderr,"XDGAOpenFramebuffer failed\n"); else return SYSDEP_DISPLAY_FULLSCREEN|SYSDEP_DISPLAY_EFFECTS; } fprintf(stderr,"Use of DGA-modes is disabled\n"); return 0; }
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; }
/* _xdga2_gfxdrv_init_drv: * Initializes driver and creates screen bitmap. */ static BITMAP *_xdga2_private_gfxdrv_init_drv(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int accel) { int dga_error_base, dga_major_version, dga_minor_version; int mode, mask, red_shift = 0, green_shift = 0, blue_shift = 0; long input_mask; char tmp1[128], tmp2[128]; BITMAP *bmp; /* This is just to test if the system driver has been installed properly */ if (_xwin.window == None) return NULL; /* Test that display is local. */ if (!_xdga2_private_display_is_local()) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("This driver needs local display")); return NULL; } /* Choose convenient size. */ if ((w == 0) && (h == 0)) { w = 640; h = 480; } if ((w < 80) || (h < 80) || (w > 4096) || (h > 4096)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported screen size")); return NULL; } if (vw < w) vw = w; if (vh < h) vh = h; if (1 #ifdef ALLEGRO_COLOR8 && (depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (depth != 15) && (depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } /* Checks presence of DGA extension */ if (!XDGAQueryExtension(_xwin.display, &dga_event_base, &dga_error_base) || !XDGAQueryVersion(_xwin.display, &dga_major_version, &dga_minor_version)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DGA extension is not supported")); return NULL; } /* Works only with DGA 2.0 or newer */ if (dga_major_version < 2) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DGA 2.0 or newer is required")); return NULL; } /* Attempts to access the framebuffer */ if (!XDGAOpenFramebuffer(_xwin.display, _xwin.screen)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open framebuffer")); return NULL; } /* Finds suitable video mode number */ mode = _xdga2_find_mode(w, h, vw, vh, depth); if (!mode) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } /* Sets DGA video mode */ dga_device = XDGASetMode(_xwin.display, _xwin.screen, mode); if (dga_device == NULL) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not switch to DGA mode")); return NULL; } _xwin.in_dga_mode = 2; _set_current_refresh_rate(dga_device->mode.verticalRefresh); set_display_switch_mode(SWITCH_NONE); /* Installs DGA color map */ if (_dga_cmap) { XFreeColormap(_xwin.display, _dga_cmap); _dga_cmap = 0; } if ((dga_device->mode.visualClass == PseudoColor) || (dga_device->mode.visualClass == GrayScale) || (dga_device->mode.visualClass == DirectColor)) _dga_cmap = XDGACreateColormap(_xwin.display, _xwin.screen, dga_device, AllocAll); else _dga_cmap = XDGACreateColormap(_xwin.display, _xwin.screen, dga_device, AllocNone); XDGAInstallColormap(_xwin.display, _xwin.screen, _dga_cmap); /* Sets up direct color shifts */ if (depth != 8) { for (mask = dga_device->mode.redMask, red_shift = 0; (mask & 1) == 0; mask >>= 1, red_shift++); for (mask = dga_device->mode.greenMask, green_shift = 0; (mask & 1) == 0; mask >>= 1, green_shift++); for (mask = dga_device->mode.blueMask, blue_shift = 0; (mask & 1) == 0; mask >>= 1, blue_shift++); } switch (depth) { case 15: _rgb_r_shift_15 = red_shift; _rgb_g_shift_15 = green_shift; _rgb_b_shift_15 = blue_shift; break; case 16: _rgb_r_shift_16 = red_shift; _rgb_g_shift_16 = green_shift; _rgb_b_shift_16 = blue_shift; break; case 24: _rgb_r_shift_24 = red_shift; _rgb_g_shift_24 = green_shift; _rgb_b_shift_24 = blue_shift; break; case 32: _rgb_r_shift_32 = red_shift; _rgb_g_shift_32 = green_shift; _rgb_b_shift_32 = blue_shift; break; } /* Enables input */ XSync(_xwin.display, True); input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; XDGASelectInput(_xwin.display, _xwin.screen, input_mask); if (_xwin_keyboard_focused) { (*_xwin_keyboard_focused)(FALSE, 0); keyboard_got_focus = TRUE; } _mouse_on = TRUE; /* Creates screen bitmap */ drv->linear = TRUE; bmp = _make_bitmap(dga_device->mode.imageWidth, dga_device->mode.imageHeight, (uintptr_t)dga_device->data, drv, depth, dga_device->mode.bytesPerScanline); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } drv->w = bmp->cr = w; drv->h = bmp->cb = h; drv->vid_mem = dga_device->mode.imageWidth * dga_device->mode.imageHeight * BYTES_PER_PIXEL(depth); if (accel) { /* Hardware acceleration has been requested */ /* Updates line switcher to accommodate framebuffer synchronization */ #ifdef ALLEGRO_NO_ASM bmp->write_bank = _xdga2_write_line; bmp->read_bank = _xdga2_write_line; #else bmp->write_bank = _xdga2_write_line_asm; bmp->read_bank = _xdga2_write_line_asm; #endif _screen_vtable.acquire = _xdga2_acquire; /* Checks for hardware acceleration support */ if (dga_device->mode.flags & XDGASolidFillRect) { /* XDGAFillRectangle is available */ _orig_hline = _screen_vtable.hline; _orig_vline = _screen_vtable.vline; _orig_rectfill = _screen_vtable.rectfill; _screen_vtable.hline = _xaccel_hline; _screen_vtable.vline = _xaccel_vline; _screen_vtable.rectfill = _xaccel_rectfill; _screen_vtable.clear_to_color = _xaccel_clear_to_color; gfx_capabilities |= (GFX_HW_HLINE | GFX_HW_FILL); } if (dga_device->mode.flags & XDGABlitRect) { /* XDGACopyArea is available */ _screen_vtable.blit_to_self = _xaccel_blit_to_self; _screen_vtable.blit_to_self_forward = _xaccel_blit_to_self; _screen_vtable.blit_to_self_backward = _xaccel_blit_to_self; gfx_capabilities |= GFX_HW_VRAM_BLIT; } if (dga_device->mode.flags & XDGABlitTransRect) { /* XDGACopyTransparentArea is available */ _orig_draw_sprite = _screen_vtable.draw_sprite; _orig_masked_blit = _screen_vtable.masked_blit; _screen_vtable.masked_blit = _xaccel_masked_blit; _screen_vtable.draw_sprite = _xaccel_draw_sprite; if (_screen_vtable.color_depth == 8) _screen_vtable.draw_256_sprite = _xaccel_draw_sprite; gfx_capabilities |= GFX_HW_VRAM_BLIT_MASKED; } RESYNC(); } /* Checks for triple buffering */ if (dga_device->mode.viewportFlags & XDGAFlipRetrace) gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; /* Sets up driver description */ uszprintf(_xdga2_driver_desc, sizeof(_xdga2_driver_desc), uconvert_ascii("X-Windows DGA 2.0 graphics%s", tmp1), uconvert_ascii(accel ? (gfx_capabilities ? " (accelerated)" : "") : " (software only)", tmp2)); drv->desc = _xdga2_driver_desc; return bmp; }