示例#1
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;
}
示例#2
0
/* _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;
}