This provides a driver hook which can either completely replace, or
just validate the parameters for, the RRSetCrtcConfigs request.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 hw/xfree86/modes/xf86Crtc.h    |   29 +++++++
 hw/xfree86/modes/xf86RandR12.c |  162 +++++++++++++++++++++++++++++++++-------
 2 files changed, 163 insertions(+), 28 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 8b42efc..c2e8131 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -647,6 +647,29 @@ struct _xf86Output {
     INT16           initialBorder[4];
 };
 
+typedef enum _xf86SetConfigResponse {
+    xf86SetConfigFailed,               /* set_config failed */
+    xf86SetConfigChecked,              /* set_config validated the 
configuration */
+    xf86SetConfigDone,                 /* set_config finished the work */
+} xf86SetConfigResponse;
+
+typedef struct _xf86CrtcSetConfig {
+    xf86CrtcPtr                        crtc;
+    int                                x, y;
+    DisplayModeRec             mode;
+    Rotation                   rotation;
+    int                                numOutputs;
+    xf86OutputPtr              *outputs;
+    struct pict_f_transform    sprite_position_transform;
+    struct pict_f_transform    sprite_image_transform;
+
+    /* Probably want some internal structure for the pixmap so that
+     * this can be set before the server is running
+     */
+    PixmapPtr                  pixmap;
+    int                                pixmap_x, pixmap_y;
+} xf86CrtcSetConfigRec, *xf86CrtcSetConfigPtr;
+
 typedef struct _xf86CrtcConfigFuncs {
     /**
      * Requests that the driver resize the screen.
@@ -664,6 +687,12 @@ typedef struct _xf86CrtcConfigFuncs {
     (*resize)(ScrnInfoPtr      scrn,
              int               width,
              int               height);
+
+    xf86SetConfigResponse
+    (*set_config) (ScrnInfoPtr         scrn,
+                  RRScreenConfigPtr    screen_config,
+                  xf86CrtcSetConfigPtr crtc_configs,
+                  int                  num_configs);
 } xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
 
 typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen);
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index ac58135..e3330f4 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -758,7 +758,7 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
        xf86CrtcPtr crtc = config->crtc[c];
        int         crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, 
crtc->rotation);
        int         crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, 
crtc->rotation);
-       
+
        if (crtc->enabled) {
            if (crtc_width > width)
                width = crtc_width;
@@ -770,13 +770,13 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
                height = crtc->panningTotalArea.y2;
        }
     }
-    
+
     if (width && height)
     {
        /*
         * Compute physical size of screen
         */
-       if (monitorResolution) 
+       if (monitorResolution)
        {
            mmWidth = width * 25.4 / monitorResolution;
            mmHeight = height * 25.4 / monitorResolution;
@@ -1007,7 +1007,7 @@ xf86RandRModeMatches (RRModePtr           randr_mode,
        if (memcmp (randr_mode->name, mode->name, len) != 0)    return FALSE;
     }
 #endif
-    
+
     /* check for same timings */
     if (randr_mode->mode.dotClock / 1000 != mode->Clock)    return FALSE;
     if (randr_mode->mode.width        != mode->HDisplay)    return FALSE;
@@ -1019,11 +1019,11 @@ xf86RandRModeMatches (RRModePtr         randr_mode,
     if (randr_mode->mode.vSyncStart   != mode->VSyncStart)  return FALSE;
     if (randr_mode->mode.vSyncEnd     != mode->VSyncEnd)    return FALSE;
     if (randr_mode->mode.vTotal       != mode->VTotal)     return FALSE;
-    
+
     /* check for same flags (using only the XF86 valid flag bits) */
     if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
        return FALSE;
-    
+
     /* everything matches */
     return TRUE;
 }
@@ -1063,7 +1063,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr  randr_crtc)
            randr_output = output->randr_output;
            randr_outputs[numOutputs++] = randr_output;
            /*
-            * We make copies of modes, so pointer equality 
+            * We make copies of modes, so pointer equality
             * isn't sufficient
             */
            for (j = 0; j < randr_output->numModes + 
randr_output->numUserModes; j++)
@@ -1071,7 +1071,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr  randr_crtc)
                RRModePtr   m = (j < randr_output->numModes ?
                                 randr_output->modes[j] :
                                 
randr_output->userModes[j-randr_output->numModes]);
-                                        
+
                if (xf86RandRModeMatches (m, mode))
                {
                    randr_mode = m;
@@ -1081,7 +1081,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr  randr_crtc)
        }
     }
     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
-                       rotation, 
+                       rotation,
                        crtc->transformPresent ? &crtc->transform : NULL,
                        numOutputs, randr_outputs);
     free(randr_outputs);
