Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sub license, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the
  14.  * next paragraph) shall be included in all copies or substantial portions
  15.  * of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  20.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  21.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  22.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  23.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  *
  26.  * Author: Alan Hourihane <alanh@tungstengraphics.com>
  27.  * Author: Jakob Bornecrantz <wallbraker@gmail.com>
  28.  *
  29.  */
  30.  
  31.  
  32. #include "xorg-server.h"
  33. #include "xf86.h"
  34. #include "xf86_OSproc.h"
  35. #include "compiler.h"
  36. #include "xf86PciInfo.h"
  37. #include "xf86Pci.h"
  38. #include "mipointer.h"
  39. #include "micmap.h"
  40. #include <X11/extensions/randr.h>
  41. #include "fb.h"
  42. #include "edid.h"
  43. #include "xf86i2c.h"
  44. #include "xf86Crtc.h"
  45. #include "miscstruct.h"
  46. #include "dixstruct.h"
  47. #include "xf86cmap.h"
  48. #include "xf86xv.h"
  49. #include "xorgVersion.h"
  50. #ifndef XSERVER_LIBPCIACCESS
  51. #error "libpciaccess needed"
  52. #endif
  53.  
  54. #include <pciaccess.h>
  55.  
  56. #include "state_tracker/drm_driver.h"
  57. #include "pipe/p_context.h"
  58. #include "xorg_tracker.h"
  59. #include "xorg_winsys.h"
  60.  
  61. #ifdef HAVE_LIBKMS
  62. #include "libkms/libkms.h"
  63. #endif
  64.  
  65. #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
  66. #define DamageUnregister(d, dd) DamageUnregister(dd)
  67. #endif
  68.  
  69. /*
  70.  * Functions and symbols exported to Xorg via pointers.
  71.  */
  72.  
  73. static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags);
  74. static Bool drv_screen_init(SCREEN_INIT_ARGS_DECL);
  75. static Bool drv_switch_mode(SWITCH_MODE_ARGS_DECL);
  76. static void drv_adjust_frame(ADJUST_FRAME_ARGS_DECL);
  77. static Bool drv_enter_vt(VT_FUNC_ARGS_DECL);
  78. static Bool drv_enter_vt_flags(ScrnInfoPtr pScrn, int flags);
  79. static void drv_leave_vt(VT_FUNC_ARGS_DECL);
  80. static void drv_free_screen(FREE_SCREEN_ARGS_DECL);
  81. static ModeStatus drv_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose,
  82.                                  int flags);
  83.  
  84. typedef enum
  85. {
  86.     OPTION_SW_CURSOR,
  87.     OPTION_2D_ACCEL,
  88.     OPTION_DEBUG_FALLBACK,
  89.     OPTION_THROTTLE_SWAP,
  90.     OPTION_THROTTLE_DIRTY,
  91.     OPTION_3D_ACCEL
  92. } drv_option_enums;
  93.  
  94. static const OptionInfoRec drv_options[] = {
  95.     {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
  96.     {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE},
  97.     {OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE},
  98.     {OPTION_THROTTLE_SWAP, "SwapThrottling", OPTV_BOOLEAN, {0}, FALSE},
  99.     {OPTION_THROTTLE_DIRTY, "DirtyThrottling", OPTV_BOOLEAN, {0}, FALSE},
  100.     {OPTION_3D_ACCEL, "3DAccel", OPTV_BOOLEAN, {0}, FALSE},
  101.     {-1, NULL, OPTV_NONE, {0}, FALSE}
  102. };
  103.  
  104.  
  105. /*
  106.  * Exported Xorg driver functions to winsys
  107.  */
  108.  
  109. const OptionInfoRec *
  110. xorg_tracker_available_options(int chipid, int busid)
  111. {
  112.     return drv_options;
  113. }
  114.  
  115. void
  116. xorg_tracker_set_functions(ScrnInfoPtr scrn)
  117. {
  118.     scrn->PreInit = drv_pre_init;
  119.     scrn->ScreenInit = drv_screen_init;
  120.     scrn->SwitchMode = drv_switch_mode;
  121.     scrn->AdjustFrame = drv_adjust_frame;
  122.     scrn->EnterVT = drv_enter_vt;
  123.     scrn->LeaveVT = drv_leave_vt;
  124.     scrn->FreeScreen = drv_free_screen;
  125.     scrn->ValidMode = drv_valid_mode;
  126. }
  127.  
  128. Bool
  129. xorg_tracker_have_modesetting(ScrnInfoPtr pScrn, struct pci_device *device)
  130. {
  131.     char *BusID = malloc(64);
  132.     sprintf(BusID, "pci:%04x:%02x:%02x.%d",
  133.             device->domain, device->bus,
  134.             device->dev, device->func);
  135.  
  136.     if (drmCheckModesettingSupported(BusID)) {
  137.         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
  138.                        "Drm modesetting not supported %s\n", BusID);
  139.         free(BusID);
  140.         return FALSE;
  141.     }
  142.  
  143.     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
  144.                    "Drm modesetting supported on %s\n", BusID);
  145.  
  146.     free(BusID);
  147.     return TRUE;
  148. }
  149.  
  150.  
  151. /*
  152.  * Internal function definitions
  153.  */
  154.  
  155. static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn);
  156. static Bool drv_close_screen(CLOSE_SCREEN_ARGS_DECL);
  157.  
  158.  
  159. /*
  160.  * Internal functions
  161.  */
  162.  
  163. static Bool
  164. drv_get_rec(ScrnInfoPtr pScrn)
  165. {
  166.     if (pScrn->driverPrivate)
  167.         return TRUE;
  168.  
  169.     pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec));
  170.  
  171.     return TRUE;
  172. }
  173.  
  174. static void
  175. drv_free_rec(ScrnInfoPtr pScrn)
  176. {
  177.     if (!pScrn)
  178.         return;
  179.  
  180.     if (!pScrn->driverPrivate)
  181.         return;
  182.  
  183.     free(pScrn->driverPrivate);
  184.  
  185.     pScrn->driverPrivate = NULL;
  186. }
  187.  
  188. static void
  189. drv_probe_ddc(ScrnInfoPtr pScrn, int index)
  190. {
  191.     ConfiguredMonitor = NULL;
  192. }
  193.  
  194. static Bool
  195. drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
  196. {
  197.     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  198.     modesettingPtr ms = modesettingPTR(pScrn);
  199.     CustomizerPtr cust = ms->cust;
  200.     ScreenPtr pScreen = pScrn->pScreen;
  201.     int old_width, old_height;
  202.     PixmapPtr rootPixmap;
  203.     int i;
  204.  
  205.     if (width == pScrn->virtualX && height == pScrn->virtualY)
  206.         return TRUE;
  207.  
  208.     if (cust && cust->winsys_check_fb_size &&
  209.         !cust->winsys_check_fb_size(cust, width*pScrn->bitsPerPixel / 8,
  210.                                     height)) {
  211.         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
  212.                    "Requested framebuffer size %dx%dx%d will not fit "
  213.                    "in display memory.\n",
  214.                    width, height, pScrn->bitsPerPixel);
  215.         return FALSE;
  216.     }
  217.  
  218.     old_width = pScrn->virtualX;
  219.     old_height = pScrn->virtualY;
  220.     pScrn->virtualX = width;
  221.     pScrn->virtualY = height;
  222.  
  223.     /* ms->create_front_buffer will remove the old front buffer */
  224.  
  225.     rootPixmap = pScreen->GetScreenPixmap(pScreen);
  226.     if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
  227.         goto error_modify;
  228.  
  229.     pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
  230.  
  231.     if (!ms->create_front_buffer(pScrn) || !ms->bind_front_buffer(pScrn))
  232.         goto error_create;
  233.  
  234.     /*
  235.      * create && bind will turn off all crtc(s) in the kernel so we need to
  236.      * re-enable all the crtcs again. For real HW we might want to do this
  237.      * before destroying the old framebuffer.
  238.      */
  239.     for (i = 0; i < xf86_config->num_crtc; i++) {
  240.         xf86CrtcPtr crtc = xf86_config->crtc[i];
  241.  
  242.         if (!crtc->enabled)
  243.             continue;
  244.  
  245.         crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y);
  246.     }
  247.  
  248.     return TRUE;
  249.  
  250.     /*
  251.      * This is the error recovery path.
  252.      */
  253. error_create:
  254.     if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL))
  255.         FatalError("failed to resize rootPixmap error path\n");
  256.  
  257.     pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
  258.  
  259. error_modify:
  260.     pScrn->virtualX = old_width;
  261.     pScrn->virtualY = old_height;
  262.  
  263.     if (ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn))
  264.         return FALSE;
  265.  
  266.     FatalError("failed to setup old framebuffer\n");
  267.     return FALSE;
  268. }
  269.  
  270. static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
  271.     .resize = drv_crtc_resize
  272. };
  273.  
  274. static Bool
  275. drv_init_drm(ScrnInfoPtr pScrn)
  276. {
  277.     modesettingPtr ms = modesettingPTR(pScrn);
  278.  
  279.     /* deal with server regeneration */
  280.     if (ms->fd < 0) {
  281.         char *BusID;
  282.  
  283.         BusID = malloc(64);
  284.         sprintf(BusID, "PCI:%d:%d:%d",
  285.                 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
  286.                 ms->PciInfo->dev, ms->PciInfo->func
  287.             );
  288.  
  289.  
  290.         ms->fd = drmOpen(driver_descriptor.driver_name, BusID);
  291.         ms->isMaster = TRUE;
  292.         free(BusID);
  293.  
  294.         if (ms->fd >= 0)
  295.             return TRUE;
  296.  
  297.         return FALSE;
  298.     }
  299.  
  300.     return TRUE;
  301. }
  302.  
  303. static Bool
  304. drv_init_resource_management(ScrnInfoPtr pScrn)
  305. {
  306.     modesettingPtr ms = modesettingPTR(pScrn);
  307.     /*
  308.     ScreenPtr pScreen = pScrn->pScreen;
  309.     PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
  310.     Bool fbAccessDisabled;
  311.     CARD8 *fbstart;
  312.      */
  313.  
  314.     if (ms->screen || ms->kms)
  315.         return TRUE;
  316.  
  317.     if (!ms->no3D)
  318.         ms->screen = driver_descriptor.create_screen(ms->fd);
  319.  
  320.     if (ms->screen)
  321.         return TRUE;
  322.  
  323. #ifdef HAVE_LIBKMS
  324.     if (!kms_create(ms->fd, &ms->kms))
  325.         return TRUE;
  326. #endif
  327.  
  328.     return FALSE;
  329. }
  330.  
  331. static void
  332. drv_cleanup_fences(ScrnInfoPtr pScrn)
  333. {
  334.     modesettingPtr ms = modesettingPTR(pScrn);
  335.     int i;
  336.  
  337.     assert(ms->screen);
  338.  
  339.     for (i = 0; i < XORG_NR_FENCES; i++) {
  340.         if (ms->fence[i]) {
  341.             ms->screen->fence_finish(ms->screen, ms->fence[i],
  342.                                      PIPE_TIMEOUT_INFINITE);
  343.             ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL);
  344.         }
  345.     }
  346. }
  347.  
  348. static Bool
  349. drv_pre_init(ScrnInfoPtr pScrn, int flags)
  350. {
  351.     xf86CrtcConfigPtr xf86_config;
  352.     modesettingPtr ms;
  353.     rgb defaultWeight = { 0, 0, 0 };
  354.     EntityInfoPtr pEnt;
  355.     EntPtr msEnt = NULL;
  356.     CustomizerPtr cust;
  357.     Bool use3D;
  358.  
  359.     if (pScrn->numEntities != 1)
  360.         return FALSE;
  361.  
  362.     pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
  363.  
  364.     if (flags & PROBE_DETECT) {
  365.         drv_probe_ddc(pScrn, pEnt->index);
  366.         return TRUE;
  367.     }
  368.  
  369.     cust = (CustomizerPtr) pScrn->driverPrivate;
  370.     pScrn->driverPrivate = NULL;
  371.  
  372.     /* Allocate driverPrivate */
  373.     if (!drv_get_rec(pScrn))
  374.         return FALSE;
  375.  
  376.     ms = modesettingPTR(pScrn);
  377.     ms->pEnt = pEnt;
  378.     ms->cust = cust;
  379.     ms->fb_id = -1;
  380.  
  381.     pScrn->displayWidth = 640;         /* default it */
  382.  
  383.     if (ms->pEnt->location.type != BUS_PCI)
  384.         return FALSE;
  385.  
  386.     ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
  387.  
  388.     /* Allocate an entity private if necessary */
  389.     if (xf86IsEntityShared(pScrn->entityList[0])) {
  390.         FatalError("Entity");
  391. #if 0
  392.         msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
  393.                                      modesettingEntityIndex)->ptr;
  394.         ms->entityPrivate = msEnt;
  395. #else
  396.         (void)msEnt;
  397. #endif
  398.     } else
  399.         ms->entityPrivate = NULL;
  400.  
  401.     if (xf86IsEntityShared(pScrn->entityList[0])) {
  402.         if (xf86IsPrimInitDone(pScrn->entityList[0])) {
  403.             /* do something */
  404.         } else {
  405.             xf86SetPrimInitDone(pScrn->entityList[0]);
  406.         }
  407.     }
  408.  
  409.     ms->fd = -1;
  410.     if (!drv_init_drm(pScrn))
  411.         return FALSE;
  412.  
  413.     pScrn->monitor = pScrn->confScreen->monitor;
  414.     pScrn->progClock = TRUE;
  415.     pScrn->rgbBits = 8;
  416.  
  417.     if (!xf86SetDepthBpp
  418.         (pScrn, 0, 0, 0,
  419.          PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
  420.         return FALSE;
  421.  
  422.     switch (pScrn->depth) {
  423.     case 8:
  424.     case 15:
  425.     case 16:
  426.     case 24:
  427.         break;
  428.     default:
  429.         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
  430.                    "Given depth (%d) is not supported by the driver\n",
  431.                    pScrn->depth);
  432.         return FALSE;
  433.     }
  434.     xf86PrintDepthBpp(pScrn);
  435.  
  436.     if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
  437.         return FALSE;
  438.     if (!xf86SetDefaultVisual(pScrn, -1))
  439.         return FALSE;
  440.  
  441.     /* Process the options */
  442.     xf86CollectOptions(pScrn, NULL);
  443.     if (!(ms->Options = malloc(sizeof(drv_options))))
  444.         return FALSE;
  445.     memcpy(ms->Options, drv_options, sizeof(drv_options));
  446.     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
  447.  
  448.     use3D = cust ? !cust->no_3d : TRUE;
  449.     ms->from_3D = xf86GetOptValBool(ms->Options, OPTION_3D_ACCEL,
  450.                                     &use3D) ?
  451.         X_CONFIG : X_PROBED;
  452.  
  453.     ms->no3D = !use3D;
  454.  
  455.     if (!drv_init_resource_management(pScrn)) {
  456.         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not init "
  457.                                                "Gallium3D or libKMS.\n");
  458.         return FALSE;
  459.     }
  460.  
  461.     /* Allocate an xf86CrtcConfig */
  462.     xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
  463.     xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  464.  
  465.     /* get max width and height */
  466.     {
  467.         drmModeResPtr res;
  468.         int max_width, max_height;
  469.  
  470.         res = drmModeGetResources(ms->fd);
  471.         max_width = res->max_width;
  472.         max_height = res->max_height;
  473.  
  474.         if (ms->screen) {
  475.             int max;
  476.  
  477.             max = ms->screen->get_param(ms->screen,
  478.                                         PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
  479.             max = 1 << (max - 1);
  480.             max_width = max < max_width ? max : max_width;
  481.             max_height = max < max_height ? max : max_height;
  482.         }
  483.  
  484.         xf86CrtcSetSizeRange(pScrn, res->min_width,
  485.                              res->min_height, max_width, max_height);
  486.         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
  487.                    "Min width %d, Max Width %d.\n",
  488.                    res->min_width, max_width);
  489.         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
  490.                    "Min height %d, Max Height %d.\n",
  491.                    res->min_height, max_height);
  492.         drmModeFreeResources(res);
  493.     }
  494.  
  495.  
  496.     if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
  497.         ms->SWCursor = TRUE;
  498.     }
  499.  
  500.     xorg_crtc_init(pScrn);
  501.     xorg_output_init(pScrn);
  502.  
  503.     if (cust && cust->winsys_pre_init && !cust->winsys_pre_init(cust, ms->fd))
  504.         return FALSE;
  505.  
  506.     if (!xf86InitialConfiguration(pScrn, TRUE)) {
  507.         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
  508.         return FALSE;
  509.     }
  510.  
  511.     /*
  512.      * If the driver can do gamma correction, it should call xf86SetGamma() here.
  513.      */
  514.     {
  515.         Gamma zeros = { 0.0, 0.0, 0.0 };
  516.  
  517.         if (!xf86SetGamma(pScrn, zeros)) {
  518.             return FALSE;
  519.         }
  520.     }
  521.  
  522.     if (pScrn->modes == NULL) {
  523.         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
  524.         return FALSE;
  525.     }
  526.  
  527.     pScrn->currentMode = pScrn->modes;
  528.  
  529.     /* Set display resolution */
  530.     xf86SetDpi(pScrn, 0, 0);
  531.  
  532.     /* Load the required sub modules */
  533.     if (!xf86LoadSubModule(pScrn, "fb"))
  534.         return FALSE;
  535.  
  536.     /* XXX: these aren't needed when we are using libkms */
  537.     if (!xf86LoadSubModule(pScrn, "exa"))
  538.         return FALSE;
  539.  
  540. #ifdef DRI2
  541.     if (!xf86LoadSubModule(pScrn, "dri2"))
  542.         return FALSE;
  543. #endif
  544.  
  545.     return TRUE;
  546. }
  547.  
  548. void xorg_flush(ScreenPtr pScreen)
  549. {
  550.     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
  551.  
  552.     if (ms->ctx) {
  553.         int j;
  554.  
  555.         ms->ctx->flush(ms->ctx,
  556.                        ms->dirtyThrottling ?
  557.                        &ms->fence[XORG_NR_FENCES-1] :
  558.                        NULL, 0);
  559.        
  560.         if (ms->dirtyThrottling) {
  561.             if (ms->fence[0])
  562.                 ms->ctx->screen->fence_finish(ms->ctx->screen,
  563.                                               ms->fence[0],
  564.                                               PIPE_TIMEOUT_INFINITE);
  565.  
  566.             /* The amount of rendering generated by a block handler can be
  567.              * quite small.  Let us get a fair way ahead of hardware before
  568.              * throttling.
  569.              */
  570.             for (j = 0; j < XORG_NR_FENCES - 1; j++)
  571.                 ms->screen->fence_reference(ms->screen,
  572.                                             &ms->fence[j],
  573.                                             ms->fence[j+1]);
  574.  
  575.             ms->screen->fence_reference(ms->screen,
  576.                                         &ms->fence[XORG_NR_FENCES-1],
  577.                                         NULL);
  578.         }
  579.     }
  580.  
  581. #ifdef DRM_MODE_FEATURE_DIRTYFB
  582.     {
  583.         RegionPtr dirty = DamageRegion(ms->damage);
  584.         unsigned num_cliprects = REGION_NUM_RECTS(dirty);
  585.  
  586.         if (num_cliprects) {
  587.             drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
  588.             BoxPtr rect = REGION_RECTS(dirty);
  589.             int i, ret;
  590.  
  591.             /* XXX no need for copy? */
  592.             for (i = 0; i < num_cliprects; i++, rect++) {
  593.                 clip[i].x1 = rect->x1;
  594.                 clip[i].y1 = rect->y1;
  595.                 clip[i].x2 = rect->x2;
  596.                 clip[i].y2 = rect->y2;
  597.             }
  598.  
  599.             /* TODO query connector property to see if this is needed */
  600.             ret = drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects);
  601.             if (ret) {
  602.                 debug_printf("%s: failed to send dirty (%i, %s)\n",
  603.                              __func__, ret, strerror(-ret));
  604.             }
  605.  
  606.             DamageEmpty(ms->damage);
  607.         }
  608.     }
  609. #endif
  610. }
  611.  
  612. static void drv_block_handler(BLOCKHANDLER_ARGS_DECL)
  613. {
  614.     SCREEN_PTR(arg);
  615.     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
  616.  
  617.     pScreen->BlockHandler = ms->blockHandler;
  618.     pScreen->BlockHandler(BLOCKHANDLER_ARGS);
  619.     pScreen->BlockHandler = drv_block_handler;
  620.  
  621.     xorg_flush(pScreen);
  622. }
  623.  
  624. static Bool
  625. drv_create_screen_resources(ScreenPtr pScreen)
  626. {
  627.     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  628.     modesettingPtr ms = modesettingPTR(pScrn);
  629.     PixmapPtr rootPixmap;
  630.     Bool ret;
  631.  
  632.     ms->noEvict = TRUE;
  633.  
  634.     pScreen->CreateScreenResources = ms->createScreenResources;
  635.     ret = pScreen->CreateScreenResources(pScreen);
  636.     pScreen->CreateScreenResources = drv_create_screen_resources;
  637.  
  638.     ms->bind_front_buffer(pScrn);
  639.  
  640.     ms->noEvict = FALSE;
  641.  
  642.     drv_adjust_frame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
  643.  
  644. #ifdef DRM_MODE_FEATURE_DIRTYFB
  645.     rootPixmap = pScreen->GetScreenPixmap(pScreen);
  646.     ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
  647.                               pScreen, rootPixmap);
  648.  
  649.     if (ms->damage) {
  650.        DamageRegister(&rootPixmap->drawable, ms->damage);
  651.  
  652.        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
  653.     } else {
  654.        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
  655.                   "Failed to create screen damage record\n");
  656.        return FALSE;
  657.     }
  658. #else
  659.     (void)rootPixmap;
  660. #endif
  661.  
  662.     return ret;
  663. }
  664.  
  665. static Bool
  666. drv_set_master(ScrnInfoPtr pScrn)
  667. {
  668.     modesettingPtr ms = modesettingPTR(pScrn);
  669.  
  670.     if (!ms->isMaster && drmSetMaster(ms->fd) != 0) {
  671.         if (errno == EINVAL) {
  672.             xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  673.                        "drmSetMaster failed: 2.6.29 or newer kernel required for "
  674.                        "multi-server DRI\n");
  675.         } else {
  676.             xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  677.                        "drmSetMaster failed: %s\n", strerror(errno));
  678.         }
  679.         return FALSE;
  680.     }
  681.  
  682.     ms->isMaster = TRUE;
  683.     return TRUE;
  684. }
  685.  
  686.  
  687. static void drv_load_palette(ScrnInfoPtr pScrn, int numColors,
  688.                              int *indices, LOCO *colors, VisualPtr pVisual)
  689. {
  690.     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  691.     modesettingPtr ms = modesettingPTR(pScrn);
  692.     int index, j, i;
  693.     int c;
  694.  
  695.     switch(pScrn->depth) {
  696.     case 15:
  697.         for (i = 0; i < numColors; i++) {
  698.             index = indices[i];
  699.             for (j = 0; j < 8; j++) {
  700.                 ms->lut_r[index * 8 + j] = colors[index].red << 8;
  701.                 ms->lut_g[index * 8 + j] = colors[index].green << 8;
  702.                 ms->lut_b[index * 8 + j] = colors[index].blue << 8;
  703.             }
  704.         }
  705.         break;
  706.     case 16:
  707.         for (i = 0; i < numColors; i++) {
  708.             index = indices[i];
  709.  
  710.             if (index < 32) {
  711.                 for (j = 0; j < 8; j++) {
  712.                     ms->lut_r[index * 8 + j] = colors[index].red << 8;
  713.                     ms->lut_b[index * 8 + j] = colors[index].blue << 8;
  714.                 }
  715.             }
  716.  
  717.             for (j = 0; j < 4; j++) {
  718.                 ms->lut_g[index * 4 + j] = colors[index].green << 8;
  719.             }
  720.         }
  721.         break;
  722.     default:
  723.         for (i = 0; i < numColors; i++) {
  724.             index = indices[i];
  725.             ms->lut_r[index] = colors[index].red << 8;
  726.             ms->lut_g[index] = colors[index].green << 8;
  727.             ms->lut_b[index] = colors[index].blue << 8;
  728.         }
  729.         break;
  730.     }
  731.  
  732.     for (c = 0; c < xf86_config->num_crtc; c++) {
  733.         xf86CrtcPtr crtc = xf86_config->crtc[c];
  734.  
  735.         /* Make the change through RandR */
  736. #ifdef RANDR_12_INTERFACE
  737.         if (crtc->randr_crtc)
  738.             RRCrtcGammaSet(crtc->randr_crtc, ms->lut_r, ms->lut_g, ms->lut_b);
  739.         else
  740. #endif
  741.             crtc->funcs->gamma_set(crtc, ms->lut_r, ms->lut_g, ms->lut_b, 256);
  742.     }
  743. }
  744.  
  745.  
  746. static Bool
  747. drv_screen_init(SCREEN_INIT_ARGS_DECL)
  748. {
  749.     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  750.     modesettingPtr ms = modesettingPTR(pScrn);
  751.     VisualPtr visual;
  752.     CustomizerPtr cust = ms->cust;
  753.     MessageType from_st;
  754.     MessageType from_dt;
  755.  
  756.     if (!drv_set_master(pScrn))
  757.         return FALSE;
  758.  
  759.     if (!drv_init_front_buffer_functions(pScrn)) {
  760.         FatalError("Could not init front buffer manager");
  761.         return FALSE;
  762.     }
  763.  
  764.     pScrn->pScreen = pScreen;
  765.  
  766.     /* HW dependent - FIXME */
  767.     pScrn->displayWidth = pScrn->virtualX;
  768.  
  769.     miClearVisualTypes();
  770.  
  771.     if (!miSetVisualTypes(pScrn->depth,
  772.                           miGetDefaultVisualMask(pScrn->depth),
  773.                           pScrn->rgbBits, pScrn->defaultVisual))
  774.         return FALSE;
  775.  
  776.     if (!miSetPixmapDepths())
  777.         return FALSE;
  778.  
  779.     pScrn->memPhysBase = 0;
  780.     pScrn->fbOffset = 0;
  781.  
  782.     if (!fbScreenInit(pScreen, NULL,
  783.                       pScrn->virtualX, pScrn->virtualY,
  784.                       pScrn->xDpi, pScrn->yDpi,
  785.                       pScrn->displayWidth, pScrn->bitsPerPixel))
  786.         return FALSE;
  787.  
  788.     if (pScrn->bitsPerPixel > 8) {
  789.         /* Fixup RGB ordering */
  790.         visual = pScreen->visuals + pScreen->numVisuals;
  791.         while (--visual >= pScreen->visuals) {
  792.             if ((visual->class | DynamicClass) == DirectColor) {
  793.                 visual->offsetRed = pScrn->offset.red;
  794.                 visual->offsetGreen = pScrn->offset.green;
  795.                 visual->offsetBlue = pScrn->offset.blue;
  796.                 visual->redMask = pScrn->mask.red;
  797.                 visual->greenMask = pScrn->mask.green;
  798.                 visual->blueMask = pScrn->mask.blue;
  799.             }
  800.         }
  801.     }
  802.  
  803.     fbPictureInit(pScreen, NULL, 0);
  804.  
  805.     ms->blockHandler = pScreen->BlockHandler;
  806.     pScreen->BlockHandler = drv_block_handler;
  807.     ms->createScreenResources = pScreen->CreateScreenResources;
  808.     pScreen->CreateScreenResources = drv_create_screen_resources;
  809.  
  810.     xf86SetBlackWhitePixels(pScreen);
  811.  
  812.     ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE);
  813.     ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d);
  814.  
  815.     if (cust && cust->winsys_screen_init)
  816.         cust->winsys_screen_init(cust);
  817.  
  818.     ms->swapThrottling = cust ?  cust->swap_throttling : TRUE;
  819.     from_st = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_SWAP,
  820.                                 &ms->swapThrottling) ?
  821.         X_CONFIG : X_DEFAULT;
  822.  
  823.     ms->dirtyThrottling = cust ?  cust->dirty_throttling : FALSE;
  824.     from_dt = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_DIRTY,
  825.                                 &ms->dirtyThrottling) ?
  826.         X_CONFIG : X_DEFAULT;
  827.  
  828.     if (ms->screen) {
  829.         ms->exa = xorg_exa_init(pScrn, ms->accelerate_2d);
  830.  
  831.         xorg_xv_init(pScreen);
  832. #ifdef DRI2
  833.         xorg_dri2_init(pScreen);
  834. #endif
  835.     }
  836.  
  837.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "#################################\n");
  838.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "# Useful debugging info follows #\n");
  839.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "#################################\n");
  840.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s backend\n",
  841.                ms->screen ? "Gallium3D" : "libkms");
  842.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s\n",
  843.                ms->screen && ms->accelerate_2d ? "enabled" : "disabled");
  844.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s\n",
  845.                ms->debug_fallback ? "enabled" : "disabled");
  846. #ifdef DRI2
  847.     xf86DrvMsg(pScrn->scrnIndex, ms->from_3D, "3D Acceleration is %s\n",
  848.                ms->screen ? "enabled" : "disabled");
  849. #else
  850.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled\n");
  851. #endif
  852.     xf86DrvMsg(pScrn->scrnIndex, from_st, "Swap Throttling is %s.\n",
  853.                ms->swapThrottling ? "enabled" : "disabled");
  854.     xf86DrvMsg(pScrn->scrnIndex, from_dt, "Dirty Throttling is %s.\n",
  855.                ms->dirtyThrottling ? "enabled" : "disabled");
  856.  
  857.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n");
  858.  
  859.     xf86SetBackingStore(pScreen);
  860.     xf86SetSilkenMouse(pScreen);
  861.     miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
  862.  
  863.     /* Need to extend HWcursor support to handle mask interleave */
  864.     if (!ms->SWCursor)
  865.         xf86_cursors_init(pScreen, 64, 64,
  866.                           HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
  867.                           HARDWARE_CURSOR_ARGB |
  868.                           ((cust && cust->unhidden_hw_cursor_update) ?
  869.                            HARDWARE_CURSOR_UPDATE_UNHIDDEN : 0));
  870.  
  871.     /* Must force it before EnterVT, so we are in control of VT and
  872.      * later memory should be bound when allocating, e.g rotate_mem */
  873.     pScrn->vtSema = TRUE;
  874.  
  875.     pScreen->SaveScreen = xf86SaveScreen;
  876.     ms->CloseScreen = pScreen->CloseScreen;
  877.     pScreen->CloseScreen = drv_close_screen;
  878.  
  879.     if (!xf86CrtcScreenInit(pScreen))
  880.         return FALSE;
  881.  
  882.     if (!miCreateDefColormap(pScreen))
  883.         return FALSE;
  884.     if (!xf86HandleColormaps(pScreen, 256, 8, drv_load_palette, NULL,
  885.                              CMAP_PALETTED_TRUECOLOR |
  886.                              CMAP_RELOAD_ON_MODE_SWITCH))
  887.         return FALSE;
  888.  
  889.     xf86DPMSInit(pScreen, xf86DPMSSet, 0);
  890.  
  891.     if (serverGeneration == 1)
  892.         xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
  893.  
  894.     return drv_enter_vt_flags(pScrn, 1);
  895. }
  896.  
  897. static void
  898. drv_adjust_frame(ADJUST_FRAME_ARGS_DECL)
  899. {
  900.     SCRN_INFO_PTR(arg);
  901.     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
  902.     xf86OutputPtr output = config->output[config->compat_output];
  903.     xf86CrtcPtr crtc = output->crtc;
  904.  
  905.     if (crtc && crtc->enabled) {
  906.         crtc->funcs->set_mode_major(crtc, pScrn->currentMode,
  907.                                     RR_Rotate_0, x, y);
  908.         crtc->x = output->initial_x + x;
  909.         crtc->y = output->initial_y + y;
  910.     }
  911. }
  912.  
  913. static void
  914. drv_free_screen(FREE_SCREEN_ARGS_DECL)
  915. {
  916.     SCRN_INFO_PTR(arg);
  917.     drv_free_rec(pScrn);
  918. }
  919.  
  920. static void
  921. drv_leave_vt(VT_FUNC_ARGS_DECL)
  922. {
  923.     SCRN_INFO_PTR(arg);
  924.     modesettingPtr ms = modesettingPTR(pScrn);
  925.     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
  926.     CustomizerPtr cust = ms->cust;
  927.     int o;
  928.  
  929.     if (cust && cust->winsys_leave_vt)
  930.         cust->winsys_leave_vt(cust);
  931.  
  932.     for (o = 0; o < config->num_crtc; o++) {
  933.         xf86CrtcPtr crtc = config->crtc[o];
  934.  
  935.         xorg_crtc_cursor_destroy(crtc);
  936.  
  937.         if (crtc->rotatedPixmap || crtc->rotatedData) {
  938.             crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
  939.                                         crtc->rotatedData);
  940.             crtc->rotatedPixmap = NULL;
  941.             crtc->rotatedData = NULL;
  942.         }
  943.     }
  944.  
  945.     if (ms->fb_id != -1) {
  946.         drmModeRmFB(ms->fd, ms->fb_id);
  947.         ms->fb_id = -1;
  948.     }
  949.  
  950.     /* idle hardware */
  951.     if (!ms->kms)
  952.         drv_cleanup_fences(pScrn);
  953.  
  954.     if (drmDropMaster(ms->fd))
  955.         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  956.                    "drmDropMaster failed: %s\n", strerror(errno));
  957.  
  958.     ms->isMaster = FALSE;
  959.     pScrn->vtSema = FALSE;
  960. }
  961.  
  962. /*
  963.  * This gets called when gaining control of the VT, and from ScreenInit().
  964.  */
  965. static Bool
  966. drv_enter_vt_flags(ScrnInfoPtr pScrn, int flags)
  967. {
  968.     modesettingPtr ms = modesettingPTR(pScrn);
  969.     CustomizerPtr cust = ms->cust;
  970.  
  971.     if (!drv_set_master(pScrn))
  972.         return FALSE;
  973.  
  974.     if (!ms->create_front_buffer(pScrn))
  975.         return FALSE;
  976.  
  977.     if (!flags && !ms->bind_front_buffer(pScrn))
  978.         return FALSE;
  979.  
  980.     if (!xf86SetDesiredModes(pScrn))
  981.         return FALSE;
  982.  
  983.     if (cust && cust->winsys_enter_vt)
  984.         cust->winsys_enter_vt(cust);
  985.  
  986.     return TRUE;
  987. }
  988.  
  989. static Bool
  990. drv_enter_vt(VT_FUNC_ARGS_DECL)
  991. {
  992.     SCRN_INFO_PTR(arg);
  993.     return drv_enter_vt_flags(pScrn, 0);
  994. }
  995.  
  996. static Bool
  997. drv_switch_mode(SWITCH_MODE_ARGS_DECL)
  998. {
  999.     SCRN_INFO_PTR(arg);
  1000.  
  1001.     return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
  1002. }
  1003.  
  1004. static Bool
  1005. drv_close_screen(CLOSE_SCREEN_ARGS_DECL)
  1006. {
  1007.     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  1008.     modesettingPtr ms = modesettingPTR(pScrn);
  1009.     CustomizerPtr cust = ms->cust;
  1010.  
  1011.     if (ms->cursor) {
  1012.        FreeCursor(ms->cursor, None);
  1013.        ms->cursor = NULL;
  1014.     }
  1015.  
  1016.     if (cust && cust->winsys_screen_close)
  1017.         cust->winsys_screen_close(cust);
  1018.  
  1019. #ifdef DRI2
  1020.     if (ms->screen)
  1021.         xorg_dri2_close(pScreen);
  1022. #endif
  1023.  
  1024.     pScreen->BlockHandler = ms->blockHandler;
  1025.     pScreen->CreateScreenResources = ms->createScreenResources;
  1026.  
  1027. #ifdef DRM_MODE_FEATURE_DIRTYFB
  1028.     if (ms->damage) {
  1029.         DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
  1030.         DamageDestroy(ms->damage);
  1031.         ms->damage = NULL;
  1032.     }
  1033. #endif
  1034.  
  1035.     ms->destroy_front_buffer(pScrn);
  1036.  
  1037.     if (ms->exa)
  1038.         xorg_exa_close(pScrn);
  1039.     ms->exa = NULL;
  1040.  
  1041.     /* calls drop master make sure we don't talk to 3D HW after that */
  1042.     if (pScrn->vtSema) {
  1043.         drv_leave_vt(VT_FUNC_ARGS);
  1044.     }
  1045.  
  1046.     pScrn->vtSema = FALSE;
  1047.     pScreen->CloseScreen = ms->CloseScreen;
  1048.  
  1049.     return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
  1050. }
  1051.  
  1052. static ModeStatus
  1053. drv_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
  1054. {
  1055.     return MODE_OK;
  1056. }
  1057.  
  1058.  
  1059. /*
  1060.  * Front buffer backing store functions.
  1061.  */
  1062.  
  1063. static Bool
  1064. drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn)
  1065. {
  1066.     modesettingPtr ms = modesettingPTR(pScrn);
  1067.  
  1068.     if (!ms->root_texture)
  1069.         return TRUE;
  1070.  
  1071.     if (ms->fb_id != -1) {
  1072.         drmModeRmFB(ms->fd, ms->fb_id);
  1073.         ms->fb_id = -1;
  1074.     }
  1075.  
  1076.     pipe_resource_reference(&ms->root_texture, NULL);
  1077.     return TRUE;
  1078. }
  1079.  
  1080. static Bool
  1081. drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
  1082. {
  1083.     modesettingPtr ms = modesettingPTR(pScrn);
  1084.     struct pipe_resource *tex;
  1085.     struct winsys_handle whandle;
  1086.     unsigned fb_id;
  1087.     int ret;
  1088.  
  1089.     ms->noEvict = TRUE;
  1090.  
  1091.     tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY,
  1092.                                        pScrn->depth, pScrn->bitsPerPixel);
  1093.  
  1094.     if (!tex)
  1095.         return FALSE;
  1096.  
  1097.     memset(&whandle, 0, sizeof(whandle));
  1098.     whandle.type = DRM_API_HANDLE_TYPE_KMS;
  1099.  
  1100.     if (!ms->screen->resource_get_handle(ms->screen, tex, &whandle))
  1101.         goto err_destroy;
  1102.  
  1103.     ret = drmModeAddFB(ms->fd,
  1104.                        pScrn->virtualX,
  1105.                        pScrn->virtualY,
  1106.                        pScrn->depth,
  1107.                        pScrn->bitsPerPixel,
  1108.                        whandle.stride,
  1109.                        whandle.handle,
  1110.                        &fb_id);
  1111.     if (ret) {
  1112.         debug_printf("%s: failed to create framebuffer (%i, %s)\n",
  1113.                      __func__, ret, strerror(-ret));
  1114.         goto err_destroy;
  1115.     }
  1116.  
  1117.     if (!drv_destroy_front_buffer_ga3d(pScrn))
  1118.         FatalError("%s: failed to take down old framebuffer\n", __func__);
  1119.  
  1120.     pScrn->frameX0 = 0;
  1121.     pScrn->frameY0 = 0;
  1122.     drv_adjust_frame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
  1123.  
  1124.     pipe_resource_reference(&ms->root_texture, tex);
  1125.     pipe_resource_reference(&tex, NULL);
  1126.     ms->fb_id = fb_id;
  1127.  
  1128.     return TRUE;
  1129.  
  1130. err_destroy:
  1131.     pipe_resource_reference(&tex, NULL);
  1132.     return FALSE;
  1133. }
  1134.  
  1135. static Bool
  1136. drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn)
  1137. {
  1138.     modesettingPtr ms = modesettingPTR(pScrn);
  1139.     ScreenPtr pScreen = pScrn->pScreen;
  1140.     PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
  1141.     struct pipe_resource *check;
  1142.  
  1143.     xorg_exa_set_displayed_usage(rootPixmap);
  1144.     xorg_exa_set_shared_usage(rootPixmap);
  1145.     xorg_exa_set_texture(rootPixmap, ms->root_texture);
  1146.     if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
  1147.         FatalError("Couldn't adjust screen pixmap\n");
  1148.  
  1149.     check = xorg_exa_get_texture(rootPixmap);
  1150.     if (ms->root_texture != check)
  1151.         FatalError("Created new root texture\n");
  1152.  
  1153.     pipe_resource_reference(&check, NULL);
  1154.     return TRUE;
  1155. }
  1156.  
  1157. #ifdef HAVE_LIBKMS
  1158. static Bool
  1159. drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn)
  1160. {
  1161.     modesettingPtr ms = modesettingPTR(pScrn);
  1162.     ScreenPtr pScreen = pScrn->pScreen;
  1163.     PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
  1164.  
  1165.     /* XXX Do something with the rootPixmap.
  1166.      * This currently works fine but if we are getting crashes in
  1167.      * the fb functions after VT switches maybe look more into it.
  1168.      */
  1169.     (void)rootPixmap;
  1170.  
  1171.     if (!ms->root_bo)
  1172.         return TRUE;
  1173.  
  1174.     if (ms->fb_id != -1) {
  1175.         drmModeRmFB(ms->fd, ms->fb_id);
  1176.         ms->fb_id = -1;
  1177.     }
  1178.  
  1179.     kms_bo_unmap(ms->root_bo);
  1180.     kms_bo_destroy(&ms->root_bo);
  1181.     return TRUE;
  1182. }
  1183.  
  1184. static Bool
  1185. drv_create_front_buffer_kms(ScrnInfoPtr pScrn)
  1186. {
  1187.     modesettingPtr ms = modesettingPTR(pScrn);
  1188.     unsigned handle, stride;
  1189.     struct kms_bo *bo;
  1190.     unsigned attr[8];
  1191.     unsigned fb_id;
  1192.     int ret;
  1193.  
  1194.     attr[0] = KMS_BO_TYPE;
  1195. #ifdef KMS_BO_TYPE_SCANOUT_X8R8G8B8
  1196.     attr[1] = KMS_BO_TYPE_SCANOUT_X8R8G8B8;
  1197. #else
  1198.     attr[1] = KMS_BO_TYPE_SCANOUT;
  1199. #endif
  1200.     attr[2] = KMS_WIDTH;
  1201.     attr[3] = pScrn->virtualX;
  1202.     attr[4] = KMS_HEIGHT;
  1203.     attr[5] = pScrn->virtualY;
  1204.     attr[6] = 0;
  1205.  
  1206.     if (kms_bo_create(ms->kms, attr, &bo))
  1207.         return FALSE;
  1208.  
  1209.     if (kms_bo_get_prop(bo, KMS_PITCH, &stride))
  1210.         goto err_destroy;
  1211.  
  1212.     if (kms_bo_get_prop(bo, KMS_HANDLE, &handle))
  1213.         goto err_destroy;
  1214.  
  1215.     ret = drmModeAddFB(ms->fd,
  1216.                        pScrn->virtualX,
  1217.                        pScrn->virtualY,
  1218.                        pScrn->depth,
  1219.                        pScrn->bitsPerPixel,
  1220.                        stride,
  1221.                        handle,
  1222.                        &fb_id);
  1223.     if (ret) {
  1224.         debug_printf("%s: failed to create framebuffer (%i, %s)",
  1225.                      __func__, ret, strerror(-ret));
  1226.         goto err_destroy;
  1227.     }
  1228.  
  1229.     if (!drv_destroy_front_buffer_kms(pScrn))
  1230.         FatalError("%s: could not takedown old bo", __func__);
  1231.  
  1232.     pScrn->frameX0 = 0;
  1233.     pScrn->frameY0 = 0;
  1234.     drv_adjust_frame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
  1235.     ms->root_bo = bo;
  1236.     ms->fb_id = fb_id;
  1237.  
  1238.     return TRUE;
  1239.  
  1240. err_destroy:
  1241.     kms_bo_destroy(&bo);
  1242.     return FALSE;
  1243. }
  1244.  
  1245. static Bool
  1246. drv_bind_front_buffer_kms(ScrnInfoPtr pScrn)
  1247. {
  1248.     modesettingPtr ms = modesettingPTR(pScrn);
  1249.     ScreenPtr pScreen = pScrn->pScreen;
  1250.     PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
  1251.     unsigned stride;
  1252.     void *ptr;
  1253.  
  1254.     if (kms_bo_get_prop(ms->root_bo, KMS_PITCH, &stride))
  1255.         return FALSE;
  1256.  
  1257.     if (kms_bo_map(ms->root_bo, &ptr))
  1258.         goto err_destroy;
  1259.  
  1260.     pScreen->ModifyPixmapHeader(rootPixmap,
  1261.                                 pScrn->virtualX,
  1262.                                 pScrn->virtualY,
  1263.                                 pScreen->rootDepth,
  1264.                                 pScrn->bitsPerPixel,
  1265.                                 stride,
  1266.                                 ptr);
  1267.  
  1268. #if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0))
  1269.  
  1270.     /* This a hack to work around EnableDisableFBAccess setting the pointer
  1271.      * the real fix would be to replace pScrn->EnableDisableFBAccess hook
  1272.      * and set the rootPixmap->devPrivate.ptr to something valid before that.
  1273.      *
  1274.      * But in its infinit visdome something uses either this some times before
  1275.      * that, so our hook doesn't get called before the crash happens.
  1276.      */
  1277.     pScrn->pixmapPrivate.ptr = ptr;
  1278.  
  1279. #endif
  1280.  
  1281.     return TRUE;
  1282.  
  1283. err_destroy:
  1284.     kms_bo_destroy(&ms->root_bo);
  1285.     return FALSE;
  1286. }
  1287. #endif /* HAVE_LIBKMS */
  1288.  
  1289. static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn)
  1290. {
  1291.     modesettingPtr ms = modesettingPTR(pScrn);
  1292.     if (ms->screen) {
  1293.         ms->destroy_front_buffer = drv_destroy_front_buffer_ga3d;
  1294.         ms->create_front_buffer = drv_create_front_buffer_ga3d;
  1295.         ms->bind_front_buffer = drv_bind_front_buffer_ga3d;
  1296. #ifdef HAVE_LIBKMS
  1297.     } else if (ms->kms) {
  1298.         ms->destroy_front_buffer = drv_destroy_front_buffer_kms;
  1299.         ms->create_front_buffer = drv_create_front_buffer_kms;
  1300.         ms->bind_front_buffer = drv_bind_front_buffer_kms;
  1301. #endif
  1302.     } else
  1303.         return FALSE;
  1304.  
  1305.     return TRUE;
  1306. }
  1307.  
  1308. CustomizerPtr xorg_customizer(ScrnInfoPtr pScrn)
  1309. {
  1310.     return modesettingPTR(pScrn)->cust;
  1311. }
  1312.  
  1313. Bool xorg_has_gallium(ScrnInfoPtr pScrn)
  1314. {
  1315.     return modesettingPTR(pScrn)->screen != NULL;
  1316. }
  1317.  
  1318. /* vim: set sw=4 ts=8 sts=4: */
  1319.