diff options
author | Alon Levy <alevy@redhat.com> | 2012-05-06 11:23:06 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2012-05-31 20:24:33 +0300 |
commit | daf2145d044699c7c22ce62c4085899b8cf9f346 (patch) | |
tree | 360eab885a46511c1737dee172cbd56b823706f6 | |
parent | 86f979fba87cb1e7c509dd7bb58b8c417f9bb5aa (diff) |
wip randr crtc/output
-rw-r--r-- | src/qxl.h | 15 | ||||
-rw-r--r-- | src/qxl_driver.c | 352 | ||||
-rw-r--r-- | src/qxl_surface.c | 7 |
3 files changed, 269 insertions, 105 deletions
@@ -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); |