@@ -1100,13 +1100,13 @@ xf86RandRModeConvert (ScrnInfoPtr       scrn,
     mode->status = MODE_OK;
 
     mode->Clock = randr_mode->mode.dotClock / 1000;
-    
+
     mode->HDisplay = randr_mode->mode.width;
     mode->HSyncStart = randr_mode->mode.hSyncStart;
     mode->HSyncEnd = randr_mode->mode.hSyncEnd;
     mode->HTotal = randr_mode->mode.hTotal;
     mode->HSkew = randr_mode->mode.hSkew;
-    
+
     mode->VDisplay = randr_mode->mode.height;
     mode->VSyncStart = randr_mode->mode.vSyncStart;
     mode->VSyncEnd = randr_mode->mode.vSyncEnd;
@@ -1146,7 +1146,7 @@ xf86RandR12CrtcSet (ScreenPtr         pScreen,
        flags |= XF86CrtcSetMode;
     else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
        flags |= XF86CrtcSetMode;
-    
+
     if (rotation != crtc->rotation)
        flags |= XF86CrtcSetRotation;
 
@@ -1159,18 +1159,18 @@ xf86RandR12CrtcSet (ScreenPtr       pScreen,
 
     if (x != crtc->x || y != crtc->y)
        flags |= XF86CrtcSetOrigin;
-    for (o = 0; o < config->num_output; o++) 
+    for (o = 0; o < config->num_output; o++)
     {
        xf86OutputPtr  output = config->output[o];
        xf86CrtcPtr    new_crtc;
 
        save_crtcs[o] = output->crtc;
-       
+
        if (output->crtc == crtc)
            new_crtc = NULL;
        else
            new_crtc = output->crtc;
-       for (ro = 0; ro < num_randr_outputs; ro++) 
+       for (ro = 0; ro < num_randr_outputs; ro++)
            if (output->randr_output == randr_outputs[ro])
            {
                new_crtc = crtc;
@@ -1182,7 +1182,7 @@ xf86RandR12CrtcSet (ScreenPtr         pScreen,
            output->crtc = new_crtc;
        }
     }
-    for (ro = 0; ro < num_randr_outputs; ro++) 
+    for (ro = 0; ro < num_randr_outputs; ro++)
         if (randr_outputs[ro]->pendingProperties)
            flags |= XF86CrtcSetProperty;
 
@@ -1385,7 +1385,7 @@ xf86RROutputSetModes (RROutputPtr randr_output, 
DisplayModePtr modes)
 
     if (nmode) {
        rrmodes = malloc(nmode * sizeof (RRModePtr));
-       
+
        if (!rrmodes)
            return FALSE;
        nmode = 0;
@@ -1395,7 +1395,7 @@ xf86RROutputSetModes (RROutputPtr randr_output, 
DisplayModePtr modes)
                if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
                    xRRModeInfo         modeInfo;
                    RRModePtr           rrmode;
-                   
+
                    modeInfo.nameLength = strlen (mode->name);
                    modeInfo.width = mode->HDisplay;
                    modeInfo.dotClock = mode->Clock * 1000;
@@ -1419,7 +1419,7 @@ xf86RROutputSetModes (RROutputPtr randr_output, 
DisplayModePtr modes)
            }
        }
     }
-    
+
     ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
     free(rrmodes);
     return ret;
@@ -1439,13 +1439,13 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
     int                        o, c, l;
     RRCrtcPtr          randr_crtc;
     int                        nclone;
-    
+
     clones = malloc(config->num_output * sizeof (RROutputPtr));
     crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr));
     for (o = 0; o < config->num_output; o++)
     {
        xf86OutputPtr   output = config->output[o];
-       
+
        ncrtc = 0;
        for (c = 0; c < config->num_crtc; c++)
            if (output->possible_crtcs & (1 << c))
@@ -1463,7 +1463,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
            return FALSE;
        }
 
