summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2012-05-06 11:23:06 +0300
committerAlon Levy <alevy@redhat.com>2012-05-31 20:24:33 +0300
commitdaf2145d044699c7c22ce62c4085899b8cf9f346 (patch)
tree360eab885a46511c1737dee172cbd56b823706f6
parent86f979fba87cb1e7c509dd7bb58b8c417f9bb5aa (diff)
wip randr crtc/output
-rw-r--r--src/qxl.h15
-rw-r--r--src/qxl_driver.c352
-rw-r--r--src/qxl_surface.c7
3 files changed, 269 insertions, 105 deletions
diff --git a/src/qxl.h b/src/qxl.h
index de19ede..fca1a81 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -38,6 +38,7 @@
#include "xf86Cursor.h"
#include "xf86_OSproc.h"
#include "xf86xv.h"
+#include "xf86Crtc.h"
#include "shadow.h"
#include "micmap.h"
#include "uxa/uxa.h"
@@ -154,11 +155,15 @@ struct _qxl_screen_t
long surface0_size;
long vram_size;
+ DisplayModePtr x_modes;
+
int virtual_x;
int virtual_y;
void * fb;
int stride;
- struct QXLMode * current_mode;
+
+ /* not the same as the heads mode for #head > 1 or virtual != head size */
+ struct QXLMode primary_mode;
qxl_surface_t * primary;
int bytes_per_pixel;
@@ -171,6 +176,9 @@ struct _qxl_screen_t
EntityInfoPtr entity;
+ xf86CrtcPtr * crtcs;
+ xf86OutputPtr * outputs;
+
#ifndef XSPICE
void * io_pages;
void * io_pages_physical;
@@ -247,6 +255,11 @@ struct _qxl_screen_t
#endif /* XSPICE */
};
+typedef struct qxl_output_private {
+ qxl_screen_t *qxl;
+ int head;
+} qxl_output_private;
+
static inline uint64_t
physical_address (qxl_screen_t *qxl, void *virtual, uint8_t slot_id)
{
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index f7161bf..121ae02 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -698,7 +698,9 @@ set_screen_pixmap_header (ScreenPtr pScreen)
qxl_screen_t *qxl = pScrn->driverPrivate;
PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
- if (pPixmap && qxl->current_mode)
+ // TODO: don't ModifyPixmapHeader too early?
+
+ if (pPixmap)
{
ErrorF ("new stride: %d (display width: %d, bpp: %d)\n",
qxl->pScrn->displayWidth * qxl->bytes_per_pixel,
@@ -706,13 +708,13 @@ set_screen_pixmap_header (ScreenPtr pScreen)
pScreen->ModifyPixmapHeader(
pPixmap,
- qxl->current_mode->x_res, qxl->current_mode->y_res,
+ qxl->primary_mode.x_res, qxl->primary_mode.y_res,
-1, -1,
qxl->pScrn->displayWidth * qxl->bytes_per_pixel,
NULL);
}
else
- ErrorF ("pix: %p; mode: %p\n", pPixmap, qxl->current_mode);
+ ErrorF ("pix: %p;\n", pPixmap);
}
static Bool
@@ -723,6 +725,19 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
struct QXLMode *m = qxl->modes + mode_index;
ScreenPtr pScreen;
+ ErrorF ("TODO: Determine (earlier then here, at rom reading) if QXLHead is supported\n");
+ ErrorF ("TODO: If it isn't, make pScreen->virtualX = width, virtualY = height\n");
+ ErrorF ("TODO: And ensure this always remains the same.\n");
+ ErrorF ("TODO: Else make sure (before, caller sets ->width) that virtualX, virtualY is actually\n");
+ ErrorF ("TODO: larger (?!?) and send a QXLHead message for the actual mode, m\n");
+ (void)m;
+
+ /*
+ * TODO: send a QXLHead message if device supports it,
+ * otherwise ensure pScrn->virtualX and pScrn->virtualY
+ * match the mode, i.e. virtual size is head size.
+ */
+
if (qxl->primary)
{
qxl_surface_kill (qxl->primary);
@@ -731,8 +746,18 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
qxl_io_destroy_primary(qxl);
- qxl->primary = qxl_surface_cache_create_primary (qxl->surface_cache, m);
- qxl->current_mode = m;
+ {
+ struct QXLMode *pm = &qxl->primary_mode;
+ pm->id = 0x4242;
+ pm->x_res = qxl->virtual_x;
+ pm->y_res = qxl->virtual_y;
+ pm->bits = qxl->pScrn->bitsPerPixel;
+ pm->stride = qxl->virtual_x * pm->bits / 8;
+ pm->x_mili = 0; // TODO
+ pm->y_mili = 0; // TODO
+ pm->orientation = 0; // ? supported by us for single head usage? more TODO
+ }
+ qxl->primary = qxl_surface_cache_create_primary (qxl->surface_cache, &qxl->primary_mode);
qxl->bytes_per_pixel = (qxl->pScrn->bitsPerPixel + 7) / 8;
pScreen = qxl->pScrn->pScreen;
@@ -1127,7 +1152,7 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
CHECK_POINT();
- qxl->pScrn = pScrn;
+ assert(qxl->pScrn == pScrn);
if (!qxl_map_memory(qxl, scrnIndex))
return FALSE;
@@ -1149,11 +1174,7 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
goto out;
if (!miSetPixmapDepths())
goto out;
-
- qxl->virtual_x = pScrn->virtualX;
- qxl->virtual_y = pScrn->virtualY;
- qxl->stride = pScrn->virtualX * 4;
-
+
pScrn->displayWidth = pScrn->virtualX;
qxl->fb = calloc (pScrn->virtualY * pScrn->displayWidth, 4);
@@ -1241,6 +1262,10 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pScreen->width = pScrn->currentMode->HDisplay;
pScreen->height = pScrn->currentMode->VDisplay;
+ if (!xf86CrtcScreenInit(pScreen)) {
+ return FALSE;
+ }
+
qxl_switch_mode(scrnIndex, pScrn->currentMode, 0);
/* Note: this must be done after DamageSetup() because it calls
@@ -1393,80 +1418,11 @@ qxl_check_device(ScrnInfoPtr pScrn, qxl_screen_t *qxl)
}
#endif /* !XSPICE */
-static int
-qxl_find_native_mode(ScrnInfoPtr pScrn, DisplayModePtr p)
-{
- int i;
- qxl_screen_t *qxl = pScrn->driverPrivate;
-
- CHECK_POINT();
-
- for (i = 0; i < qxl->num_modes; i++)
- {
- struct QXLMode *m = qxl->modes + i;
-
- if (m->x_res == p->HDisplay &&
- m->y_res == p->VDisplay &&
- m->bits == pScrn->bitsPerPixel)
- {
- if (m->bits == 16)
- {
- /* What QXL calls 16 bit is actually x1r5g5b515 */
- if (pScrn->depth == 15)
- return i;
- }
- else if (m->bits == 32)
- {
- /* What QXL calls 32 bit is actually x8r8g8b8 */
- if (pScrn->depth == 24)
- return i;
- }
- }
- }
-
- return -1;
-}
-
-static ModeStatus
-qxl_valid_mode(int scrn, DisplayModePtr p, Bool flag, int pass)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrn];
- int scrnIndex = pScrn->scrnIndex;
- qxl_screen_t *qxl = pScrn->driverPrivate;
- int bpp = pScrn->bitsPerPixel;
- int mode_idx;
-
- /* FIXME: I don't think this is necessary now that we report the
- * correct amount of video ram?
- */
- if (p->HDisplay * p->VDisplay * (bpp/8) > qxl->surface0_size)
- {
- xf86DrvMsg(scrnIndex, X_INFO, "rejecting mode %d x %d: insufficient memory\n", p->HDisplay, p->VDisplay);
- return MODE_MEM;
- }
-
- mode_idx = qxl_find_native_mode (pScrn, p);
- if (mode_idx == -1)
- {
- xf86DrvMsg(scrnIndex, X_INFO, "rejecting unknown mode %d x %d\n", p->HDisplay, p->VDisplay);
- return MODE_NOMODE;
- }
- p->Private = (void *)(unsigned long)mode_idx;
-
- xf86DrvMsg (scrnIndex, X_INFO, "accepting %d x %d\n", p->HDisplay, p->VDisplay);
-
- return MODE_OK;
-}
-
-static void qxl_add_mode(ScrnInfoPtr pScrn, int width, int height, int type)
+static DisplayModePtr qxl_add_mode(qxl_screen_t *qxl, ScrnInfoPtr pScrn,
+ int width, int height, int type)
{
DisplayModePtr mode;
- /* Skip already present modes */
- for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
- if (mode->HDisplay == width && mode->VDisplay == height)
- return;
-
mode = xnfcalloc(1, sizeof(DisplayModeRec));
mode->status = MODE_OK;
@@ -1483,10 +1439,134 @@ static void qxl_add_mode(ScrnInfoPtr pScrn, int width, int height, int type)
mode->Flags = V_NHSYNC | V_PVSYNC;
xf86SetModeDefaultName(mode);
- xf86ModesAdd(pScrn->monitor->Modes, mode);
+ xf86SetModeCrtc(mode, pScrn->adjustFlags); /* needed? xf86-video-modesetting does this */
+ qxl->x_modes = xf86ModesAdd(qxl->x_modes, mode);
+ return mode;
+}
+
+static DisplayModePtr
+qxl_output_get_modes(xf86OutputPtr output)
+{
+ qxl_output_private *qxl_output = output->driver_private;
+
+ /* xf86ProbeOutputModes owns this memory */
+ return xf86DuplicateModes(qxl_output->qxl->pScrn, qxl_output->qxl->x_modes);
+}
+
+static void
+qxl_output_destroy(xf86OutputPtr output)
+{
+}
+
+static void
+qxl_output_dpms(xf86OutputPtr output, int mode)
+{
+}
+
+static void
+qxl_output_create_resources(xf86OutputPtr output)
+{
+}
+
+static Bool
+qxl_output_set_property(xf86OutputPtr output, Atom property,
+ RRPropertyValuePtr value)
+{
+ return FALSE;
+}
+
+static Bool
+qxl_output_get_property(xf86OutputPtr output, Atom property)
+{
+ return TRUE;
+}
+
+static xf86OutputStatus
+qxl_output_detect(xf86OutputPtr output)
+{
+ // TODO - how do I query this? do I add fields and let the host set this instead
+ // of the guest agent? or can I set this via the guest agent? I could just check
+ // some files / anything in userspace, settable by the guest agent. dbus even.
+ return XF86OutputStatusConnected;
+}
+
+static Bool
+qxl_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+{
+ return MODE_OK;
+}
+
+static const xf86OutputFuncsRec qxl_output_funcs = {
+ .dpms = qxl_output_dpms,
+ .create_resources = qxl_output_create_resources,
+#ifdef RANDR_12_INTERFACE
+ .set_property = qxl_output_set_property,
+ .get_property = qxl_output_get_property,
+#endif
+ .detect = qxl_output_detect,
+ .mode_valid = qxl_output_mode_valid,
+
+ .get_modes = qxl_output_get_modes,
+ .destroy = qxl_output_destroy
+};
+
+static void
+qxl_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
}
static Bool
+qxl_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
+{
+ return FALSE;
+}
+
+static void
+qxl_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
+{
+}
+
+static void
+qxl_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+}
+
+static void
+qxl_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
+{
+}
+
+static void
+qxl_hide_cursor (xf86CrtcPtr crtc)
+{
+}
+
+static void
+qxl_show_cursor (xf86CrtcPtr crtc)
+{
+}
+
+static void
+qxl_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
+ uint16_t *blue, int size)
+{
+}
+
+static const xf86CrtcFuncsRec qxl_crtc_funcs = {
+ .dpms = qxl_crtc_dpms,
+ .set_mode_major = qxl_set_mode_major,
+ .set_cursor_colors = qxl_set_cursor_colors,
+ .set_cursor_position = qxl_set_cursor_position,
+ .show_cursor = qxl_show_cursor,
+ .hide_cursor = qxl_hide_cursor,
+ .load_cursor_argb = qxl_load_cursor_argb,
+
+ .gamma_set = qxl_crtc_gamma_set,
+ .destroy = NULL, /* XXX */
+};
+
+static Bool
qxl_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
{
/* TODO */
@@ -1497,15 +1577,86 @@ static const xf86CrtcConfigFuncsRec qxl_xf86crtc_config_funcs = {
qxl_xf86crtc_resize
};
+static void
+qxl_init_randr(ScrnInfoPtr pScrn, qxl_screen_t *qxl)
+{
+ char name[32];
+ qxl_output_private *qxl_output;
+ int i;
+ xf86OutputPtr output;
+ int maxWidth = 2048;
+ int maxHeight = 1024;
+
+ xf86CrtcConfigInit(pScrn, &qxl_xf86crtc_config_funcs);
+
+ /* This is actually redundant, it's overwritten by a later call via
+ * xf86InitialConfiguration */
+ xf86CrtcSetSizeRange(pScrn, 320, 200, maxWidth, maxHeight);
+
+ /* The count is arbitrary. */
+ // TODO pickup count from xorg.conf and/or from pci device (QXLRom)
+ qxl->crtcs = xnfcalloc(sizeof(xf86CrtcPtr), 2);
+ qxl->outputs = xnfcalloc(sizeof(xf86OutputPtr), 2);
+ for (i = 0 ; i < 2; ++i) {
+ qxl->crtcs[i] = xf86CrtcCreate(pScrn, &qxl_crtc_funcs);
+ if (!qxl->crtcs[i]) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to create Crtc %d",
+ i);
+ }
+ snprintf(name, sizeof(name), "qxl-%d", i);
+ qxl->outputs[i] = output = xf86OutputCreate(pScrn, &qxl_output_funcs, name);
+ if (!output) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to create Output %d",
+ i);
+ }
+ output->possible_crtcs = (1 << i); /* bitrange of allowed outputs - do a 1:1 */
+ output->possible_clones = 0; /* TODO: not? */
+ qxl_output = xnfcalloc(sizeof(qxl_output_private), 1);
+ output->driver_private = qxl_output;
+ qxl_output->head = i;
+ qxl_output->qxl = qxl;
+ }
+
+ // TODO: resizable primary surface.
+ qxl->virtual_x = maxWidth;
+ qxl->virtual_y = maxHeight;
+ qxl->stride = maxWidth * 4; // TODO - do we actually use this?
+
+ pScrn->display->virtualX = qxl->virtual_x;
+ pScrn->display->virtualY = qxl->virtual_y;
+
+ xf86InitialConfiguration(pScrn, FALSE /* no growing of virtualX/virtualY, TODO */);
+}
+
+static void
+qxl_initialize_x_modes(qxl_screen_t *qxl, ScrnInfoPtr pScrn,
+ unsigned int *max_x, unsigned int *max_y)
+{
+ int i;
+
+ *max_x = *max_y = 0;
+ /* Create a list of modes used by the qxl_output_get_modes */
+ for (i = 0; i < qxl->num_modes; i++) {
+ if (qxl->modes[i].orientation == 0) {
+ qxl_add_mode(qxl, pScrn, qxl->modes[i].x_res, qxl->modes[i].y_res,
+ M_T_DRIVER);
+ if (qxl->modes[i].x_res > *max_x)
+ *max_x = qxl->modes[i].x_res;
+ if (qxl->modes[i].y_res > *max_y)
+ *max_y = qxl->modes[i].y_res;
+ }
+ }
+}
+
static Bool
qxl_pre_init(ScrnInfoPtr pScrn, int flags)
{
- int i, scrnIndex = pScrn->scrnIndex;
+ int scrnIndex = pScrn->scrnIndex;
qxl_screen_t *qxl = NULL;
ClockRangePtr clockRanges = NULL;
- int *linePitches = NULL;
- DisplayModePtr mode;
- unsigned int max_x = 0, max_y = 0;
+ //int *linePitches = NULL;
+ //DisplayModePtr mode;
+ unsigned int max_x, max_y;
/* In X server 1.7.5, Xorg -configure will cause this
* function to get called without a confScreen.
@@ -1526,6 +1677,8 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
qxl = pScrn->driverPrivate;
memset(qxl, 0, sizeof(qxl));
qxl->device_primary = QXL_DEVICE_PRIMARY_UNDEFINED;
+ qxl->pScrn = pScrn;
+ qxl->x_modes = NULL;
qxl->entity = xf86GetEntityInfo(pScrn->entityList[0]);
@@ -1596,17 +1749,9 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
pScrn->monitor->nVrefresh = 1;
}
- /* Add any modes not in xorg's default mode list */
- for (i = 0; i < qxl->num_modes; i++)
- if (qxl->modes[i].orientation == 0) {
- qxl_add_mode(pScrn, qxl->modes[i].x_res, qxl->modes[i].y_res,
- M_T_DRIVER);
- if (qxl->modes[i].x_res > max_x)
- max_x = qxl->modes[i].x_res;
- if (qxl->modes[i].y_res > max_y)
- max_y = qxl->modes[i].y_res;
- }
+ qxl_initialize_x_modes(qxl, pScrn, &max_x, &max_y);
+#if 0
if (pScrn->display->virtualX == 0 && pScrn->display->virtualY == 0) {
/* It is possible for the largest x + largest y size combined leading
to a virtual size which will not fit into the framebuffer when this
@@ -1628,16 +1773,14 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
pScrn->display->virtualY,
128 * 1024 * 1024, LOOKUP_BEST_REFRESH))
goto out;
+#endif
CHECK_POINT();
- xf86CrtcConfigInit(pScrn, &qxl_xf86crtc_config_funcs);
-
- xf86CrtcSetSizeRange(pScrn, 320, 200, 4096, 4096);
-
xf86PruneDriverModes(pScrn);
- pScrn->currentMode = pScrn->modes;
+ qxl_init_randr(pScrn, qxl);
+#if 0
/* If no modes are specified in xorg.conf, default to 1024x768 */
if (pScrn->display->modes == NULL || pScrn->display->modes[0] == NULL)
for (mode = pScrn->modes; mode; mode = mode->next)
@@ -1645,8 +1788,9 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
pScrn->currentMode = mode;
break;
}
+#endif
- xf86PrintModes(pScrn);
+ //xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
if (!xf86LoadSubModule(pScrn, "fb")
@@ -1740,7 +1884,7 @@ qxl_init_scrn(ScrnInfoPtr pScrn)
pScrn->PreInit = qxl_pre_init;
pScrn->ScreenInit = qxl_screen_init;
pScrn->SwitchMode = qxl_switch_mode;
- pScrn->ValidMode = qxl_valid_mode;
+ pScrn->ValidMode = NULL,
pScrn->EnterVT = qxl_enter_vt;
pScrn->LeaveVT = qxl_leave_vt;
}
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index c2f4797..0ec7064 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -342,6 +342,12 @@ qxl_surface_recycle (surface_cache_t *cache, uint32_t id)
cache->free_surfaces = surface;
}
+/*
+ * mode is used for the whole virtual screen, not for a specific head.
+ * For a single head where virtual size is equal to the head size, they are
+ * equal. For multiple heads this mode will not match any existing heads and
+ * will be the containing virtual size.
+ */
qxl_surface_t *
qxl_surface_cache_create_primary (surface_cache_t *cache,
struct QXLMode *mode)
@@ -458,6 +464,7 @@ make_drawable (qxl_screen_t *qxl, int surface, uint8_t type,
int i;
drawable = qxl_allocnf (qxl, sizeof *drawable);
+ assert(drawable);
drawable->release_info.id = pointer_to_u64 (drawable);