/* _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; }
/* _set_gfx_mode: * Called by set_gfx_mode(). Separated to make a clear difference between * the virtual GFX_SAFE driver and the rest. The allow_config parameter, * if true, allows the configuration to override the graphics card/driver * when using GFX_AUTODETECT. */ static int _set_gfx_mode(int card, int w, int h, int v_w, int v_h, int allow_config) { _DRIVER_INFO *driver_list; GFX_DRIVER *drv; char tmp1[64], tmp2[64]; AL_CONST char *dv; int flags = 0; int c; ASSERT(system_driver); ASSERT(card != GFX_SAFE); /* remember the current console state */ if (gfx_virgin) { TRACE(PREFIX_I "First call, remembering console state.\n"); LOCK_FUNCTION(_stub_bank_switch); LOCK_FUNCTION(blit); if (system_driver->save_console_state) system_driver->save_console_state(); _add_exit_func(shutdown_gfx, "shutdown_gfx"); gfx_virgin = FALSE; } timer_simulate_retrace(FALSE); _screen_split_position = 0; /* close down any existing graphics driver */ if (gfx_driver) { TRACE(PREFIX_I "Closing graphics driver (%p) ", gfx_driver); TRACE("%s.\n", gfx_driver->ascii_name); if (_al_linker_mouse) _al_linker_mouse->show_mouse(NULL); while (vram_bitmap_list) destroy_bitmap(vram_bitmap_list->bmp); bmp_read_line(screen, 0); bmp_write_line(screen, 0); bmp_unwrite_line(screen); if (gfx_driver->scroll) gfx_driver->scroll(0, 0); if (gfx_driver->exit) gfx_driver->exit(screen); destroy_bitmap(screen); gfx_driver = NULL; screen = NULL; gfx_capabilities = 0; } /* We probably don't want to do this because it makes * Allegro "forget" the color layout of previously set * graphics modes. But it should be retained if bitmaps * created in those modes are to be used in the new mode. */ #if 0 /* restore default truecolor pixel format */ _rgb_r_shift_15 = 0; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 10; _rgb_r_shift_16 = 0; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 11; _rgb_r_shift_24 = 0; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 16; _rgb_r_shift_32 = 0; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 16; _rgb_a_shift_32 = 24; #endif gfx_capabilities = 0; _set_current_refresh_rate(0); /* return to text mode? */ if (card == GFX_TEXT) { TRACE(PREFIX_I "Closing, restoring original console state.\n"); if (system_driver->restore_console_state) system_driver->restore_console_state(); if (_gfx_bank) { _AL_FREE(_gfx_bank); _gfx_bank = NULL; } TRACE(PREFIX_I "Graphic mode closed.\n"); return 0; } /* now to the interesting part: let's try to find a graphics driver */ usetc(allegro_error, 0); /* ask the system driver for a list of graphics hardware drivers */ if (system_driver->gfx_drivers) driver_list = system_driver->gfx_drivers(); else driver_list = _gfx_driver_list; /* filter specific fullscreen/windowed driver requests */ if (card == GFX_AUTODETECT_FULLSCREEN) { flags |= GFX_DRIVER_FULLSCREEN_FLAG; card = GFX_AUTODETECT; } else if (card == GFX_AUTODETECT_WINDOWED) { flags |= GFX_DRIVER_WINDOWED_FLAG; card = GFX_AUTODETECT; } if (card == GFX_AUTODETECT) { /* autodetect the driver */ int found = FALSE; tmp1[0] = '\0'; /* first try the config variables */ if (allow_config) { /* try the gfx_card variable if GFX_AUTODETECT or GFX_AUTODETECT_FULLSCREEN was selected */ if (!(flags & GFX_DRIVER_WINDOWED_FLAG)) found = get_config_gfx_driver(uconvert_ascii("gfx_card", tmp1), w, h, v_w, v_h, flags, driver_list); /* try the gfx_cardw variable if GFX_AUTODETECT or GFX_AUTODETECT_WINDOWED was selected */ if (!(flags & GFX_DRIVER_FULLSCREEN_FLAG) && !found) found = get_config_gfx_driver(uconvert_ascii("gfx_cardw", tmp1), w, h, v_w, v_h, flags, driver_list); } /* go through the list of autodetected drivers if none was previously found */ if (!found) { TRACE(PREFIX_I "Autodetecting graphic driver.\n"); for (c=0; driver_list[c].driver; c++) { if (driver_list[c].autodetect) { drv = driver_list[c].driver; if (gfx_driver_is_valid(drv, flags)) { screen = init_gfx_driver(drv, w, h, v_w, v_h); if (screen) break; } } } } else { TRACE(PREFIX_I "GFX_AUTODETECT overridden through configuration:" " %s.\n", tmp1); } } else { /* search the list for the requested driver */ drv = get_gfx_driver_from_id(card, driver_list); if (drv) screen = init_gfx_driver(drv, w, h, v_w, v_h); } /* gracefully handle failure */ if (!screen) { gfx_driver = NULL; /* set by init_gfx_driver() */ if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to find a suitable graphics driver")); TRACE(PREFIX_E "Failed setting graphic driver %d.\n", card); return -1; } /* set the basic capabilities of the driver */ if ((VIRTUAL_W > SCREEN_W) || (VIRTUAL_H > SCREEN_H)) { if (gfx_driver->scroll) gfx_capabilities |= GFX_CAN_SCROLL; if ((gfx_driver->request_scroll) || (gfx_driver->request_video_bitmap)) gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; } /* check whether we are instructed to disable vsync */ dv = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("disable_vsync", tmp2), NULL); if ((dv) && ((c = ugetc(dv)) != 0) && ((c == 'y') || (c == 'Y') || (c == '1'))) _wait_for_vsync = FALSE; else _wait_for_vsync = TRUE; TRACE(PREFIX_I "The driver %s wait for vsync.\n", (_wait_for_vsync) ? "will" : "won't"); /* Give the gfx driver an opportunity to set the drawing mode */ if ((gfx_driver->drawing_mode) && (!_dispsw_status)) gfx_driver->drawing_mode(); clear_bitmap(screen); /* set up the default colors */ for (c=0; c<256; c++) _palette_color8[c] = c; set_palette(default_palette); if (_al_linker_mouse) _al_linker_mouse->set_mouse_etc(); LOCK_DATA(gfx_driver, sizeof(GFX_DRIVER)); _register_switch_bitmap(screen, NULL); TRACE(PREFIX_I "set_gfx_card success for %dx%dx%d.\n", screen->w, screen->h, bitmap_color_depth(screen)); return 0; }