-       RROutputSetPhysicalSize(output->randr_output, 
+       RROutputSetPhysicalSize(output->randr_output,
                                output->mm_width,
                                output->mm_height);
        xf86RROutputSetModes (output->randr_output, output->probed_modes);
@@ -1489,7 +1489,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
        for (l = 0; l < config->num_output; l++)
        {
            xf86OutputPtr           clone = config->output[l];
-           
+
            if (l != o && (output->possible_clones & (1 << l)))
                clones[nclone++] = clone->randr_output;
        }
@@ -1530,7 +1530,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
     int                        c;
     int                        o;
-    
+
     if (!RRInit ())
        return FALSE;
 
@@ -1540,7 +1540,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     for (c = 0; c < config->num_crtc; c++)
     {
        xf86CrtcPtr    crtc = config->crtc[c];
-       
+
        crtc->randr_crtc = RRCrtcCreate (pScreen, crtc);
        RRCrtcGammaSetSize (crtc->randr_crtc, 256);
     }
@@ -1551,7 +1551,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     {
        xf86OutputPtr   output = config->output[o];
 
-       output->randr_output = RROutputCreate (pScreen, output->name, 
+       output->randr_output = RROutputCreate (pScreen, output->name,
                                               strlen (output->name),
                                               output);
 
@@ -1574,7 +1574,7 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 
     for (c = 0; c < config->num_crtc; c++)
         xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
-    
+
     RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
                          config->maxWidth, config->maxHeight);
     return TRUE;
@@ -1747,6 +1747,112 @@ xf86RandR14SetCrtcSpriteTransform(ScreenPtr             
pScreen,
 }
 
 static Bool
+xf86RRConvertCrtcConfig(xf86CrtcSetConfigPtr   xf86_config,
+                       RRCrtcConfigPtr         rr_config)
+{
+    RRCrtcPtr          rr_crtc = rr_config->crtc;
+    xf86CrtcPtr                crtc = rr_crtc->devPrivate;
+    ScrnInfoPtr                scrn = xf86Screens[rr_crtc->pScreen->myNum];
+    int                        o;
+
+    xf86_config->crtc = crtc;
+    xf86_config->x = rr_config->x;
+    xf86_config->y = rr_config->y;
+    xf86RandRModeConvert(scrn, rr_config->mode, &xf86_config->mode);
+    xf86_config->rotation = rr_config->rotation;
+    xf86_config->numOutputs = rr_config->numOutputs;
+    xf86_config->outputs = calloc(rr_config->numOutputs, sizeof 
(xf86OutputPtr));
+    if (!xf86_config->outputs)
+       return FALSE;
+    for (o = 0; o < rr_config->numOutputs; o++)
+       xf86_config->outputs[o] = rr_config->outputs[o]->devPrivate;
+    xf86_config->sprite_position_transform = 
rr_config->sprite_position_transform;
+    xf86_config->sprite_image_transform = rr_config->sprite_image_transform;
+    xf86_config->pixmap = rr_config->pixmap;
+    xf86_config->pixmap_x = rr_config->pixmap_x;
+    xf86_config->pixmap_y = rr_config->pixmap_y;
+    return TRUE;
+}
+
+static void
+xf86FreeCrtcSetConfigs(xf86CrtcSetConfigPtr xf86_crtc_configs, int num_configs)
+{
+    int        i;
+
+    for (i = 0; i < num_configs; i++)
+       free(xf86_crtc_configs[i].outputs);
+    free(xf86_crtc_configs);
+}
+
+static Bool
+xf86RRSetCrtcConfigs(ScreenPtr screen,
+                    RRScreenConfigPtr screen_config,
+                    RRCrtcConfigPtr crtc_configs,
+                    int num_configs)
+{
+    ScrnInfoPtr                        scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr          config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    if (config->funcs->set_config) {
+       xf86CrtcSetConfigPtr    xf86_crtc_configs;
+       int                     i;
+       xf86SetConfigResponse   response;
+
+       /*
+        * Convert RRCrtcConfigRecs to xf86CrtcSetConfigs
+        */
+       xf86_crtc_configs = calloc(num_configs, sizeof (xf86CrtcSetConfigRec));
+       if (!xf86_crtc_configs)
+           return FALSE;
+       for (i = 0; i < num_configs; i++)
+           if (!xf86RRConvertCrtcConfig(&xf86_crtc_configs[i], 
&crtc_configs[i])) {
+               xf86FreeCrtcSetConfigs(xf86_crtc_configs, num_configs);
+               return FALSE;
+           }
+
+       /*
+        * Ask the driver to set the configuration
+        */
+       response = (*config->funcs->set_config)(scrn,
+                                               screen_config,
+                                               xf86_crtc_configs,
+                                               num_configs);
+       xf86FreeCrtcSetConfigs(xf86_crtc_configs, num_configs);
+
+       /*
+        * The driver is allowed to answer with one of three
+        * responses:
+        */
+       switch (response) {
+       case xf86SetConfigFailed:
+
+           /* The configuration isn't usable, or some error
+            * occurred while setting it. Everything has been
+            * cleaned up and we're ready to return an error
+            * back to the client
+            */
+           return FALSE;
+       case xf86SetConfigDone:
+
+           /* The configuration was acceptable, and the whole
+            * mode setting experience is over. Nothing more to do
+            * here.
+            */
+           return TRUE;
+       case xf86SetConfigChecked:
+
+           /* The configuration was acceptable, but the driver
+            * didn't actually do anything. Go ask the DIX code
+            * to do the mode setting operation using the simpler
+            * interfaces
+            */
+           break;
+       }
+    }
+    return miRRSetCrtcConfigs(screen, screen_config, crtc_configs, 
num_configs);
+}
+
+static Bool
 xf86RandR12EnterVT (int screen_index, int flags)
 {
     ScreenPtr        pScreen = screenInfo.screens[screen_index];
@@ -1797,7 +1903,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
     rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
-    rp->rrSetCrtcConfigs = miRRSetCrtcConfigs;
+    rp->rrSetCrtcConfigs = xf86RRSetCrtcConfigs;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
-- 
1.7.2.3

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to