summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-05-11 16:29:56 +0100
committerDave Airlie <airlied@redhat.com>2012-05-11 16:29:56 +0100
commit78040dba52351651f02412b4db9418e7fcf66311 (patch)
tree7177af7240d569c5d478c9b9eb7fd9aae8ef23bc
parent4362804f9cc745078aa916e3c79cab4cd8c01f27 (diff)
WIP RANDR checkpointdrvmodelv3
nouveau can now scanout on intel frontbuffer again
-rw-r--r--drv/imped.h12
-rw-r--r--drv/imped_gc.c12
-rw-r--r--drv/imped_plug.c13
-rw-r--r--drv/imped_scrn.c77
-rw-r--r--hw/xfree86/common/xf86.h5
-rw-r--r--hw/xfree86/common/xf86AutoConfig.c2
-rw-r--r--hw/xfree86/common/xf86DrvHelper.c24
-rw-r--r--hw/xfree86/dri2/dri2.h4
-rw-r--r--hw/xfree86/dri2/imped_dri2.c102
-rw-r--r--hw/xfree86/modes/xf86Crtc.h5
-rw-r--r--hw/xfree86/modes/xf86RandR12.c52
-rw-r--r--hw/xfree86/modes/xf86Rotate.c7
-rw-r--r--include/pixmapstr.h2
-rw-r--r--miext/damage/damage.c10
-rw-r--r--randr/randr.c3
-rw-r--r--randr/randrstr.h7
-rw-r--r--randr/rrcrtc.c182
-rw-r--r--randr/rrinfo.c3
-rw-r--r--randr/rrscreen.c214
19 files changed, 598 insertions, 138 deletions
diff --git a/drv/imped.h b/drv/imped.h
index 1f8873c6f..36ebaeefd 100644
--- a/drv/imped.h
+++ b/drv/imped.h
@@ -1,6 +1,7 @@
#ifndef IMPED_H
#define IMPED_H
+#include "randrstr.h"
#include "picturestr.h"
extern _X_EXPORT Bool impedSetupScreen(ScreenPtr pScreen);
@@ -27,6 +28,8 @@ impedCreateGC(GCPtr pGC);
extern _X_EXPORT void
impedAttachUnboundScreen(ScreenPtr pScreen, ScreenPtr new);
+extern _X_EXPORT void
+impedDetachUnboundScreen(ScreenPtr pScreen, ScreenPtr slave);
extern _X_EXPORT void
impedAttachScreen(ScreenPtr pScreen, ScreenPtr slave);
@@ -44,9 +47,6 @@ extern _X_EXPORT void
impedDetachOffloadSlave(ScreenPtr pScreen, ScreenPtr slave);
extern _X_EXPORT void
-impedDetachAllSlaves(ScreenPtr pScreen);
-
-extern _X_EXPORT void
impedMigrateOutputSlaves(ScreenPtr pOldMaster, ScreenPtr pNewMaster);
extern _X_EXPORT void
@@ -101,4 +101,10 @@ impedAddScreen(ScreenPtr protocol_master, ScreenPtr new);
extern _X_EXPORT Bool
impedRemoveScreen(ScreenPtr protocol_master, ScreenPtr slave);
+
+extern _X_EXPORT Bool
+impedRandR12Init(ScreenPtr pScreen);
+
+Bool impedCheckPixmapBounding(ScreenPtr pScreen,
+ RRCrtcPtr rr_crtc, int x, int y, int w, int h);
#endif
diff --git a/drv/imped_gc.c b/drv/imped_gc.c
index 797dcdd8b..c7f34b874 100644
--- a/drv/imped_gc.c
+++ b/drv/imped_gc.c
@@ -68,12 +68,18 @@ impedValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
miComputeCompositeClip (pGC, pDrawable);
}
+ if (pGC->pCompositeClip)
+ ErrorF("clip %d %d %d %d\n",
+ pGC->pCompositeClip->extents.x1,
+ pGC->pCompositeClip->extents.y1,
+ pGC->pCompositeClip->extents.x2,
+ pGC->pCompositeClip->extents.y2);
/* have to translate the composite clip before syncing it */
#ifdef COMPOSITE
if (pDrawable->type == DRAWABLE_WINDOW) {
- x_off = -pPixmap->screen_x;
- y_off = -pPixmap->screen_y;
- RegionTranslate(pGC->pCompositeClip, x_off, y_off);
+ x_off = -pPixmap->screen_x;
+ y_off = -pPixmap->screen_y;
+ RegionTranslate(pGC->pCompositeClip, x_off, y_off);
}
#endif
for (i = 0; i < pGC->pScreen->num_gpu; i++) {
diff --git a/drv/imped_plug.c b/drv/imped_plug.c
index 938b3d91b..c44360952 100644
--- a/drv/imped_plug.c
+++ b/drv/imped_plug.c
@@ -94,6 +94,15 @@ impedAddScreen(ScreenPtr protocol_master, ScreenPtr new)
}
}
+ /* set the screen pixmap up correctly */
+ {
+ PixmapPtr pPixmap;
+
+ pPixmap = protocol_master->GetScreenPixmap(protocol_master);
+
+ protocol_master->gpu[new_gpu_index]->SetScreenPixmap(pPixmap->gpu[new_gpu_index]);
+ }
+
return 0;
}
@@ -119,6 +128,7 @@ impedRemoveScreen(ScreenPtr protocol_master, ScreenPtr slave)
PicturePtr pPicture;
xorg_list_for_each_entry(pPicture, &protocol_master->picture_list, member) {
PicturePtr tofree = pPicture->gpu[remove_index];
+ pPicture->gpu[remove_index] = NULL;
for (i = remove_index ; i < protocol_master->num_gpu - 1; i++)
pPicture->gpu[i] = pPicture->gpu[i + 1];
FreePicture(tofree, (XID)0);
@@ -129,6 +139,7 @@ impedRemoveScreen(ScreenPtr protocol_master, ScreenPtr slave)
xorg_list_for_each_entry(pGC, &protocol_master->gc_list, member) {
GCPtr tofree = pGC->gpu[remove_index];
pGC->serialNumber = NEXT_SERIAL_NUMBER;
+ pGC->gpu[remove_index] = NULL;
for (i = remove_index ; i < protocol_master->num_gpu - 1; i++)
pGC->gpu[i] = pGC->gpu[i + 1];
FreeGC(tofree, 0);
@@ -139,12 +150,14 @@ impedRemoveScreen(ScreenPtr protocol_master, ScreenPtr slave)
PixmapPtr pPixmap;
xorg_list_for_each_entry(pPixmap, &protocol_master->pixmap_list, member) {
PixmapPtr tofree = pPixmap->gpu[remove_index];
+ pPixmap->gpu[remove_index] = NULL;
for (i = remove_index ; i < protocol_master->num_gpu - 1; i++)
pPixmap->gpu[i] = pPixmap->gpu[i + 1];
(*slave->DestroyPixmap)(tofree);
}
}
+ xorg_list_del(&slave->gpu_screen_head);
protocol_master->gpu[remove_index] = NULL;
for (i = remove_index; i < protocol_master->num_gpu - 1; i++)
protocol_master->gpu[i] = protocol_master->gpu[i + 1];
diff --git a/drv/imped_scrn.c b/drv/imped_scrn.c
index 1fe16be25..83082ace3 100644
--- a/drv/imped_scrn.c
+++ b/drv/imped_scrn.c
@@ -274,7 +274,7 @@ impedDestroyPixmap(PixmapPtr pPixmap)
ScreenPtr pScreen = pPixmap->drawable.pScreen;
if (--pPixmap->refcnt)
return TRUE;
-
+
xorg_list_del(&pPixmap->member);
for (i = 0; i < pScreen->num_gpu; i++) {
pScreen->gpu[i]->DestroyPixmap(pPixmap->gpu[i]);
@@ -293,6 +293,20 @@ static void
impedBlockHandler(ScreenPtr pScreen, pointer blockData, pointer pTimeout,
pointer pReadmask)
{
+ int i;
+ ScreenPtr master, slave;
+
+ for (i = 0; i < pScreen->num_gpu; i++) {
+ master = pScreen->gpu[i];
+
+ master->BlockHandler(master, blockData, pTimeout, pReadmask);
+ xorg_list_for_each_entry(slave, &master->offload_slave_list, offload_head) {
+ slave->BlockHandler(slave, blockData, pTimeout, pReadmask);
+ }
+ xorg_list_for_each_entry(slave, &master->output_slave_list, output_head) {
+ slave->BlockHandler(slave, blockData, pTimeout, pReadmask);
+ }
+ }
}
PixmapPtr
@@ -404,6 +418,14 @@ impedAttachUnboundScreen(ScreenPtr pScreen, ScreenPtr new)
assert(!pScreen->isGPU);
assert(new->isGPU);
xorg_list_add(&new->unattached_head, &pScreen->unattached_list);
+ new->protocol_master = pScreen;
+}
+
+void
+impedDetachUnboundScreen(ScreenPtr pScreen, ScreenPtr slave)
+{
+ xorg_list_del(&slave->unattached_head);
+ slave->protocol_master = NULL;
}
/* attach a gpu screen to a protocol screen */
@@ -461,24 +483,6 @@ impedDetachOffloadSlave(ScreenPtr master, ScreenPtr slave)
}
void
-impedDetachAllSlaves(ScreenPtr pScreen)
-{
- ScreenPtr iter, safe;
-
- assert(pScreen->isGPU);
-
- xorg_list_for_each_entry_safe(iter, safe, &pScreen->offload_slave_list, offload_head) {
- impedDetachOffloadSlave(pScreen, iter);
- }
-
-
- xorg_list_for_each_entry_safe(iter, safe, &pScreen->output_slave_list, output_head) {
- impedDetachOutputSlave(pScreen, iter);
- }
-
-}
-
-void
impedMigrateOutputSlaves(ScreenPtr pOldMaster, ScreenPtr pNewMaster)
{
ScreenPtr iter, safe;
@@ -494,3 +498,38 @@ impedMigrateOutputSlaves(ScreenPtr pOldMaster, ScreenPtr pNewMaster)
xorg_list_add(&iter->output_head, &pNewMaster->output_slave_list);
}
}
+
+static Bool
+impedScreenSetSize(ScreenPtr pScreen,
+ CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
+ PixmapPtr pScrnPix;
+
+ SetRootClip(pScreen, FALSE);
+
+ pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
+ pScreen->width = pScrnPix->drawable.width = width;
+ pScreen->height = pScrnPix->drawable.width = height;
+
+ update_desktop_dimensions();
+
+ SetRootClip(pScreen, TRUE);
+
+ if (pScreen->root)
+ RRScreenSizeNotify(pScreen);
+ return TRUE;
+}
+
+Bool
+impedRandR12Init(ScreenPtr pScreen)
+{
+ rrScrPrivPtr rp;
+ if (!RRScreenInit(pScreen))
+ return FALSE;
+
+ rp = rrGetScrPriv(pScreen);
+ rp->rrScreenSetSize = impedScreenSetSize;
+
+ return TRUE;
+}
diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index f326b95ec..6b51ce8bb 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -454,7 +454,12 @@ VidModeExtensionInit(ScreenPtr pScreen);
extern _X_EXPORT ScrnInfoPtr xf86ScreenToScrn(ScreenPtr pScreen);
/* convert ScrnInfoPtr to ScreenPtr */
extern _X_EXPORT ScreenPtr xf86ScrnToScreen(ScrnInfoPtr pScrn);
+extern _X_EXPORT Bool (*drv_dri2_hook)(ScreenPtr);
#endif /* _NO_XF86_PROTOTYPES */
+#define XF86_HAS_SCRN_CONV 1
+
+#define XF86_SCRN_INTERFACE 1
+
#endif /* _XF86_H */
diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index 7d75b1c09..4977e27d5 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/hw/xfree86/common/xf86AutoConfig.c
@@ -278,7 +278,7 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
#if !defined(__linux__) && defined(__sparc__)
matches[i++] = xnfstrdup("wsfb");
#else
- matches[i++] = xnfstrdup("fbdev");
+ matches[i++] = xnfstrdup("modesetting");
#endif
}
#endif /* !sun */
diff --git a/hw/xfree86/common/xf86DrvHelper.c b/hw/xfree86/common/xf86DrvHelper.c
index 189f65ba8..1aa44e6e1 100644
--- a/hw/xfree86/common/xf86DrvHelper.c
+++ b/hw/xfree86/common/xf86DrvHelper.c
@@ -14,6 +14,9 @@
#include "micmap.h"
#include "imped.h"
#include "xf86Priv.h"
+#include "xf86Crtc.h"
+
+Bool (*drv_dri2_hook)(ScreenPtr);
static void xf86FixupRGBOrdering(ScrnInfoPtr scrn, ScreenPtr screen)
{
@@ -44,7 +47,7 @@ impedHelperScreenInit(ScreenPtr pScreen,
int i;
Bool allow_slave = FALSE;
ScrnInfoPtr master = NULL;
-
+
if (!impedSetupScreen(pScreen))
return FALSE;
@@ -63,8 +66,8 @@ retry:
if (xf86GPUScreens[i]->numEntities != 1)
continue;
- if (!xf86IsEntityPrimary(xf86GPUScreens[i]->entityList[0]))
- continue;
+ if (!xf86IsEntityPrimary(xf86GPUScreens[i]->entityList[0]))
+ continue;
master = xf86GPUScreens[i];
@@ -126,15 +129,20 @@ retry:
return FALSE;
}
+ /* do dri2 init */
+ if (xf86LoaderCheckSymbol("DRI2Connect") && drv_dri2_hook)
+ drv_dri2_hook(pScreen);
+
pScreen->SaveScreen = impedSaveScreen;
xf86DisableRandR(); /* disable old randr extension */
- // impedRandR12Init(pScreen);
+
+ /* need to create a dumb randr 12 to handle protocol stuff */
+ impedRandR12Init(pScreen);
return TRUE;
}
-static Bool impedPointerMoved(ScrnInfoPtr pScrn, int x, int y)
+static void impedPointerMoved(ScrnInfoPtr pScrn, int x, int y)
{
- return TRUE;
}
static void
@@ -143,10 +151,10 @@ impedLeaveVT(ScrnInfoPtr pScrn, int flags)
}
-static void
+static Bool
impedEnterVT(ScrnInfoPtr pScrn, int flags)
{
-
+ return TRUE;
}
void xf86HelperAddProtoScreens(int screennum)
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index ca8490e4d..edc920003 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -222,10 +222,10 @@ typedef PixmapPtr (*DRI2CreateBufferPixmapProcPtr)(ScreenPtr pScreen,
typedef void (*DRI2DestroyBufferPixmapProcPtr)(PixmapPtr pPixmap);
typedef void (*DRI2CopyPixmapPtrCB)(PixmapPtr src, PixmapPtr dst,
- RegionPtr pRegion, RegionPtr front_clip);
+ RegionPtr pRegion, int x, int y);
typedef void (*DRI2CopyRegionPixmapProcPtr)(PixmapPtr src, PixmapPtr dst,
- RegionPtr pRegion, RegionPtr f_c,
+ RegionPtr pRegion, int x, int y,
DRI2CopyPixmapPtrCB cb);
typedef int (*DRI2ScheduleSwapPixmapProcPtr) (PixmapPtr pDraw,
diff --git a/hw/xfree86/dri2/imped_dri2.c b/hw/xfree86/dri2/imped_dri2.c
index fc09e4df4..3d8d8fc81 100644
--- a/hw/xfree86/dri2/imped_dri2.c
+++ b/hw/xfree86/dri2/imped_dri2.c
@@ -10,9 +10,12 @@
#include "list.h"
#include "windowstr.h"
+#include "imped.h"
#include "dri2.h"
#include "dri2_priv.h"
+#include "gcstruct.h"
+#include "damagestr.h"
typedef struct {
int refcnt;
PixmapPtr pixmap;
@@ -35,15 +38,14 @@ GetScreenPrime(ScreenPtr master, int prime_id)
return master->gpu[master->primary_gpu_index];
}
i = 0;
- xorg_list_for_each_entry(slave, &master->offload_slave_list, offload_head) {
+ xorg_list_for_each_entry(slave, &master->gpu[master->primary_gpu_index]->offload_slave_list, offload_head) {
if (i == (prime_id - 1))
break;
i++;
}
if (!slave)
return master->gpu[master->primary_gpu_index];
- /* TODO */
- return master->gpu[master->primary_gpu_index];
+ return slave;
}
@@ -198,9 +200,41 @@ static void imped_dri2_destroy_buffer(DrawablePtr pDraw,
imped_dri2_unref_buffer(NULL, buffer);
}
+static Bool
+update_prime_state(DRI2BufferPtr buffer, RegionPtr region,
+ PixmapPtr mpix)
+{
+ impedDRI2BufferPrivatePtr private;
+ ScreenPtr master, slave;
+ int fd_handle, ret;
+ PixmapPtr spix;
+ private = buffer->driverPrivate;
+
+ master = mpix->drawable.pScreen;
+ ret = master->SharePixmapBacking(mpix, &fd_handle);
+
+ slave = GetScreenPrime(mpix->drawable.pScreen->protocol_master, private->prime_id);
+
+ spix = slave->CreatePixmap(slave, 0, 0, (buffer->format != 0) ? buffer->format : mpix->drawable.depth, CREATE_PIXMAP_USAGE_SHARED);
+
+ slave->ModifyPixmapHeader(spix, mpix->drawable.width, mpix->drawable.height,
+ (buffer->format != 0) ? buffer->format : mpix->drawable.depth,
+ 0, mpix->devKind, NULL);
+
+ ret = slave->SetSharedPixmapBacking(spix, fd_handle);
+ if (ret == FALSE) {
+ ErrorF("failed to slave pixmap\n");
+ return FALSE;
+ }
+
+ private->pixmap = spix;
+ /* share pixmap + import pixmap */
+ return TRUE;
+}
+
static void
imped_dri2_copy_region_callback(PixmapPtr src, PixmapPtr dst,
- RegionPtr pRegion, RegionPtr front_clip)
+ RegionPtr pRegion, int x, int y)
{
miCopyProc copy;
int nbox;
@@ -216,26 +250,41 @@ imped_dri2_copy_region_callback(PixmapPtr src, PixmapPtr dst,
ValidateGC(&dst->drawable, gc);
nbox = RegionNumRects(pRegion);
pbox = RegionRects(pRegion);
- copy(&src->drawable, &dst->drawable, gc, pbox, nbox, 0, 0, 0, 0, 0, NULL);
+ copy(&src->drawable, &dst->drawable, gc, pbox, nbox, -x, -y, 0, 0, 0, NULL);
FreeScratchGC(gc);
}
static void
imped_copy_region(PixmapPtr pixmap, RegionPtr pRegion,
- DRI2BufferPtr dst_buffer, DRI2BufferPtr src_buffer)
+ DRI2BufferPtr dst_buffer, DRI2BufferPtr src_buffer, int x, int y)
{
impedDRI2BufferPrivatePtr src_private = src_buffer->driverPrivate;
impedDRI2BufferPrivatePtr dst_private = dst_buffer->driverPrivate;
PixmapPtr src, dst;
-
+ int ret;
ScreenPtr pScreen = pixmap->drawable.pScreen;
DRI2ScreenPtr gpu_ds = DRI2GetScreen(pScreen);
src = src_private->pixmap;
dst = dst_private->pixmap;
- gpu_ds->CopyRegionPixmap(src, dst, pRegion, NULL, imped_dri2_copy_region_callback);
+ if (src_private->attachment == DRI2BufferFrontLeft) {
+ if (!src || src->drawable.pScreen != pixmap->drawable.pScreen) {
+ ErrorF("copying prime in reverse %p\n", src);
+ return;
+ }
+ } else if (dst_private->attachment == DRI2BufferFrontLeft) {
+ if (!dst || dst->drawable.pScreen != pixmap->drawable.pScreen) {
+ ret = update_prime_state(dst_buffer, NULL, pixmap);
+ if (ret == FALSE)
+ return;
+ dst = dst_private->pixmap;
+ }
+ gpu_ds = DRI2GetScreen(dst->drawable.pScreen);
+ }
+
+ gpu_ds->CopyRegionPixmap(src, dst, pRegion, x, y, imped_dri2_copy_region_callback);
}
static void imped_dri2_copy_region(DrawablePtr pDraw,
@@ -247,15 +296,48 @@ static void imped_dri2_copy_region(DrawablePtr pDraw,
PixmapPtr pPixmap = GetDrawablePixmap(pDraw);
PixmapPtr src;
PixmapPtr dst;
+ GCPtr gc;
+ RegionPtr pCopyClip;
+ int x, y;
+ int scr_x, scr_y;
+
+ impedGetDrawableDeltas(pDraw, pPixmap, &x, &y);
+ impedGetCompositeDeltas(pDraw, pPixmap, &scr_x, &scr_y);
+ gc = GetScratchGC(pDraw->depth, pDraw->pScreen);
+ pCopyClip = RegionCreate(NULL, 0);
+ RegionCopy(pCopyClip, pRegion);
+ (*gc->funcs->ChangeClip)(gc, CT_REGION, pCopyClip, 0);
+ ValidateGC(pDraw, gc);
+
+ ErrorF("draw copy region %d %dx%d vs p %dx%d @ %dx%d, scr %dx%d\n", pDraw->type, pDraw->width, pDraw->height, pPixmap->drawable.width, pPixmap->drawable.height, x, y, scr_x, scr_y);
- ErrorF("draw copy region %d %dx%d vs p %dx%d\n", pDraw->type, pDraw->width, pDraw->height, pPixmap->drawable.width, pPixmap->drawable.height);
+ // RegionTranslate(gc->pCompositeClip, -scr_x, -scr_y);
- imped_copy_region(pPixmap->gpu[pDraw->pScreen->primary_gpu_index], pRegion, pDestBuffer, pSrcBuffer);
+ {
+ int nbox = RegionNumRects(gc->pCompositeClip);
+ BoxPtr pbox = RegionRects(gc->pCompositeClip);
+ int ind;
+
+ for (ind = 0; ind < nbox; ind++) {
+ ErrorF("%d: %d %d %d %d\n", ind, pbox[ind].x1, pbox[ind].y1,
+ pbox[ind].x2, pbox[ind].y2);
+ /* debugging */
+ }
+ }
+
+ DamageRegionAppend(pDraw, gc->pCompositeClip);
+
+ RegionTranslate(gc->pCompositeClip, -scr_x, -scr_y);
+ imped_copy_region(pPixmap->gpu[pDraw->pScreen->primary_gpu_index], gc->pCompositeClip, pDestBuffer, pSrcBuffer, x, y);
+
+ RegionTranslate(gc->pCompositeClip, scr_x, scr_y);
if (pDraw->type == DRAWABLE_WINDOW) {
/* translate */
}
+ DamageRegionProcessPending(pDraw);
+ FreeScratchGC(gc);
}
static int imped_dri2_schedule_swap(ClientPtr client,
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index acc579145..3d53f38e4 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -219,6 +219,11 @@ typedef struct _xf86CrtcFuncs {
void
(*set_origin) (xf86CrtcPtr crtc, int x, int y);
+ /**
+ */
+ Bool
+ (*set_slave_pixmap)(xf86CrtcPtr crtc, PixmapPtr pixmap);
+
} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
#define XF86_CRTC_VERSION 4
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 7ab000b97..e62faab4b 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1758,12 +1758,32 @@ xf86RandR12EnterVT(ScrnInfoPtr pScrn, int flags)
return RRGetInfo(pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */
}
+static void
+detach_all_slaves(ScreenPtr pScreen)
+{
+ ScreenPtr iter, safe;
+
+ assert(pScreen->isGPU);
+
+ xorg_list_for_each_entry_safe(iter, safe, &pScreen->offload_slave_list, offload_head) {
+ impedDetachOffloadSlave(pScreen, iter);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), 0);
+ }
+
+ xorg_list_for_each_entry_safe(iter, safe, &pScreen->output_slave_list, output_head) {
+ impedDetachOutputSlave(pScreen, iter);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), 0);
+ }
+
+}
+
static Bool
xf86RandR12ProviderSetRole(ScreenPtr pScreen,
RRProviderPtr provider,
uint32_t new_role)
{
ScreenPtr protocol_master;
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
if (!pScreen->isGPU)
return FALSE;
@@ -1777,7 +1797,7 @@ xf86RandR12ProviderSetRole(ScreenPtr pScreen,
pNewMaster = pScreen;
impedMigrateOutputSlaves(pOldMaster, pNewMaster);
- impedDetachAllSlaves(pOldMaster);
+ detach_all_slaves(pOldMaster);
impedAddScreen(protocol_master, pNewMaster);
impedRemoveScreen(protocol_master, pOldMaster);
@@ -1787,31 +1807,51 @@ xf86RandR12ProviderSetRole(ScreenPtr pScreen,
if (pOldMaster->roles & RR_Role_Slave_Output) {
impedAttachOutputSlave(pNewMaster, pOldMaster, 0);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), RR_Role_Slave_Output);
}
- if (pOldMaster->roles & RR_Role_Slave_Offload)
+ if (pOldMaster->roles & RR_Role_Slave_Offload) {
impedAttachOffloadSlave(pNewMaster, pOldMaster, 0);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), RR_Role_Slave_Offload);
+ }
}
if (new_role == RR_Role_Slave_Output) {
+ if (provider->current_role == 0)
+ impedDetachUnboundScreen(protocol_master, pScreen);
impedAttachOutputSlave(protocol_master->gpu[0],
pScreen, 0);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), RR_Role_Slave_Output);
}
if (!new_role) {
- if (provider->current_role == RR_Role_Slave_Output)
+ if (provider->current_role == RR_Role_Slave_Output) {
impedDetachOutputSlave(protocol_master->gpu[0], pScreen);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), 0);
+ }
- if (provider->current_role == RR_Role_Slave_Offload)
+ if (provider->current_role == RR_Role_Slave_Offload) {
impedDetachOffloadSlave(protocol_master->gpu[0], pScreen);
+ xf86SetCurrentRole(xf86ScreenToScrn(pScreen), 0);
+ }
+ impedAttachUnboundScreen(protocol_master, pScreen);
}
- // RRTellChanged(protocol_master);
+ RRTellChanged(protocol_master);
SetRootClip(protocol_master, TRUE);
return TRUE;
}
static Bool
+xf86CrtcSetSlavePixmap(RRCrtcPtr randr_crtc, PixmapPtr pixmap)
+{
+ xf86CrtcPtr crtc = randr_crtc->devPrivate;
+ if (!crtc->funcs->set_slave_pixmap)
+ return FALSE;
+ return crtc->funcs->set_slave_pixmap(crtc, pixmap);
+}
+
+static Bool
xf86RandR12Init12(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
@@ -1835,6 +1875,7 @@ xf86RandR12Init12(ScreenPtr pScreen)
rp->rrSetConfig = NULL;
rp->rrProviderSetRole = xf86RandR12ProviderSetRole;
+ rp->rrCrtcSlavePixmap = xf86CrtcSetSlavePixmap;
pScrn->PointerMoved = xf86RandR12PointerMoved;
pScrn->ChangeGamma = xf86RandR12ChangeGamma;
@@ -1862,3 +1903,4 @@ xf86RandR12PreInit(ScrnInfoPtr pScrn)
{
return TRUE;
}
+
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 1f09ce563..d295c27c7 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -339,9 +339,12 @@ xf86CrtcFitsScreen(xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
/* When called before PreInit, the driver is
* presumably doing load detect
*/
- if (pScrn->virtualX == 0 || pScrn->virtualY == 0)
+ if (pScrn->is_gpu) {
return TRUE;
-
+ }
+ else if (pScrn->virtualX == 0 || pScrn->virtualY == 0)
+ return TRUE;
+
b.x1 = 0;
b.y1 = 0;
b.x2 = crtc->mode.HDisplay;
diff --git a/include/pixmapstr.h b/include/pixmapstr.h
index 2b2cd0914..a1a49c12f 100644
--- a/include/pixmapstr.h
+++ b/include/pixmapstr.h
@@ -84,6 +84,8 @@ typedef struct _Pixmap {
struct xorg_list member;
PixmapPtr gpu[MAXGPU];
Bool shattered;
+
+ PixmapPtr master_pixmap;
} PixmapRec;
static inline void
diff --git a/miext/damage/damage.c b/miext/damage/damage.c
index 85b54fc56..d12acf0ec 100644
--- a/miext/damage/damage.c
+++ b/miext/damage/damage.c
@@ -58,7 +58,7 @@
(a)->y2 == (b)->y2)
#define DAMAGE_VALIDATE_ENABLE 0
-#define DAMAGE_DEBUG_ENABLE 0
+#define DAMAGE_DEBUG_ENABLE 1
#if DAMAGE_DEBUG_ENABLE
#define DAMAGE_DEBUG(x) ErrorF x
#else
@@ -263,9 +263,16 @@ damageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
*/
pDamageRegion = pRegion;
+ DAMAGE_DEBUG(("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
+ where,
+ pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
+ pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
+ pDamageRegion->extents.x1, pDamageRegion->extents.y1,
+ pDrawable->id, pDamage->pDrawable->id));
if (clip || pDamage->pDrawable != pDrawable) {
pDamageRegion = &clippedRec;
if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
+ ErrorF("clipping against border clip\n");
RegionIntersect(pDamageRegion, pRegion,
&((WindowPtr) (pDamage->pDrawable))->
borderClip);
@@ -280,6 +287,7 @@ damageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
RegionInit(&pixClip, &box, 1);
RegionIntersect(pDamageRegion, pRegion, &pixClip);
RegionUninit(&pixClip);
+ ErrorF("clipping against pixmap clip\n");
}
/*
* Short circuit empty results
diff --git a/randr/randr.c b/randr/randr.c
index b43a58788..46258e6a2 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -93,7 +93,8 @@ RRCloseScreen(ScreenPtr pScreen)
RRCrtcDestroy(pScrPriv->crtcs[j]);
for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
RROutputDestroy(pScrPriv->outputs[j]);
- RRProviderDestroy(pScrPriv->provider);
+ if (pScrPriv->provider)
+ RRProviderDestroy(pScrPriv->provider);
free(pScrPriv->crtcs);
free(pScrPriv->outputs);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index b224c94b0..356fa1da3 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -127,6 +127,8 @@ struct _rrCrtc {
PictTransform transform;
struct pict_f_transform f_transform;
struct pict_f_transform f_inverse;
+
+ PixmapPtr slave_pixmap; /* may need to go in xf86 */
};
struct _rrOutput {
@@ -238,6 +240,8 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
#endif
+typedef Bool (*RRCrtcSetSlavePixmapProcPtr)(RRCrtcPtr crtc, PixmapPtr pixmap);
+
typedef struct _rrScrPriv {
/*
* 'public' part of the structure; DDXen fill this in
@@ -261,6 +265,9 @@ typedef struct _rrScrPriv {
RRGetPanningProcPtr rrGetPanning;
RRSetPanningProcPtr rrSetPanning;
#endif
+ /* TODO #if RANDR_15_INTERFACE */
+ RRCrtcSetSlavePixmapProcPtr rrCrtcSlavePixmap;
+
RRProviderSetRoleProcPtr rrProviderSetRole;
/*
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 36caa5822..b5af260f8 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -24,7 +24,7 @@
#include "randrstr.h"
#include "swaprep.h"
#include "mipointer.h"
-
+#include "imped.h"
RESTYPE RRCrtcType;
/*
@@ -367,6 +367,161 @@ RRComputeContiguity(ScreenPtr pScreen)
pScrPriv->discontiguous = discontiguous;
}
+
+static Bool
+impedCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
+ int x, int y)
+{
+ PixmapPtr mpix, spix;
+ ScreenPtr master = crtc->pScreen->output_master;
+ int fd_handle = -1;
+ Bool ret;
+ int depth;
+ PixmapPtr mscreenpix;
+ PixmapPtr protopix = crtc->pScreen->protocol_master->GetScreenPixmap(crtc->pScreen->protocol_master);
+ rrScrPriv(crtc->pScreen);
+
+ /* create a pixmap on the master screen,
+ then get a shared handle for it
+ create a shared pixmap on the slave screen using the handle
+
+ set the master screen to do dirty updates to the shared pixmap
+ from the screen pixmap.
+ set slave screen to scanout shared linear pixmap
+ */
+
+ mscreenpix = master->GetScreenPixmap(master);
+ depth = protopix->drawable.depth;
+
+ if (width == 0 && height == 0) {
+ ret = pScrPriv->rrCrtcSlavePixmap(crtc, NULL);
+ if (crtc->slave_pixmap) {
+ master->StopPixmapTracking(mscreenpix, crtc->slave_pixmap->master_pixmap);
+ master->DestroyPixmap(crtc->slave_pixmap->master_pixmap);
+ crtc->pScreen->DestroyPixmap(crtc->slave_pixmap);
+ }
+ crtc->slave_pixmap = NULL;
+ return TRUE;
+ }
+
+ if (crtc->slave_pixmap)
+ master->StopPixmapTracking(mscreenpix, crtc->slave_pixmap->master_pixmap);
+
+ mpix = master->CreatePixmap(master, width, height, depth,
+ CREATE_PIXMAP_USAGE_SHARED);
+ if (!mpix)
+ return FALSE;
+
+ ret = master->SharePixmapBacking(mpix, &fd_handle);
+ if (ret == FALSE) {
+ master->DestroyPixmap(mpix);
+ return FALSE;
+ }
+
+ spix = crtc->pScreen->CreatePixmap(crtc->pScreen, 0, 0, depth,
+ CREATE_PIXMAP_USAGE_SHARED);
+ crtc->pScreen->ModifyPixmapHeader(spix, width, height, depth, 0,
+ mpix->devKind, NULL);
+
+ ret = crtc->pScreen->SetSharedPixmapBacking(spix, fd_handle);
+ if (ret == FALSE) {
+ ErrorF("failed to slave pixmap\n");
+ crtc->pScreen->DestroyPixmap(spix);
+ master->DestroyPixmap(mpix);
+ return FALSE;
+ }
+
+ spix->master_pixmap = mpix;
+ ret = pScrPriv->rrCrtcSlavePixmap(crtc, spix);
+ if (ret == FALSE) {
+ ErrorF("failed to set shadow slave pixmap\n");
+ return FALSE;
+ }
+
+ crtc->slave_pixmap = spix;
+
+ master->StartPixmapTracking(mpix, mscreenpix, spix, x, y);
+ return TRUE;
+}
+
+Bool
+impedCheckPixmapBounding(ScreenPtr pScreen,
+ RRCrtcPtr rr_crtc, int x, int y, int w, int h)
+{
+ RegionRec root_pixmap_region, total_region, new_crtc_region;
+ int i, c;
+ BoxRec newbox;
+ BoxPtr newsize;
+ ScreenPtr slave;
+ int new_width, new_height;
+ PixmapPtr screen_pixmap = pScreen->GetScreenPixmap(pScreen);
+ PixmapRegionInit(&root_pixmap_region, screen_pixmap);
+ RegionInit(&total_region, NULL, 0);
+
+ /* have to iterate all the crtcs of the attached gpu masters
+ and all their output slaves */
+ if (pScreen->num_gpu > 1)
+ ErrorF("TODO shatter\n");
+
+ for (i = 0; i < pScreen->num_gpu; i++) {
+ rrScrPriv(pScreen->gpu[i]);
+ for (c = 0; c < pScrPriv->numCrtcs; c++) {
+ if (pScrPriv->crtcs[c] == rr_crtc) {
+ newbox.x1 = x;
+ newbox.x2 = x + w;
+ newbox.y1 = y;
+ newbox.y2 = y + h;
+ } else {
+ if (!pScrPriv->crtcs[c]->mode)
+ continue;
+ newbox.x1 = pScrPriv->crtcs[c]->x;
+ newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
+ newbox.y1 = pScrPriv->crtcs[c]->y;
+ newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
+ }
+ RegionInit(&new_crtc_region, &newbox, 1);
+ RegionUnion(&total_region, &total_region, &new_crtc_region);
+ }
+
+ xorg_list_for_each_entry(slave, &pScreen->gpu[i]->output_slave_list, output_head) {
+ rrScrPriv(slave);
+ for (c = 0; c < pScrPriv->numCrtcs; c++)
+ if (pScrPriv->crtcs[c] == rr_crtc) {
+ newbox.x1 = x;
+ newbox.x2 = x + w;
+ newbox.y1 = y;
+ newbox.y2 = y + h;
+ }
+ else {
+ if (!pScrPriv->crtcs[c]->mode)
+ continue;
+ newbox.x1 = pScrPriv->crtcs[c]->x;
+ newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
+ newbox.y1 = pScrPriv->crtcs[c]->y;
+ newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
+ }
+ RegionInit(&new_crtc_region, &newbox, 1);
+ RegionUnion(&total_region, &total_region, &new_crtc_region);
+ }
+ }
+ newsize = RegionExtents(&total_region);
+ new_width = newsize->x2 - newsize->x1;
+ new_height = newsize->y2 - newsize->y1;
+
+ if (new_width == screen_pixmap->drawable.width &&
+ new_height == screen_pixmap->drawable.height) {
+ ErrorF("adjust shatters %d %d\n", newsize->x1, newsize->x2);
+ } else {
+ int ret;
+ rrScrPriv(pScreen->gpu[0]);
+ ret = pScrPriv->rrScreenSetSize(pScreen->gpu[0],
+ new_width, new_height, 0, 0);
+ }
+
+ /* set shatters TODO */
+ return TRUE;
+}
+
/*
* Request that the Crtc be reconfigured
*/
@@ -394,6 +549,27 @@ RRCrtcSet(RRCrtcPtr crtc,
ret = TRUE;
}
else {
+ if (pScreen->isGPU) {
+ ScreenPtr protocol_screen = pScreen->protocol_master;
+ int width = 0, height = 0;
+
+ if (mode) {
+ width = mode->mode.width;
+ height = mode->mode.height;
+ }
+ ErrorF("have a master to look out for\n");
+ ret = impedCheckPixmapBounding(protocol_screen, crtc,
+ x, y, width, height);
+ if (!ret)
+ return FALSE;
+
+ if (pScreen->output_master) {
+ ret = impedCreateSharedPixmap(crtc, width, height, x, y);
+ ErrorF("need to create shared pixmap %d", ret);
+
+ }
+
+ }
#if RANDR_12_INTERFACE
if (pScrPriv->rrCrtcSet) {
ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
@@ -965,6 +1141,9 @@ ProcRRSetCrtcConfig(ClientPtr client)
RRModeGetScanoutSize(mode, &transform, &source_width,
&source_height);
+#if 0 /*TODO*/
+ ErrorF("%d %d %d\n", stuff->x, source_width, pScreen->width);
+ ErrorF("%d %d %d\n", stuff->y, source_height, pScreen->height);
if (stuff->x + source_width > pScreen->width) {
client->errorValue = stuff->x;
free(outputs);
@@ -976,6 +1155,7 @@ ProcRRSetCrtcConfig(ClientPtr client)
free(outputs);
return BadValue;
}
+#endif
}
#endif
}
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 114ec3471..31a83c424 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -192,6 +192,9 @@ RRGetInfo(ScreenPtr pScreen, Bool force_query)
pScrPriv->changed = FALSE;
pScrPriv->configChanged = FALSE;
+ if (!pScrPriv->rrGetInfo)
+ return TRUE;
+
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 92ea78fc9..e521abb02 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -73,6 +73,9 @@ RRSendConfigNotify(ScreenPtr pScreen)
WindowPtr pWin = pScreen->root;
xEvent event;
+ if (!pWin)
+ return;
+
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
@@ -208,7 +211,16 @@ ProcRRGetScreenSizeRange(ClientPtr client)
rep.sequenceNumber = client->sequence;
rep.length = 0;
- if (pScrPriv) {
+ if (pScreen->num_gpu) {
+ rrScrPrivPtr gpupriv = rrGetScrPriv(pScreen->gpu[0]);
+ if (!RRGetInfo(pScreen->gpu[0], FALSE))
+ return BadAlloc;
+ rep.minWidth = gpupriv->minWidth;
+ rep.minHeight = gpupriv->minHeight;
+ rep.maxWidth = gpupriv->maxWidth;
+ rep.maxHeight = gpupriv->maxHeight;
+
+ } else if (pScrPriv) {
if (!RRGetInfo(pScreen, FALSE))
return BadAlloc;
rep.minWidth = pScrPriv->minWidth;
@@ -232,29 +244,18 @@ ProcRRGetScreenSizeRange(ClientPtr client)
return Success;
}
-int
-ProcRRSetScreenSize(ClientPtr client)
+static int rr_check_single_size(ClientPtr client,
+ rrScrPrivPtr pScrPriv, int width, int height)
{
- REQUEST(xRRSetScreenSizeReq);
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- int i, rc;
-
- REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) {
- client->errorValue = stuff->width;
+ int i;
+ if (width < pScrPriv->minWidth || pScrPriv->maxWidth < width) {
+ ErrorF("pScrPriv w/h %d %d\n", pScrPriv->minWidth, pScrPriv->maxWidth);
+ client->errorValue = width;
return BadValue;
}
- if (stuff->height < pScrPriv->minHeight ||
- pScrPriv->maxHeight < stuff->height) {
- client->errorValue = stuff->height;
+ if (height < pScrPriv->minHeight ||
+ pScrPriv->maxHeight < height) {
+ client->errorValue = height;
return BadValue;
}
for (i = 0; i < pScrPriv->numCrtcs; i++) {
@@ -271,11 +272,51 @@ ProcRRSetScreenSize(ClientPtr client)
source_height = mode->mode.width;
}
- if (crtc->x + source_width > stuff->width ||
- crtc->y + source_height > stuff->height)
+ if (crtc->x + source_width > width ||
+ crtc->y + source_height > height)
return BadMatch;
}
}
+ return Success;
+}
+static int rrCheckMultiScreenSize(ClientPtr client,
+ ScreenPtr pScreen, int width, int height)
+{
+ rrScrPrivPtr pScrPriv, gpupriv;
+ ScreenPtr gpuscreen;
+ int ret;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ gpuscreen = pScreen->gpu[0];
+ gpupriv = rrGetScrPriv(gpuscreen);
+
+ ret = rr_check_single_size(client, gpupriv, width, height);
+ return ret;
+}
+
+int
+ProcRRSetScreenSize(ClientPtr client)
+{
+ REQUEST(xRRSetScreenSizeReq);
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ int i, rc;
+ int ret;
+
+ REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ pScreen = pWin->drawable.pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+ if (pScreen->num_gpu)
+ ret = rrCheckMultiScreenSize(client, pScreen, stuff->width, stuff->height);
+ else
+ ret = rr_check_single_size(client, pScrPriv, stuff->width, stuff->height);
+ if (ret)
+ return ret;
if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) {
client->errorValue = 0;
return BadValue;
@@ -289,6 +330,65 @@ ProcRRSetScreenSize(ClientPtr client)
return Success;
}
+#define update_totals(gpuscreen, pScrPriv) do { \
+ total_crtcs += pScrPriv->numCrtcs; \
+ total_outputs += pScrPriv->numOutputs; \
+ modes = RRModesForScreen(gpuscreen, &num_modes); \
+ if (!modes) \
+ return BadAlloc; \
+ for (j = 0; j < num_modes; j++) \
+ total_name_len += modes[j]->mode.nameLength; \
+ total_modes += num_modes; \
+ free(modes); \
+} while(0)
+
+static inline void swap_modeinfos(xRRModeInfo *modeinfos, int i)
+{
+ swapl(&modeinfos[i].id);
+ swaps(&modeinfos[i].width);
+ swaps(&modeinfos[i].height);
+ swapl(&modeinfos[i].dotClock);
+ swaps(&modeinfos[i].hSyncStart);
+ swaps(&modeinfos[i].hSyncEnd);
+ swaps(&modeinfos[i].hTotal);
+ swaps(&modeinfos[i].hSkew);
+ swaps(&modeinfos[i].vSyncStart);
+ swaps(&modeinfos[i].vSyncEnd);
+ swaps(&modeinfos[i].vTotal);
+ swaps(&modeinfos[i].nameLength);
+ swapl(&modeinfos[i].modeFlags);
+}
+
+#define update_arrays(gpuscreen, pScrPriv) do { \
+ for (j = 0; j < pScrPriv->numCrtcs; j++) { \
+ crtcs[crtc_count] = pScrPriv->crtcs[j]->id; \
+ if (client->swapped) \
+ swapl(&crtcs[crtc_count]); \
+ crtc_count++; \
+ } \
+ for (j = 0; j < pScrPriv->numOutputs; j++) { \
+ outputs[output_count] = pScrPriv->outputs[j]->id; \
+ if (client->swapped) \
+ swapl(&outputs[output_count]); \
+ output_count++; \
+ } \
+ { \
+ RRModePtr mode; \
+ modes = RRModesForScreen(gpuscreen, &num_modes); \
+ for (j = 0; j < num_modes; j++) { \
+ mode = modes[j]; \
+ modeinfos[mode_count] = mode->mode; \
+ if (client->swapped) { \
+ swap_modeinfos(modeinfos, i); \
+ } \
+ memcpy(names, mode->name, mode->mode.nameLength); \
+ names += mode->mode.nameLength; \
+ mode_count++; \
+ } \
+ free(modes); \
+ } \
+ } while (0)
+
static int
rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
{
@@ -319,32 +419,16 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
pScrPriv = rrGetScrPriv(gpuscreen);
- total_crtcs += pScrPriv->numCrtcs;
- total_outputs += pScrPriv->numOutputs;
+ if (query && pScrPriv)
+ if (!RRGetInfo(gpuscreen, query))
+ return BadAlloc;
- /* maybe add a mode count fn */
- modes = RRModesForScreen(gpuscreen, &num_modes);
- if (!modes)
- return BadAlloc;
-
- for (j = 0; j < num_modes; j++)
- total_name_len += modes[j]->mode.nameLength;
- total_modes += num_modes;
- free(modes);
+ update_totals(gpuscreen, pScrPriv);
xorg_list_for_each_entry(iter, &gpuscreen->output_slave_list, output_head) {
pScrPriv = rrGetScrPriv(iter);
- total_crtcs += pScrPriv->numCrtcs;
- total_outputs += pScrPriv->numOutputs;
-
- modes = RRModesForScreen(gpuscreen, &num_modes);
- if (!modes)
- return BadAlloc;
- for (j = 0; j < num_modes; j++)
- total_name_len += modes[j]->mode.nameLength;
- total_modes += num_modes;
- free(modes);
+ update_totals(iter, pScrPriv);
}
}
@@ -389,46 +473,12 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
gpuscreen = pScreen->gpu[i];
pScrPriv = rrGetScrPriv(gpuscreen);
- for (j = 0; j < pScrPriv->numCrtcs; j++) {
- crtcs[crtc_count] = pScrPriv->crtcs[j]->id;
- if (client->swapped)
- swapl(&crtcs[crtc_count]);
- crtc_count++;
- }
+ update_arrays(gpuscreen, pScrPriv);
- for (j = 0; j < pScrPriv->numOutputs; j++) {
- outputs[output_count] = pScrPriv->outputs[j]->id;
- if (client->swapped)
- swapl(&outputs[output_count]);
- output_count++;
- }
+ xorg_list_for_each_entry(iter, &gpuscreen->output_slave_list, output_head) {
+ pScrPriv = rrGetScrPriv(iter);
- {
- RRModePtr mode;
- modes = RRModesForScreen(gpuscreen, &num_modes);
- for (j = 0; j < num_modes; j++) {
- mode = modes[j];
- modeinfos[mode_count] = mode->mode;
- if (client->swapped) {
- swapl(&modeinfos[i].id);
- swaps(&modeinfos[i].width);
- swaps(&modeinfos[i].height);
- swapl(&modeinfos[i].dotClock);
- swaps(&modeinfos[i].hSyncStart);
- swaps(&modeinfos[i].hSyncEnd);
- swaps(&modeinfos[i].hTotal);
- swaps(&modeinfos[i].hSkew);
- swaps(&modeinfos[i].vSyncStart);
- swaps(&modeinfos[i].vSyncEnd);
- swaps(&modeinfos[i].vTotal);
- swaps(&modeinfos[i].nameLength);
- swapl(&modeinfos[i].modeFlags);
- }
- memcpy(names, mode->name, mode->mode.nameLength);
- names += mode->mode.nameLength;
- mode_count++;
- }
- free(modes);
+ update_arrays(iter, pScrPriv);
}
}