diff options
author | marha <marha@users.sourceforge.net> | 2009-07-25 20:12:58 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-07-25 20:12:58 +0000 |
commit | 2553bdd7c359cd87525d367761c86932cec5adff (patch) | |
tree | ae71245933c98474a699d3e392de5820879b2018 /xorg-server/hw/xfree86/modes | |
parent | e2c51f2ee7b0a3ea1a052fc49324057b4a4bbc78 (diff) | |
parent | 4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05 (diff) | |
download | vcxsrv-2553bdd7c359cd87525d367761c86932cec5adff.tar.gz vcxsrv-2553bdd7c359cd87525d367761c86932cec5adff.tar.bz2 vcxsrv-2553bdd7c359cd87525d367761c86932cec5adff.zip |
svn merge file:///D:/svnrepos/vcxsrv/branches/released .
Diffstat (limited to 'xorg-server/hw/xfree86/modes')
-rw-r--r-- | xorg-server/hw/xfree86/modes/Makefile.in | 76 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Crtc.c | 516 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Crtc.h | 122 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Cursors.c | 65 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86EdidModes.c | 331 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Modes.c | 34 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Modes.h | 16 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86RandR12.c | 596 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86RandR12.h | 1 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Rename.h | 1 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Rotate.c | 494 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86gtf.c | 4 |
12 files changed, 1666 insertions, 590 deletions
diff --git a/xorg-server/hw/xfree86/modes/Makefile.in b/xorg-server/hw/xfree86/modes/Makefile.in index ff0a94f9f..0af44e357 100644 --- a/xorg-server/hw/xfree86/modes/Makefile.in +++ b/xorg-server/hw/xfree86/modes/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. +# Makefile.in generated by automake 1.10.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -45,7 +45,6 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \ $(top_builddir)/include/xorg-server.h \ $(top_builddir)/include/dix-config.h \ - $(top_builddir)/include/xgl-config.h \ $(top_builddir)/include/xorg-config.h \ $(top_builddir)/include/xkb-config.h \ $(top_builddir)/include/xwin-config.h \ @@ -65,9 +64,6 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -91,8 +87,9 @@ ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ -APPDEFAULTDIR = @APPDEFAULTDIR@ APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APPLE_APPLICATION_ID = @APPLE_APPLICATION_ID@ +APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ APP_MAN_DIR = @APP_MAN_DIR@ APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ AR = @AR@ @@ -113,10 +110,6 @@ CFLAGS = @CFLAGS@ COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DARWIN_LIBS = @DARWIN_LIBS@ DBUS_CFLAGS = @DBUS_CFLAGS@ @@ -138,6 +131,7 @@ DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ +DOLT_BASH = @DOLT_BASH@ DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ @@ -147,18 +141,15 @@ DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ DRI_DRIVER_PATH = @DRI_DRIVER_PATH@ DSYMUTIL = @DSYMUTIL@ DTRACE = @DTRACE@ -ECHO = @ECHO@ +DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ +FGREP = @FGREP@ FILE_MAN_DIR = @FILE_MAN_DIR@ FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ -FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ -FREETYPE_LIBS = @FREETYPE_LIBS@ GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ GLX_DEFINES = @GLX_DEFINES@ GL_CFLAGS = @GL_CFLAGS@ @@ -177,7 +168,7 @@ KDRIVE_LIBS = @KDRIVE_LIBS@ KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ -LAUNCHD = @LAUNCHD@ +LD = @LD@ LDFLAGS = @LDFLAGS@ LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ LEX = @LEX@ @@ -191,7 +182,10 @@ LIBTOOL = @LIBTOOL@ LIB_MAN_DIR = @LIB_MAN_DIR@ LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ LINUXDOC = @LINUXDOC@ +LIPO = @LIPO@ LN_S = @LN_S@ +LTCOMPILE = @LTCOMPILE@ +LTCXXCOMPILE = @LTCXXCOMPILE@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ @@ -203,8 +197,7 @@ MESA_SOURCE = @MESA_SOURCE@ MISC_MAN_DIR = @MISC_MAN_DIR@ MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ MKDIR_P = @MKDIR_P@ -MKFONTDIR = @MKFONTDIR@ -MKFONTSCALE = @MKFONTSCALE@ +NM = @NM@ NMEDIT = @NMEDIT@ OBJC = @OBJC@ OBJCCLD = @OBJCCLD@ @@ -213,8 +206,8 @@ OBJCFLAGS = @OBJCFLAGS@ OBJCLINK = @OBJCLINK@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ @@ -247,7 +240,6 @@ VENDOR_NAME = @VENDOR_NAME@ VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ VENDOR_RELEASE = @VENDOR_RELEASE@ VERSION = @VERSION@ -X11APP_ARCHS = @X11APP_ARCHS@ X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ XDMCP_CFLAGS = @XDMCP_CFLAGS@ @@ -257,27 +249,12 @@ XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ XDMX_CFLAGS = @XDMX_CFLAGS@ XDMX_LIBS = @XDMX_LIBS@ XDMX_SYS_LIBS = @XDMX_SYS_LIBS@ -XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@ -XEGL_LIBS = @XEGL_LIBS@ -XEGL_SYS_LIBS = @XEGL_SYS_LIBS@ XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ -XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@ XEPHYR_INCS = @XEPHYR_INCS@ XEPHYR_LIBS = @XEPHYR_LIBS@ XF86CONFIGFILE = @XF86CONFIGFILE@ -XF86MISC_CFLAGS = @XF86MISC_CFLAGS@ -XF86MISC_LIBS = @XF86MISC_LIBS@ XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ -XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@ -XGLMODULES_LIBS = @XGLMODULES_LIBS@ -XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@ -XGLXMODULES_LIBS = @XGLXMODULES_LIBS@ -XGLX_LIBS = @XGLX_LIBS@ -XGLX_SYS_LIBS = @XGLX_SYS_LIBS@ -XGL_LIBS = @XGL_LIBS@ -XGL_MODULE_PATH = @XGL_MODULE_PATH@ -XGL_SYS_LIBS = @XGL_SYS_LIBS@ XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@ XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@ XKB_COMPILED_DIR = @XKB_COMPILED_DIR@ @@ -288,10 +265,6 @@ XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@ XNESTMODULES_LIBS = @XNESTMODULES_LIBS@ XNEST_LIBS = @XNEST_LIBS@ XNEST_SYS_LIBS = @XNEST_SYS_LIBS@ -XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@ -XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@ -XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@ -XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@ XORG_CFLAGS = @XORG_CFLAGS@ XORG_INCS = @XORG_INCS@ XORG_LIBS = @XORG_LIBS@ @@ -300,13 +273,8 @@ XORG_MODULES_LIBS = @XORG_MODULES_LIBS@ XORG_OS = @XORG_OS@ XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ XORG_SYS_LIBS = @XORG_SYS_LIBS@ -XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@ -XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@ -XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@ -XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@ -XPRINT_CFLAGS = @XPRINT_CFLAGS@ -XPRINT_LIBS = @XPRINT_LIBS@ -XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@ +XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@ +XPBPROXY_LIBS = @XPBPROXY_LIBS@ XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ XSDL_INCS = @XSDL_INCS@ @@ -339,8 +307,7 @@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -360,7 +327,6 @@ driverdir = @driverdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ extdir = @extdir@ -ft_config = @ft_config@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -370,12 +336,12 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ -launchagentsdir = @launchagentsdir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ +lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ moduledir = @moduledir@ @@ -393,8 +359,6 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -xglmoduledir = @xglmoduledir@ -xpconfigdir = @xpconfigdir@ noinst_LIBRARIES = libxf86modes.a libxf86modes_a_SOURCES = \ xf86Crtc.c \ @@ -432,8 +396,8 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ @@ -530,7 +494,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 1facf86e9..84d3cac3e 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -96,6 +96,7 @@ xf86CrtcCreate (ScrnInfoPtr scrn, crtc = xcalloc (sizeof (xf86CrtcRec), 1); if (!crtc) return NULL; + crtc->version = XF86_CRTC_VERSION; crtc->scrn = scrn; crtc->funcs = funcs; #ifdef RANDR_12_INTERFACE @@ -103,6 +104,19 @@ xf86CrtcCreate (ScrnInfoPtr scrn, #endif crtc->rotation = RR_Rotate_0; crtc->desiredRotation = RR_Rotate_0; + pixman_transform_init_identity (&crtc->crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); + crtc->filter = NULL; + crtc->params = NULL; + crtc->nparams = 0; + crtc->filter_width = 0; + crtc->filter_height = 0; + crtc->transform_in_use = FALSE; + crtc->transformPresent = FALSE; + crtc->desiredTransformPresent = FALSE; + memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); + if (xf86_config->crtc) crtcs = xrealloc (xf86_config->crtc, (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); @@ -134,6 +148,8 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) xf86_config->num_crtc--; break; } + if (crtc->params) + xfree (crtc->params); xfree (crtc); } @@ -224,8 +240,8 @@ xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) * Sets the given video mode on the given crtc */ _X_EXPORT Bool -xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - int x, int y) +xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + RRTransformPtr transform, int x, int y) { ScrnInfoPtr scrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -236,12 +252,14 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, DisplayModeRec saved_mode; int saved_x, saved_y; Rotation saved_rotation; + RRTransformRec saved_transform; + Bool saved_transform_present; if (crtc->funcs->set_mode_major) return crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); - + crtc->enabled = xf86CrtcInUse (crtc); - + if (!crtc->enabled) { /* XXX disable crtc? */ @@ -256,6 +274,12 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, saved_x = crtc->x; saved_y = crtc->y; saved_rotation = crtc->rotation; + if (crtc->transformPresent) { + RRTransformInit (&saved_transform); + RRTransformCopy (&saved_transform, &crtc->transform); + } + saved_transform_present = crtc->transformPresent; + /* Update crtc values up front so the driver can rely on them for mode * setting. */ @@ -263,33 +287,25 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, crtc->x = x; crtc->y = y; crtc->rotation = rotation; + if (transform) { + RRTransformCopy (&crtc->transform, transform); + crtc->transformPresent = TRUE; + } else + crtc->transformPresent = FALSE; - /* Shift offsets that move us out of virtual size */ - if (x + mode->HDisplay > xf86_config->maxWidth || - y + mode->VDisplay > xf86_config->maxHeight) + if (crtc->funcs->set_origin && + memcmp (mode, &saved_mode, sizeof(saved_mode)) == 0 && + saved_rotation == rotation && + saved_transform_present == crtc->transformPresent && + (!crtc->transformPresent || RRTransformEqual(&saved_transform, &crtc->transform))) { - if (x + mode->HDisplay > xf86_config->maxWidth) - crtc->x = xf86_config->maxWidth - mode->HDisplay; - if (y + mode->VDisplay > xf86_config->maxHeight) - crtc->y = xf86_config->maxHeight - mode->VDisplay; - if (crtc->x < 0 || crtc->y < 0) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Mode %dx%d does not fit virtual size %dx%d - " - "internal error\n", mode->HDisplay, mode->VDisplay, - xf86_config->maxWidth, xf86_config->maxHeight); - goto done; - } - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Mode %dx%d+%d+%d does not fit virtual size %dx%d - " - "offset updated to +%d+%d\n", - mode->HDisplay, mode->VDisplay, x, y, - xf86_config->maxWidth, xf86_config->maxHeight, - crtc->x, crtc->y); + if (!xf86CrtcRotate (crtc)) + goto done; + crtc->funcs->set_origin (crtc, crtc->x, crtc->y); + ret = TRUE; + goto done; } - /* XXX short-circuit changes to base location only */ - /* Pass our mode to the outputs and the CRTC to give them a chance to * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. @@ -309,9 +325,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, goto done; } - if (!xf86CrtcRotate (crtc, mode, rotation)) { + if (!xf86CrtcRotate (crtc)) goto done; - } /* Prepare the outputs and CRTCs before setting the mode. */ for (i = 0; i < xf86_config->num_output; i++) { @@ -343,13 +358,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, { xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) - { output->funcs->commit(output); -#ifdef RANDR_12_INTERFACE - if (output->randr_output) - RRPostPendingProperties (output->randr_output); -#endif - } } /* XXX free adjustedmode */ @@ -363,6 +372,9 @@ done: crtc->y = saved_y; crtc->rotation = saved_rotation; crtc->mode = saved_mode; + if (saved_transform_present) + RRTransformCopy (&crtc->transform, &saved_transform); + crtc->transformPresent = saved_transform_present; } if (didLock) @@ -371,6 +383,34 @@ done: return ret; } +/** + * Sets the given video mode on the given crtc, but without providing + * a transform + */ +_X_EXPORT Bool +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) +{ + return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); +} + +/** + * Pans the screen, does not change the mode + */ +_X_EXPORT void +xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) +{ + crtc->x = x; + crtc->y = y; + if (crtc->funcs->set_origin) { + if (!xf86CrtcRotate (crtc)) + return; + crtc->funcs->set_origin (crtc, x, y); + } + else + xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); +} + /* * Output functions */ @@ -390,6 +430,7 @@ typedef enum { OPTION_MAX_CLOCK, OPTION_IGNORE, OPTION_ROTATE, + OPTION_PANNING, } OutputOpts; static OptionInfoRec xf86OutputOptions[] = { @@ -405,6 +446,7 @@ static OptionInfoRec xf86OutputOptions[] = { {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, + {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, {-1, NULL, OPTV_NONE, {0}, FALSE }, }; @@ -694,7 +736,12 @@ xf86CrtcCloseScreen (int index, ScreenPtr screen) /* * Called at ScreenInit time to set up */ -_X_EXPORT Bool +_X_EXPORT +#ifdef RANDR_13_INTERFACE +int +#else +Bool +#endif xf86CrtcScreenInit (ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; @@ -714,11 +761,17 @@ xf86CrtcScreenInit (ScreenPtr screen) break; } if (c == config->num_crtc) + { xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270 | RR_Reflect_X | RR_Reflect_Y); + xf86RandR12SetTransformSupport (screen, TRUE); + } else + { xf86RandR12SetRotations (screen, RR_Rotate_0); + xf86RandR12SetTransformSupport (screen, FALSE); + } /* Wrap CreateScreenResources so we can initialize the RandR code */ config->CreateScreenResources = screen->CreateScreenResources; @@ -727,7 +780,11 @@ xf86CrtcScreenInit (ScreenPtr screen) config->CloseScreen = screen->CloseScreen; screen->CloseScreen = xf86CrtcCloseScreen; +#ifdef RANDR_13_INTERFACE + return RANDR_INTERFACE_VERSION; +#else return TRUE; +#endif } static DisplayModePtr @@ -905,7 +962,7 @@ xf86PickCrtcs (ScrnInfoPtr scrn, * see if they can be cloned */ if (xf86ModesEqual (modes[o], modes[n]) && - config->output[0]->initial_rotation == config->output[n]->initial_rotation && + config->output[o]->initial_rotation == config->output[n]->initial_rotation && config->output[o]->initial_x == config->output[n]->initial_x && config->output[o]->initial_y == config->output[n]->initial_y) { @@ -1176,10 +1233,12 @@ xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); break; case OPTION_ABOVE: - output->initial_y -= xf86ModeHeight (modes[o], relative->initial_rotation); + if (modes[o]) + output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); break; case OPTION_LEFT_OF: - output->initial_x -= xf86ModeWidth (modes[o], relative->initial_rotation); + if (modes[o]) + output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); break; default: break; @@ -1237,6 +1296,59 @@ xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) return TRUE; } +static void +xf86InitialPanning (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *panning = xf86GetOptValString (output->options, OPTION_PANNING); + int width, height, left, top; + int track_width, track_height, track_left, track_top; + int brdr[4]; + + memset (&output->initialTotalArea, 0, sizeof(BoxRec)); + memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); + memset (output->initialBorder, 0, 4*sizeof(INT16)); + + if (! panning) + continue; + + switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", + &width, &height, &left, &top, + &track_width, &track_height, &track_left, &track_top, + &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { + case 12: + output->initialBorder[0] = brdr[0]; + output->initialBorder[1] = brdr[1]; + output->initialBorder[2] = brdr[2]; + output->initialBorder[3] = brdr[3]; + /* fall through */ + case 8: + output->initialTrackingArea.x1 = track_left; + output->initialTrackingArea.y1 = track_top; + output->initialTrackingArea.x2 = track_left + track_width; + output->initialTrackingArea.y2 = track_top + track_height; + /* fall through */ + case 4: + output->initialTotalArea.x1 = left; + output->initialTotalArea.y1 = top; + /* fall through */ + case 2: + output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; + output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; + break; + default: + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Broken panning specification '%s' for output %s in config file\n", + panning, output->name); + } + } +} + /* * XXX walk the monitor mode list and prune out duplicates that * are inserted by xf86DDCMonitorSet. In an ideal world, that @@ -1407,7 +1519,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) { xf86OutputPtr output = config->output[o]; DisplayModePtr mode; - DisplayModePtr config_modes = NULL, output_modes, default_modes; + DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; char *preferred_mode; xf86MonPtr edid_monitor; XF86ConfMonitorPtr conf_monitor; @@ -1415,6 +1527,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) int min_clock = 0; int max_clock = 0; double clock; + Bool add_default_modes = TRUE; enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) @@ -1465,6 +1578,11 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) int i; Bool set_hsync = mon_rec.nHsync == 0; Bool set_vrefresh = mon_rec.nVrefresh == 0; + struct disp_features *features = &edid_monitor->features; + + /* if display is not continuous-frequency, don't add default modes */ + if (!GTF_SUPPORTED(features->msc)) + add_default_modes = FALSE; for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++) { @@ -1521,8 +1639,10 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) mon_rec.vrefresh[0].hi = 62.0; mon_rec.nVrefresh = 1; } - default_modes = xf86GetDefaultModes (output->interlaceAllowed, - output->doubleScanAllowed); + + if (add_default_modes) + default_modes = xf86GetDefaultModes (output->interlaceAllowed, + output->doubleScanAllowed); /* * If this is not an RB monitor, remove RB modes from the default @@ -1809,6 +1929,66 @@ nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) } static Bool +aspectMatch(float a, float b) +{ + return fabs(1 - (a / b)) < 0.05; +} + +static DisplayModePtr +nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) +{ + DisplayModePtr m = NULL; + + if (!o) + return NULL; + + if (!last) + m = o->probed_modes; + else + m = last->next; + + for (; m; m = m->next) + if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) + return m; + + return NULL; +} + +static DisplayModePtr +bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) +{ + int o = -1, p; + DisplayModePtr mode = NULL, test = NULL, match = NULL; + + if (!nextEnabledOutput(config, enabled, &o)) + return NULL; + while ((mode = nextAspectMode(config->output[o], mode, aspect))) { + test = mode; + for (p = o; nextEnabledOutput(config, enabled, &p); ) { + test = xf86OutputFindClosestMode(config->output[p], mode); + if (!test) + break; + if (test->HDisplay != mode->HDisplay || + test->VDisplay != mode->VDisplay) { + test = NULL; + break; + } + } + + /* if we didn't match it on all outputs, try the next one */ + if (!test) + continue; + + /* if it's bigger than the last one, save it */ + if (!match || (test->HDisplay > match->HDisplay)) + match = test; + } + + /* return the biggest one found */ + return match; +} + +static Bool xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, DisplayModePtr *modes, Bool *enabled, int width, int height) @@ -1860,75 +2040,43 @@ xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, } } - if (ret) { - /* oh good, there is a match. stash the selected modes and return. */ - memcpy(modes, preferred_match, - config->num_output * sizeof(DisplayModePtr)); - } - - xfree(preferred); - xfree(preferred_match); - return ret; -} - -static Bool -aspectMatch(float a, float b) -{ - return fabs(1 - (a / b)) < 0.05; -} - -static DisplayModePtr -nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) -{ - DisplayModePtr m = NULL; - - if (!o) - return NULL; + /* + * If there's no preferred mode, but only one monitor, pick the + * biggest mode for its aspect ratio, assuming one exists. + */ + if (!ret) do { + int i = 0; + float aspect = 0.0; - if (!last) - m = o->probed_modes; - else - m = last->next; + /* count the number of enabled outputs */ + for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; - for (; m; m = m->next) - if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) - return m; + if (i != 1) + break; - return NULL; -} + p = -1; + nextEnabledOutput(config, enabled, &p); + if (config->output[p]->mm_height) + aspect = (float)config->output[p]->mm_width / + (float)config->output[p]->mm_height; -static DisplayModePtr -bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) -{ - int o = -1, p; - DisplayModePtr mode = NULL, test = NULL, match = NULL; + if (aspect) + preferred_match[p] = bestModeForAspect(config, enabled, aspect); - if (!nextEnabledOutput(config, enabled, &o)) - return NULL; - while ((mode = nextAspectMode(config->output[o], mode, aspect))) { - test = mode; - for (p = o; nextEnabledOutput(config, enabled, &p); ) { - test = xf86OutputFindClosestMode(config->output[p], mode); - if (!test) - break; - if (test->HDisplay != mode->HDisplay || - test->VDisplay != mode->VDisplay) { - test = NULL; - break; - } - } + if (preferred_match[p]) + ret = TRUE; - /* if we didn't match it on all outputs, try the next one */ - if (!test) - continue; + } while (0); - /* if it's bigger than the last one, save it */ - if (!match || (test->HDisplay > match->HDisplay)) - match = test; + if (ret) { + /* oh good, there is a match. stash the selected modes and return. */ + memcpy(modes, preferred_match, + config->num_output * sizeof(DisplayModePtr)); } - /* return the biggest one found */ - return match; + xfree(preferred); + xfree(preferred_match); + return ret; } static Bool @@ -2127,6 +2275,11 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) xfree (modes); return FALSE; } + + /* + * Set initial panning of each output + */ + xf86InitialPanning (scrn); /* * Assign CRTCs to fit output configuration @@ -2166,9 +2319,13 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) crtc->desiredRotation = output->initial_rotation; crtc->desiredX = output->initial_x; crtc->desiredY = output->initial_y; + crtc->desiredTransformPresent = FALSE; crtc->enabled = TRUE; crtc->x = output->initial_x; crtc->y = output->initial_y; + memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); output->crtc = crtc; } else { output->crtc = NULL; @@ -2217,6 +2374,68 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) } /* + * Check the CRTC we're going to map each output to vs. it's current + * CRTC. If they don't match, we have to disable the output and the CRTC + * since the driver will have to re-route things. + */ +static void +xf86PrepareOutputs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; +#if RANDR_GET_CRTC_INTERFACE + /* Disable outputs that are unused or will be re-routed */ + if (!output->funcs->get_crtc || + output->crtc != (*output->funcs->get_crtc)(output) || + output->crtc == NULL) +#endif + (*output->funcs->dpms)(output, DPMSModeOff); + } +} + +static void +xf86PrepareCrtcs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { +#if RANDR_GET_CRTC_INTERFACE + xf86CrtcPtr crtc = config->crtc[c]; + xf86OutputPtr output = NULL; + uint32_t desired_outputs = 0, current_outputs = 0; + int o; + + for (o = 0; o < config->num_output; o++) { + output = config->output[o]; + if (output->crtc == crtc) + desired_outputs |= (1<<o); + /* If we can't tell where it's mapped, force it off */ + if (!output->funcs->get_crtc) { + desired_outputs = 0; + break; + } + if ((*output->funcs->get_crtc)(output) == crtc) + current_outputs |= (1<<o); + } + + /* + * If mappings are different or the CRTC is unused, + * we need to disable it + */ + if (desired_outputs != current_outputs || + !desired_outputs) + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#else + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#endif + } +} + +/* * Using the desired mode information in each crtc, set * modes (used in EnterVT functions, or at server startup) */ @@ -2225,31 +2444,22 @@ _X_EXPORT Bool xf86SetDesiredModes (ScrnInfoPtr scrn) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; + xf86CrtcPtr crtc = config->crtc[0]; + int c; - /* - * Turn off everything so mode setting is done - * with hardware in a consistent state - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - (*output->funcs->dpms)(output, DPMSModeOff); + /* A driver with this hook will take care of this */ + if (!crtc->funcs->set_mode_major) { + xf86PrepareOutputs(scrn); + xf86PrepareCrtcs(scrn); } - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->mode, 0, sizeof(crtc->mode)); - } - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; xf86OutputPtr output = NULL; int o; + RRTransformPtr transform; + + crtc = config->crtc[c]; /* Skip disabled CRTCs */ if (!crtc->enabled) @@ -2280,12 +2490,17 @@ xf86SetDesiredModes (ScrnInfoPtr scrn) return FALSE; crtc->desiredMode = *mode; crtc->desiredRotation = RR_Rotate_0; + crtc->desiredTransformPresent = FALSE; crtc->desiredX = 0; crtc->desiredY = 0; } - if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, - crtc->desiredX, crtc->desiredY)) + if (crtc->desiredTransformPresent) + transform = &crtc->desiredTransform; + else + transform = NULL; + if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, + transform, crtc->desiredX, crtc->desiredY)) return FALSE; } @@ -2414,18 +2629,19 @@ xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) crtc->enabled = FALSE; continue; } - if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0)) + if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) ok = FALSE; else { crtc->desiredMode = *crtc_mode; crtc->desiredRotation = rotation; + crtc->desiredTransformPresent = FALSE; crtc->desiredX = 0; crtc->desiredY = 0; } } xf86DisableUnusedFunctions(pScrn); -#if RANDR_12_INTERFACE +#ifdef RANDR_12_INTERFACE xf86RandR12TellChanged (pScrn->pScreen); #endif return ok; @@ -2513,8 +2729,11 @@ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) { crtc->funcs->dpms(crtc, DPMSModeOff); memset(&crtc->mode, 0, sizeof(crtc->mode)); + xf86RotateDestroy(crtc); } } + if (pScrn->pScreen) + xf86_crtc_notify(pScrn->pScreen); } #ifdef RANDR_12_INTERFACE @@ -2576,9 +2795,11 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) size = 0; if (edid_mon) { - if (edid_mon->ver.version == 1) + if (edid_mon->ver.version == 1) { size = 128; - else if (edid_mon->ver.version == 2) + if (edid_mon->flags & EDID_COMPLETE_RAWDATA) + size += edid_mon->no_sections * 128; + } else if (edid_mon->ver.version == 2) size = 256; } xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); @@ -2623,15 +2844,16 @@ xf86OutputGetEDIDModes (xf86OutputPtr output) return xf86DDCGetModes(scrn->scrnIndex, edid_mon); } +/* maybe we should care about DDC1? meh. */ _X_EXPORT xf86MonPtr xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) { ScrnInfoPtr scrn = output->scrn; xf86MonPtr mon; - mon = xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus); + mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); if (mon) - xf86DDCApplyQuirks (scrn->scrnIndex, mon); + xf86DDCApplyQuirks(scrn->scrnIndex, mon); return mon; } @@ -2766,3 +2988,41 @@ xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, return ret; } + +xf86_crtc_notify_proc_ptr +xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86_crtc_notify_proc_ptr old; + + old = config->xf86_crtc_notify; + config->xf86_crtc_notify = new; + return old; + } + return NULL; +} + +void +xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->xf86_crtc_notify = old; + } +} + +void +xf86_crtc_notify(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + if (config->xf86_crtc_notify) + config->xf86_crtc_notify(screen); +} diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.h b/xorg-server/hw/xfree86/modes/xf86Crtc.h index cc045b229..0a596bc49 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.h +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.h @@ -213,10 +213,24 @@ typedef struct _xf86CrtcFuncs { Bool (*set_mode_major)(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y); + + /** + * Callback for panning. Doesn't change the mode. + */ + void + (*set_origin)(xf86CrtcPtr crtc, int x, int y); + } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr; +#define XF86_CRTC_VERSION 2 + struct _xf86Crtc { /** + * ABI versioning + */ + int version; + + /** * Associated ScrnInfo */ ScrnInfoPtr scrn; @@ -298,12 +312,35 @@ struct _xf86Crtc { * Current transformation matrix */ PictTransform crtc_to_framebuffer; - PictTransform framebuffer_to_crtc; + struct pict_f_transform f_crtc_to_framebuffer; + struct pict_f_transform f_framebuffer_to_crtc; + PictFilterPtr filter; + xFixed *params; + int nparams; + int filter_width; + int filter_height; Bool transform_in_use; + RRTransformRec transform; + Bool transformPresent; + RRTransformRec desiredTransform; + Bool desiredTransformPresent; /** * Bounding box in screen space */ BoxRec bounds; + /** + * Panning: + * TotalArea: total panning area, larger than CRTC's size + * TrackingArea: Area of the pointer for which the CRTC is panned + * border: Borders of the displayed CRTC area which induces panning if the pointer reaches them + */ + BoxRec panningTotalArea; + BoxRec panningTrackingArea; + INT16 panningBorder[4]; + /** + * Clear the shadow + */ + Bool shadowClear; }; typedef struct _xf86OutputFuncs { @@ -410,6 +447,21 @@ typedef struct _xf86OutputFuncs { Atom property, RRPropertyValuePtr value); #endif +#ifdef RANDR_13_INTERFACE + /** + * Callback to get an updated property value + */ + Bool + (*get_property)(xf86OutputPtr output, + Atom property); +#endif +#ifdef RANDR_GET_CRTC_INTERFACE + /** + * Callback to get current CRTC for a given output + */ + xf86CrtcPtr + (*get_crtc)(xf86OutputPtr output); +#endif /** * Clean up driver-specific bits of the output */ @@ -417,8 +469,16 @@ typedef struct _xf86OutputFuncs { (*destroy) (xf86OutputPtr output); } xf86OutputFuncsRec, *xf86OutputFuncsPtr; + +#define XF86_OUTPUT_VERSION 2 + struct _xf86Output { /** + * ABI versioning + */ + int version; + + /** * Associated ScrnInfo */ ScrnInfoPtr scrn; @@ -518,6 +578,10 @@ struct _xf86Output { #else void *randr_output; #endif + /** Desired initial panning */ + BoxRec initialTotalArea; + BoxRec initialTrackingArea; + INT16 initialBorder[4]; }; typedef struct _xf86CrtcConfigFuncs { @@ -539,6 +603,8 @@ typedef struct _xf86CrtcConfigFuncs { int height); } xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr; +typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen); + typedef struct _xf86CrtcConfig { int num_output; xf86OutputPtr *output; @@ -591,6 +657,9 @@ typedef struct _xf86CrtcConfig { /* wrap screen BlockHandler for rotation */ ScreenBlockHandlerProcPtr BlockHandler; + /* callback when crtc configuration changes */ + xf86_crtc_notify_proc_ptr xf86_crtc_notify; + } xf86CrtcConfigRec, *xf86CrtcConfigPtr; extern int xf86CrtcConfigPrivateIndex; @@ -624,15 +693,36 @@ xf86CrtcDestroy (xf86CrtcPtr crtc); /** * Sets the given video mode on the given crtc */ + +Bool +xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + RRTransformPtr transform, int x, int y); + Bool xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y); +void +xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y); + /* * Assign crtc rotation during mode set */ Bool -xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation); +xf86CrtcRotate (xf86CrtcPtr crtc); + +/* + * Clean up any rotation data, used when a crtc is turned off + * as well as when rotation is disabled. + */ +void +xf86RotateDestroy (xf86CrtcPtr crtc); + +/* + * free shadow memory allocated for all crtcs + */ +void +xf86RotateFreeShadow(ScrnInfoPtr pScrn); /* * Clean up rotation during CloseScreen @@ -669,7 +759,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY); void xf86SetScrnInfoModes (ScrnInfoPtr pScrn); +#ifdef RANDR_13_INTERFACE +int +#else Bool +#endif xf86CrtcScreenInit (ScreenPtr pScreen); Bool @@ -798,4 +892,28 @@ xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, INT32 width, INT32 height); +xf86_crtc_notify_proc_ptr +xf86_wrap_crtc_notify (ScreenPtr pScreen, xf86_crtc_notify_proc_ptr new); + +void +xf86_unwrap_crtc_notify(ScreenPtr pScreen, xf86_crtc_notify_proc_ptr old); + +void +xf86_crtc_notify(ScreenPtr pScreen); + +/** + * Panning + */ +Bool +xf86_crtc_get_panning(ScrnInfoPtr pScrn, + BoxPtr totalArea, + BoxPtr TrackingArea, + INT16 *border); + +Bool +xf86_crtc_set_panning(ScrnInfoPtr pScrn, + BoxPtr totalArea, + BoxPtr TrackingArea, + INT16 *border); + #endif /* _XF86CRTC_H_ */ diff --git a/xorg-server/hw/xfree86/modes/xf86Cursors.c b/xorg-server/hw/xfree86/modes/xf86Cursors.c index fee02df38..3106f051b 100644 --- a/xorg-server/hw/xfree86/modes/xf86Cursors.c +++ b/xorg-server/hw/xfree86/modes/xf86Cursors.c @@ -37,6 +37,7 @@ #include "xf86Crtc.h" #include "xf86Modes.h" #include "xf86RandR12.h" +#include "xf86CursorPriv.h" #include "X11/extensions/render.h" #define DPMS_SERVER #include "X11/extensions/dpms.h" @@ -45,6 +46,7 @@ #include "picturestr.h" #endif #include "cursorstr.h" +#include "inputstr.h" /* * Given a screen coordinate, rotate back to a cursor source coordinate @@ -227,8 +229,13 @@ xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); CursorPtr cursor = xf86_config->cursor; int c; - CARD8 *bits = cursor ? dixLookupPrivate(&cursor->devPrivates, - screen) : NULL; + CARD8 *bits = cursor ? +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen)) +#else + cursor->devPriv[screen->myNum] +#endif + : NULL; /* Save ARGB versions of these colors */ xf86_config->cursor_fg = (CARD32) fg | 0xff000000; @@ -315,25 +322,31 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) */ if (crtc->transform_in_use) { - PictVector v; - v.vector[0] = IntToxFixed (x); v.vector[1] = IntToxFixed (y); v.vector[2] = IntToxFixed(1); - PictureTransformPoint (&crtc->framebuffer_to_crtc, &v); - x = xFixedToInt (v.vector[0]); y = xFixedToInt (v.vector[1]); - } + ScreenPtr screen = scrn->pScreen; + xf86CursorScreenPtr ScreenPriv = + (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates, + xf86CursorScreenKey); + struct pict_f_vector v; + + v.v[0] = x + ScreenPriv->HotX; v.v[1] = y + ScreenPriv->HotY; v.v[2] = 1; + pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v); + x = floor (v.v[0] + 0.5); + y = floor (v.v[1] + 0.5); + /* + * Transform position of cursor upper left corner + */ + xf86_crtc_rotate_coord_back (crtc->rotation, + cursor_info->MaxWidth, + cursor_info->MaxHeight, + ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy); + x -= dx; + y -= dy; + } else { x -= crtc->x; y -= crtc->y; } - /* - * Transform position of cursor upper left corner - */ - xf86_crtc_rotate_coord_back (crtc->rotation, - cursor_info->MaxWidth, - cursor_info->MaxHeight, - 0, 0, &dx, &dy); - x -= dx; - y -= dy; /* * Disable the cursor when it is outside the viewport @@ -589,10 +602,19 @@ xf86_reload_cursors (ScreenPtr screen) xf86CursorInfoPtr cursor_info; CursorPtr cursor; int x, y; + xf86CursorScreenPtr cursor_screen_priv; - /* initial mode setting will not have set a screen yet */ - if (!screen) + /* initial mode setting will not have set a screen yet. + May be called before the devices are initialised. + */ + if (!screen || !inputInfo.pointer) + return; + cursor_screen_priv = dixLookupPrivate(&screen->devPrivates, + xf86CursorScreenKey); + /* return if HW cursor is inactive, to avoid displaying two cursors */ + if (!cursor_screen_priv->isUp) return; + scrn = xf86Screens[screen->myNum]; xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -600,16 +622,16 @@ xf86_reload_cursors (ScreenPtr screen) cursor_info = xf86_config->cursor_info; if (!cursor_info) return; - + cursor = xf86_config->cursor; - GetSpritePosition (&x, &y); + GetSpritePosition (inputInfo.pointer, &x, &y); if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) (*cursor_info->HideCursor)(scrn); if (cursor) { #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - void *src = dixLookupPrivate(&cursor->devPrivates, screen); + void *src = dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen)); #else void *src = cursor->devPriv[screen->myNum]; #endif @@ -621,7 +643,6 @@ xf86_reload_cursors (ScreenPtr screen) (*cursor_info->LoadCursorImage)(cursor_info->pScrn, src); (*cursor_info->SetCursorPosition)(cursor_info->pScrn, x, y); - (*cursor_info->ShowCursor)(cursor_info->pScrn); } } diff --git a/xorg-server/hw/xfree86/modes/xf86EdidModes.c b/xorg-server/hw/xfree86/modes/xf86EdidModes.c index bf0ea3f64..087f66376 100644 --- a/xorg-server/hw/xfree86/modes/xf86EdidModes.c +++ b/xorg-server/hw/xfree86/modes/xf86EdidModes.c @@ -1,5 +1,6 @@ /* * Copyright 2006 Luc Verhaegen. + * Copyright 2008 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -34,16 +35,39 @@ #endif #endif +#define _PARSE_EDID_ #include "xf86.h" #include "xf86DDC.h" #include <X11/Xatom.h> #include "property.h" #include "propertyst.h" -#include "xf86DDC.h" #include "xf86Crtc.h" #include <string.h> #include <math.h> +static Bool +xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) +{ + /* EDID 1.4 explicitly defines RB support */ + if (DDC->ver.revision >= 4) { + int i; + for (i = 0; i < DET_TIMINGS; i++) { + struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; + if (det_mon->type == DS_RANGES) + if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) + return TRUE; + } + + return FALSE; + } + + /* For anything older, assume digital means RB support. Boo. */ + if (DDC->features.input_type) + return TRUE; + + return FALSE; +} + /* * Quirks to work around broken EDID data from various monitors. */ @@ -68,6 +92,8 @@ typedef enum { DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6, /* use +hsync +vsync for detailed mode */ DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7, + /* Force single-link DVI bandwidth limit */ + DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8, } ddc_quirk_t; static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) @@ -129,6 +155,11 @@ static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC) DDC->vendor.prod_id == 13600) return TRUE; + /* Bug #21000: LGPhilipsLCD LP154W01-TLAJ */ + if (memcmp (DDC->vendor.name, "LPL", 4) == 0 && + DDC->vendor.prod_id == 47360) + return TRUE; + return FALSE; } @@ -139,6 +170,11 @@ static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC) (DDC->vendor.prod_id == 0 || DDC->vendor.prod_id == 0x2a00)) return TRUE; + /* Bug #21324: Iiyama Vision Master 450 */ + if (memcmp (DDC->vendor.name, "IVM", 4) == 0 && + DDC->vendor.prod_id == 6400) + return TRUE; + return FALSE; } @@ -181,6 +217,16 @@ static Bool quirk_detailed_sync_pp(int scrnIndex, xf86MonPtr DDC) return FALSE; } +/* This should probably be made more generic */ +static Bool quirk_dvi_single_link(int scrnIndex, xf86MonPtr DDC) +{ + /* Red Hat bug #453106: Apple 23" Cinema Display */ + if (memcmp (DDC->vendor.name, "APL", 4) == 0 && + DDC->vendor.prod_id == 0x921c) + return TRUE; + return FALSE; +} + typedef struct { Bool (*detect) (int scrnIndex, xf86MonPtr DDC); ddc_quirk_t quirk; @@ -220,6 +266,10 @@ static const ddc_quirk_map_t ddc_quirks[] = { quirk_detailed_sync_pp, DDC_QUIRK_DETAILED_SYNC_PP, "Use +hsync +vsync for detailed timing." }, + { + quirk_dvi_single_link, DDC_QUIRK_DVI_SINGLE_LINK, + "Forcing maximum pixel clock to single DVI link." + }, { NULL, DDC_QUIRK_NONE, "No known quirks" @@ -227,8 +277,13 @@ static const ddc_quirk_map_t ddc_quirks[] = { }; /* - * TODO: - * - for those with access to the VESA DMT standard; review please. + * These more or less come from the DMT spec. The 720x400 modes are + * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75 + * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode + * should be 1152x870, again for the Mac, but instead we use the x864 DMT + * mode. + * + * The DMT modes have been fact-checked; the rest are mild guesses. */ #define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER #define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 @@ -237,16 +292,16 @@ static const DisplayModeRec DDCEstablishedModes[17] = { { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ - { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ + { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ { MODEPREFIX, 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */ - { MODEPREFIX, 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ { MODEPREFIX, 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */ { MODEPREFIX, 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */ { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ - { MODEPREFIX, 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ + { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ - { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */ + { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */ { MODEPREFIX, 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */ { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ @@ -272,6 +327,90 @@ DDCModesFromEstablished(int scrnIndex, struct established_timings *timing, return Modes; } +/* Autogenerated from the DMT spec */ +static const DisplayModeRec DMTModes[] = { + { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */ + { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */ + { MODEPREFIX, 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */ + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ + { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ + { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ + { MODEPREFIX, 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@85Hz */ + { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ + { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ + { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ + { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ + { MODEPREFIX, 56250, 800, 832, 896, 1048, 0, 600, 601, 604, 631, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@85Hz */ + { MODEPREFIX, 73250, 800, 848, 880, 960, 0, 600, 603, 607, 636, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 800x600@120Hz RB */ + { MODEPREFIX, 33750, 848, 864, 976, 1088, 0, 480, 486, 494, 517, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 848x480@60Hz */ + { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz (interlaced) */ + { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ + { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ + { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ + { MODEPREFIX, 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@85Hz */ + { MODEPREFIX, 115500, 1024, 1072, 1104, 1184, 0, 768, 771, 775, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@120Hz RB */ + { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ + { MODEPREFIX, 68250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 790, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@60Hz RB */ + { MODEPREFIX, 79500, 1280, 1344, 1472, 1664, 0, 768, 771, 778, 798, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@60Hz */ + { MODEPREFIX, 102250, 1280, 1360, 1488, 1696, 0, 768, 771, 778, 805, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@75Hz */ + { MODEPREFIX, 117500, 1280, 1360, 1496, 1712, 0, 768, 771, 778, 809, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@85Hz */ + { MODEPREFIX, 140250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@120Hz RB */ + { MODEPREFIX, 71000, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 823, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@60Hz RB */ + { MODEPREFIX, 83500, 1280, 1352, 1480, 1680, 0, 800, 803, 809, 831, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@60Hz */ + { MODEPREFIX, 106500, 1280, 1360, 1488, 1696, 0, 800, 803, 809, 838, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@75Hz */ + { MODEPREFIX, 122500, 1280, 1360, 1496, 1712, 0, 800, 803, 809, 843, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@85Hz */ + { MODEPREFIX, 146250, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 847, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@120Hz RB */ + { MODEPREFIX, 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@60Hz */ + { MODEPREFIX, 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@85Hz */ + { MODEPREFIX, 175500, 1280, 1328, 1360, 1440, 0, 960, 963, 967, 1017, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x960@120Hz RB */ + { MODEPREFIX, 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@60Hz */ + { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ + { MODEPREFIX, 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@85Hz */ + { MODEPREFIX, 187250, 1280, 1328, 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x1024@120Hz RB */ + { MODEPREFIX, 85500, 1360, 1424, 1536, 1792, 0, 768, 771, 777, 795, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1360x768@60Hz */ + { MODEPREFIX, 148250, 1360, 1408, 1440, 1520, 0, 768, 771, 776, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1360x768@120Hz RB */ + { MODEPREFIX, 101000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@60Hz RB */ + { MODEPREFIX, 121750, 1400, 1488, 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@60Hz */ + { MODEPREFIX, 156000, 1400, 1504, 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@75Hz */ + { MODEPREFIX, 179500, 1400, 1504, 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@85Hz */ + { MODEPREFIX, 208000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@120Hz RB */ + { MODEPREFIX, 88750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 926, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@60Hz RB */ + { MODEPREFIX, 106500, 1440, 1520, 1672, 1904, 0, 900, 903, 909, 934, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@60Hz */ + { MODEPREFIX, 136750, 1440, 1536, 1688, 1936, 0, 900, 903, 909, 942, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@75Hz */ + { MODEPREFIX, 157000, 1440, 1544, 1696, 1952, 0, 900, 903, 909, 948, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@85Hz */ + { MODEPREFIX, 182750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 953, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@120Hz RB */ + { MODEPREFIX, 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@60Hz */ + { MODEPREFIX, 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@65Hz */ + { MODEPREFIX, 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@70Hz */ + { MODEPREFIX, 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@75Hz */ + { MODEPREFIX, 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@85Hz */ + { MODEPREFIX, 268250, 1600, 1648, 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1600x1200@120Hz RB */ + { MODEPREFIX, 119000, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@60Hz RB */ + { MODEPREFIX, 146250, 1680, 1784, 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@60Hz */ + { MODEPREFIX, 187000, 1680, 1800, 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@75Hz */ + { MODEPREFIX, 214750, 1680, 1808, 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@85Hz */ + { MODEPREFIX, 245500, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@120Hz RB */ + { MODEPREFIX, 204750, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@60Hz */ + { MODEPREFIX, 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@75Hz */ + { MODEPREFIX, 333250, 1792, 1840, 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1792x1344@120Hz RB */ + { MODEPREFIX, 218250, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@60Hz */ + { MODEPREFIX, 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@75Hz */ + { MODEPREFIX, 356500, 1856, 1904, 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1856x1392@120Hz RB */ + { MODEPREFIX, 154000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@60Hz RB */ + { MODEPREFIX, 193250, 1920, 2056, 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@60Hz */ + { MODEPREFIX, 245250, 1920, 2056, 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@75Hz */ + { MODEPREFIX, 281250, 1920, 2064, 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@85Hz */ + { MODEPREFIX, 317000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@120Hz RB */ + { MODEPREFIX, 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@60Hz */ + { MODEPREFIX, 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@75Hz */ + { MODEPREFIX, 380500, 1920, 1968, 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1440@120Hz RB */ + { MODEPREFIX, 268500, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@60Hz RB */ + { MODEPREFIX, 348500, 2560, 2752, 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@60Hz */ + { MODEPREFIX, 443250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@75Hz */ + { MODEPREFIX, 505250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@85Hz */ + { MODEPREFIX, 552750, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@120Hz RB */ +}; + #define LEVEL_DMT 0 #define LEVEL_GTF 1 #define LEVEL_CVT 2 @@ -288,12 +427,43 @@ MonitorStandardTimingLevel(xf86MonPtr DDC) return LEVEL_DMT; } +static int +ModeRefresh(const DisplayModeRec *mode) +{ + return (int)(xf86ModeVRefresh(mode) + 0.5); +} + /* - * This is not really correct. Appendix B of the EDID 1.4 spec defines - * the right thing to do here. If the timing given here matches a mode - * defined in the VESA DMT standard, we _must_ use that. If the device - * supports CVT modes, then we should generate a CVT timing. If both - * of the above fail, use GTF. + * If rb is not set, then we'll not consider reduced-blanking modes as + * part of the DMT pool. For the 'standard' EDID mode descriptor there's + * no way to specify whether the mode should be RB or not. + */ +static DisplayModePtr +FindDMTMode(int hsize, int vsize, int refresh, Bool rb) +{ + int i; + const DisplayModeRec *ret; + + for (i = 0; i < sizeof(DMTModes) / sizeof(DisplayModeRec); i++) { + ret = &DMTModes[i]; + + if (!rb && xf86ModeIsReduced(ret)) + continue; + + if (ret->HDisplay == hsize && + ret->VDisplay == vsize && + refresh == ModeRefresh(ret)) + return xf86DuplicateMode(ret); + } + + return NULL; +} + +/* + * Appendix B of the EDID 1.4 spec defines the right thing to do here. + * If the timing given here matches a mode defined in the VESA DMT standard, + * we _must_ use that. If the device supports CVT modes, then we should + * generate a CVT timing. If both of the above fail, use GTF. * * There are some wrinkles here. EDID 1.1 and 1.0 sinks can't really * "support" GTF, since it wasn't a standard yet; so if they ask for a @@ -308,20 +478,28 @@ MonitorStandardTimingLevel(xf86MonPtr DDC) */ static DisplayModePtr DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks, - int timing_level) + int timing_level, Bool rb) { DisplayModePtr Modes = NULL, Mode = NULL; int i; for (i = 0; i < STD_TIMINGS; i++) { if (timing[i].hsize && timing[i].vsize && timing[i].refresh) { - /* XXX check for DMT first, else... */ - if (timing_level == LEVEL_CVT) - Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize, - timing[i].refresh, FALSE, FALSE); - else - Mode = xf86GTFMode(timing[i].hsize, timing[i].vsize, - timing[i].refresh, FALSE, FALSE); + Mode = FindDMTMode(timing[i].hsize, timing[i].vsize, + timing[i].refresh, rb); + + if (!Mode) { + if (timing_level == LEVEL_CVT) + /* pass rb here too? */ + Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize, + timing[i].refresh, FALSE, FALSE); + else if (timing_level == LEVEL_GTF) + Mode = xf86GTFMode(timing[i].hsize, timing[i].vsize, + timing[i].refresh, FALSE, FALSE); + } + + if (!Mode) + continue; Mode->type = M_T_DRIVER; Modes = xf86ModesAdd(Modes, Mode); @@ -363,7 +541,7 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, /* We only do seperate sync currently */ if (timing->sync != 0x03) { xf86DrvMsg(scrnIndex, X_INFO, - "%s: %dx%d Warning: We only handle seperate" + "%s: %dx%d Warning: We only handle separate" " sync.\n", __func__, timing->h_active, timing->v_active); } @@ -419,6 +597,7 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, return Mode; } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) static DisplayModePtr DDCModesFromCVT(int scrnIndex, struct cvt_timings *t) { @@ -447,7 +626,87 @@ DDCModesFromCVT(int scrnIndex, struct cvt_timings *t) return modes; } +#endif + +static const struct { + short w; + short h; + short r; + short rb; +} EstIIIModes[] = { + /* byte 6 */ + { 640, 350, 85, 0 }, + { 640, 400, 85, 0 }, + { 720, 400, 85, 0 }, + { 640, 480, 85, 0 }, + { 848, 480, 60, 0 }, + { 800, 600, 85, 0 }, + { 1024, 768, 85, 0 }, + { 1152, 864, 75, 0 }, + /* byte 7 */ + { 1280, 768, 60, 1 }, + { 1280, 768, 60, 0 }, + { 1280, 768, 75, 0 }, + { 1280, 768, 85, 0 }, + { 1280, 960, 60, 0 }, + { 1280, 960, 85, 0 }, + { 1280, 1024, 60, 0 }, + { 1280, 1024, 85, 0 }, + /* byte 8 */ + { 1360, 768, 60, 0 }, + { 1440, 900, 60, 1 }, + { 1440, 900, 60, 0 }, + { 1440, 900, 75, 0 }, + { 1440, 900, 85, 0 }, + { 1400, 1050, 60, 1 }, + { 1400, 1050, 60, 0 }, + { 1400, 1050, 75, 0 }, + /* byte 9 */ + { 1400, 1050, 85, 0 }, + { 1680, 1050, 60, 1 }, + { 1680, 1050, 60, 0 }, + { 1680, 1050, 75, 0 }, + { 1680, 1050, 85, 0 }, + { 1600, 1200, 60, 0 }, + { 1600, 1200, 65, 0 }, + { 1600, 1200, 70, 0 }, + /* byte 10 */ + { 1600, 1200, 75, 0 }, + { 1600, 1200, 85, 0 }, + { 1792, 1344, 60, 0 }, + { 1792, 1344, 85, 0 }, + { 1856, 1392, 60, 0 }, + { 1856, 1392, 75, 0 }, + { 1920, 1200, 60, 1 }, + { 1920, 1200, 60, 0 }, + /* byte 11 */ + { 1920, 1200, 75, 0 }, + { 1920, 1200, 85, 0 }, + { 1920, 1440, 60, 0 }, + { 1920, 1440, 75, 0 }, +}; + +static DisplayModePtr +DDCModesFromEstIII(unsigned char *est) +{ + DisplayModePtr modes = NULL; + int i, j, m; + + for (i = 0; i < 6; i++) { + for (j = 7; j > 0; j--) { + if (est[i] & (1 << j)) { + m = (i * 8) + (7 - j); + modes = xf86ModesAdd(modes, + FindDMTMode(EstIIIModes[m].w, + EstIIIModes[m].h, + EstIIIModes[m].r, + EstIIIModes[m].rb)); + } + } + } + return modes; +} /* * This is only valid when the sink claims to be continuous-frequency @@ -595,7 +854,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) int i; DisplayModePtr Modes = NULL, Mode; ddc_quirk_t quirks; - Bool preferred; + Bool preferred, rb; int timing_level; xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n", @@ -611,11 +870,14 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75)) preferred = FALSE; + rb = xf86MonitorSupportsReducedBlanking(DDC); + timing_level = MonitorStandardTimingLevel(DDC); for (i = 0; i < DET_TIMINGS; i++) { struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; + Mode = NULL; switch (det_mon->type) { case DT: Mode = DDCModeFromDetailedTiming(scrnIndex, @@ -623,20 +885,23 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) preferred, quirks); preferred = FALSE; - Modes = xf86ModesAdd(Modes, Mode); break; case DS_STD_TIMINGS: Mode = DDCModesFromStandardTiming(det_mon->section.std_t, - quirks, timing_level); - Modes = xf86ModesAdd(Modes, Mode); + quirks, timing_level, rb); break; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) case DS_CVT: Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt); - Modes = xf86ModesAdd(Modes, Mode); + break; +#endif + case DS_EST_III: + Mode = DDCModesFromEstIII(det_mon->section.est_iii); break; default: break; } + Modes = xf86ModesAdd(Modes, Mode); } /* Add established timings */ @@ -644,7 +909,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) Modes = xf86ModesAdd(Modes, Mode); /* Add standard timings */ - Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level); + Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb); Modes = xf86ModesAdd(Modes, Mode); if (quirks & DDC_QUIRK_PREFER_LARGE_60) @@ -665,23 +930,21 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) DisplayModePtr Modes = NULL, Mode; int i, clock; Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE; + ddc_quirk_t quirks; if (!Monitor || !DDC) return; Monitor->DDC = DDC; + quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE); + if (Monitor->widthmm <= 0 && Monitor->heightmm <= 0) { Monitor->widthmm = 10 * DDC->features.hsize; Monitor->heightmm = 10 * DDC->features.vsize; } - /* - * If this is a digital display, then we can use reduced blanking. - * XXX This is a 1.3 heuristic. 1.4 explicitly defines rb support. - */ - if (DDC->features.input_type) - Monitor->reducedblanking = TRUE; + Monitor->reducedblanking = xf86MonitorSupportsReducedBlanking(DDC); Modes = xf86DDCGetModes(scrnIndex, DDC); @@ -723,6 +986,8 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) } clock = DDC->det_mon[i].section.ranges.max_clock * 1000; + if (quirks & DDC_QUIRK_DVI_SINGLE_LINK) + clock = min(clock, 165000); if (!have_maxpixclock && clock > Monitor->maxPixClock) Monitor->maxPixClock = clock; diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.c b/xorg-server/hw/xfree86/modes/xf86Modes.c index ea398ad81..1522fa731 100644 --- a/xorg-server/hw/xfree86/modes/xf86Modes.c +++ b/xorg-server/hw/xfree86/modes/xf86Modes.c @@ -52,7 +52,7 @@ extern XF86ConfigPtr xf86configptr; * Exact copy of xf86Mode.c's. */ _X_EXPORT double -xf86ModeHSync(DisplayModePtr mode) +xf86ModeHSync(const DisplayModeRec *mode) { double hsync = 0.0; @@ -70,7 +70,7 @@ xf86ModeHSync(DisplayModePtr mode) * Exact copy of xf86Mode.c's. */ _X_EXPORT double -xf86ModeVRefresh(DisplayModePtr mode) +xf86ModeVRefresh(const DisplayModeRec *mode) { double refresh = 0.0; @@ -89,7 +89,7 @@ xf86ModeVRefresh(DisplayModePtr mode) } _X_EXPORT int -xf86ModeWidth (DisplayModePtr mode, Rotation rotation) +xf86ModeWidth (const DisplayModeRec *mode, Rotation rotation) { switch (rotation & 0xf) { case RR_Rotate_0: @@ -104,7 +104,7 @@ xf86ModeWidth (DisplayModePtr mode, Rotation rotation) } _X_EXPORT int -xf86ModeHeight (DisplayModePtr mode, Rotation rotation) +xf86ModeHeight (const DisplayModeRec *mode, Rotation rotation) { switch (rotation & 0xf) { case RR_Rotate_0: @@ -206,7 +206,7 @@ xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) * Allocates and returns a copy of pMode, including pointers within pMode. */ _X_EXPORT DisplayModePtr -xf86DuplicateMode(DisplayModePtr pMode) +xf86DuplicateMode(const DisplayModeRec *pMode) { DisplayModePtr pNew; @@ -264,7 +264,7 @@ xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) * This isn't in xf86Modes.c, but it might deserve to be there. */ _X_EXPORT Bool -xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2) +xf86ModesEqual(const DisplayModeRec *pMode1, const DisplayModeRec *pMode2) { if (pMode1->Clock == pMode2->Clock && pMode1->HDisplay == pMode2->HDisplay && @@ -509,10 +509,27 @@ xf86ValidateModesBandwidth(ScrnInfoPtr pScrn, DisplayModePtr modeList, for (mode = modeList; mode != NULL; mode = mode->next) { if (xf86ModeBandwidth(mode, depth) > bandwidth) +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) mode->status = MODE_BANDWIDTH; +#else + /* MODE_BANDWIDTH didn't exist in xserver 1.2 */ + mode->status = MODE_BAD; +#endif } } +Bool +xf86ModeIsReduced(const DisplayModeRec *mode) +{ + if ((((mode->HDisplay * 5 / 4) & ~0x07) > mode->HTotal) && + ((mode->HTotal - mode->HDisplay) == 160) && + ((mode->HSyncEnd - mode->HDisplay) == 80) && + ((mode->HSyncEnd - mode->HSyncStart) == 32) && + ((mode->VSyncStart - mode->VDisplay) == 3)) + return TRUE; + return FALSE; +} + /** * Marks as bad any reduced-blanking modes. * @@ -521,7 +538,6 @@ xf86ValidateModesBandwidth(ScrnInfoPtr pScrn, DisplayModePtr modeList, _X_EXPORT void xf86ValidateModesReducedBlanking(ScrnInfoPtr pScrn, DisplayModePtr modeList) { - Bool mode_is_reduced = FALSE; DisplayModePtr mode; for (mode = modeList; mode != NULL; mode = mode->next) { @@ -677,12 +693,12 @@ xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) _X_EXPORT DisplayModePtr xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed) { - DisplayModePtr head = NULL, prev = NULL, mode; + DisplayModePtr head = NULL, mode; int i; for (i = 0; i < xf86NumDefaultModes; i++) { - DisplayModePtr defMode = &xf86DefaultModes[i]; + const DisplayModeRec *defMode = &xf86DefaultModes[i]; if (!interlaceAllowed && (defMode->Flags & V_INTERLACE)) continue; diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.h b/xorg-server/hw/xfree86/modes/xf86Modes.h index acdea65d8..2fb6a374d 100644 --- a/xorg-server/hw/xfree86/modes/xf86Modes.h +++ b/xorg-server/hw/xfree86/modes/xf86Modes.h @@ -40,22 +40,23 @@ #include "xf86Rename.h" #endif -double xf86ModeHSync(DisplayModePtr mode); -double xf86ModeVRefresh(DisplayModePtr mode); +double xf86ModeHSync(const DisplayModeRec *mode); +double xf86ModeVRefresh(const DisplayModeRec *mode); unsigned int xf86ModeBandwidth(DisplayModePtr mode, int depth); int -xf86ModeWidth (DisplayModePtr mode, Rotation rotation); +xf86ModeWidth (const DisplayModeRec *mode, Rotation rotation); int -xf86ModeHeight (DisplayModePtr mode, Rotation rotation); +xf86ModeHeight (const DisplayModeRec *mode, Rotation rotation); -DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode); +DisplayModePtr xf86DuplicateMode(const DisplayModeRec *pMode); DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList); void xf86SetModeDefaultName(DisplayModePtr mode); void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); -Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); +Bool xf86ModesEqual(const DisplayModeRec *pMode1, + const DisplayModeRec *pMode2); void xf86PrintModeline(int scrnIndex,DisplayModePtr mode); DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); @@ -64,6 +65,9 @@ DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, Bool Interlaced); DisplayModePtr xf86GTFMode(int h_pixels, int v_lines, float freq, int interlaced, int margins); +Bool +xf86ModeIsReduced(const DisplayModeRec *mode); + void xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, int flags); diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.c b/xorg-server/hw/xfree86/modes/xf86RandR12.c index 6f8ccdf84..454649213 100644 --- a/xorg-server/hw/xfree86/modes/xf86RandR12.c +++ b/xorg-server/hw/xfree86/modes/xf86RandR12.c @@ -37,6 +37,7 @@ #include "xf86DDC.h" #include "mipointer.h" #include "windowstr.h" +#include "inputstr.h" #include <randrstr.h> #include <X11/extensions/render.h> @@ -50,6 +51,8 @@ typedef struct _xf86RandR12Info { int mmHeight; int maxX; int maxY; + int pointerX; + int pointerY; Rotation rotation; /* current mode */ Rotation supported_rotations; /* driver supported */ } XF86RandRInfoRec, *XF86RandRInfoPtr; @@ -60,11 +63,22 @@ static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen); #endif static int xf86RandR12Generation; -static DevPrivateKey xf86RandR12Key; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) +static int xf86RandR12KeyIndex; +static DevPrivateKey xf86RandR12Key; #define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \ dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key)) +#else /* XORG_VERSION_CURRENT < 7.0 */ + +static int xf86RandR12Index; +#define XF86RANDRINFO(p) \ + ((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr) + +#endif /* XORG_VERSION_CURRENT < 7.0 */ + + static int xf86RandR12ModeRefresh (DisplayModePtr mode) { @@ -74,6 +88,355 @@ xf86RandR12ModeRefresh (DisplayModePtr mode) return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); } +/* Adapt panning area; return TRUE if panning area was valid without adaption */ +static int +xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight) +{ + int ret = TRUE; + + if (crtc->version < 2) + return FALSE; + + if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) { + /* Panning in X is disabled */ + if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2) + /* Illegal configuration -> fail/disable */ + ret = FALSE; + crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0; + crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0; + crtc->panningBorder[0] = crtc->panningBorder[2] = 0; + } else { + /* Panning in X is enabled */ + if (crtc->panningTotalArea.x1 < 0) { + /* Panning region outside screen -> move inside */ + crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1; + crtc->panningTotalArea.x1 = 0; + ret = FALSE; + } + if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) { + /* Panning region smaller than displayed area -> crop to displayed area */ + crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay; + ret = FALSE; + } + if (crtc->panningTotalArea.x2 > screenWidth) { + /* Panning region larger than screen -> move inside, then crop to screen */ + crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth; + crtc->panningTotalArea.x2 = screenWidth; + ret = FALSE; + if (crtc->panningTotalArea.x1 < 0) + crtc->panningTotalArea.x1 = 0; + } + if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) { + /* Borders too large -> set to 0 */ + crtc->panningBorder[0] = crtc->panningBorder[2] = 0; + ret = FALSE; + } + } + + if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) { + /* Panning in Y is disabled */ + if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2) + /* Illegal configuration -> fail/disable */ + ret = FALSE; + crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0; + crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0; + crtc->panningBorder[1] = crtc->panningBorder[3] = 0; + } else { + /* Panning in Y is enabled */ + if (crtc->panningTotalArea.y1 < 0) { + /* Panning region outside screen -> move inside */ + crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1; + crtc->panningTotalArea.y1 = 0; + ret = FALSE; + } + if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) { + /* Panning region smaller than displayed area -> crop to displayed area */ + crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay; + ret = FALSE; + } + if (crtc->panningTotalArea.y2 > screenHeight) { + /* Panning region larger than screen -> move inside, then crop to screen */ + crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight; + crtc->panningTotalArea.y2 = screenHeight; + ret = FALSE; + if (crtc->panningTotalArea.y1 < 0) + crtc->panningTotalArea.y1 = 0; + } + if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) { + /* Borders too large -> set to 0 */ + crtc->panningBorder[1] = crtc->panningBorder[3] = 0; + ret = FALSE; + } + } + + return ret; +} + +/* + * The heart of the panning operation: + * + * Given a frame buffer position (fb_x, fb_y), + * and a crtc position (crtc_x, crtc_y), + * and a transform matrix which maps frame buffer to crtc, + * compute a panning position (pan_x, pan_y) that + * makes the resulting transform line those two up + */ + +static void +xf86ComputeCrtcPan (Bool transform_in_use, + struct pixman_f_transform *m, + double screen_x, double screen_y, + double crtc_x, double crtc_y, + int old_pan_x, int old_pan_y, + int *new_pan_x, int *new_pan_y) +{ + if (transform_in_use) { + /* + * Given the current transform, M, the current position + * on the Screen, S, and the desired position on the CRTC, + * C, compute a translation, T, such that: + * + * M T S = C + * + * where T is of the form + * + * | 1 0 dx | + * | 0 1 dy | + * | 0 0 1 | + * + * M T S = + * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F | + * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F | + * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F | + * + * R = M S + * + * Cx F = M00 dx + M01 dy + R0 + * Cy F = M10 dx + M11 dy + R1 + * F = M20 dx + M21 dy + R2 + * + * Zero out dx, then dy + * + * F (Cx M10 - Cy M00) = + * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1 + * F (M10 - Cy M20) = + * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1 + * + * F (Cx M11 - Cy M01) = + * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1 + * F (M11 - Cy M21) = + * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1 + * + * Make some temporaries + * + * T = | Cx M10 - Cy M00 | + * | Cx M11 - Cy M01 | + * + * U = | M10 M01 - M00 M11 | + * | M11 M00 - M01 M10 | + * + * Q = | M10 R0 - M00 R1 | + * | M11 R0 - M01 R1 | + * + * P = | M10 - Cy M20 | + * | M11 - Cy M21 | + * + * W = | M10 M21 - M20 M11 | + * | M11 M20 - M21 M10 | + * + * V = | M10 R2 - M20 R1 | + * | M11 R2 - M21 R1 | + * + * Rewrite: + * + * F T0 = U0 dy + Q0 + * F P0 = W0 dy + V0 + * F T1 = U1 dx + Q1 + * F P1 = W1 dx + V1 + * + * Solve for F (two ways) + * + * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0 + * + * W0 Q0 - U0 V0 + * F = ------------- + * W0 T0 - U0 P0 + * + * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1 + * + * W1 Q1 - U1 V1 + * F = ------------- + * W1 T1 - U1 P1 + * + * We'll use which ever solution works (denominator != 0) + * + * Finally, solve for dx and dy: + * + * dx = (F T1 - Q1) / U1 + * dx = (F P1 - V1) / W1 + * + * dy = (F T0 - Q0) / U0 + * dy = (F P0 - V0) / W0 + */ + double r[3]; + double q[2], u[2], t[2], v[2], w[2], p[2]; + double f; + struct pict_f_vector d; + int i; + + /* Get the un-normalized crtc coordinates again */ + for (i = 0; i < 3; i++) + r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2]; + + /* Combine values into temporaries */ + for (i = 0; i < 2; i++) { + q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1]; + u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i]; + t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y; + + v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1]; + w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i]; + p[i] = m->m[1][i] - m->m[2][i] * crtc_y; + } + + /* Find a way to compute f */ + f = 0; + for (i = 0; i < 2; i++) { + double a = w[i] * q[i] - u[i] * v[i]; + double b = w[i] * t[i] - u[i] * p[i]; + if (b != 0) { + f = a/b; + break; + } + } + + /* Solve for the resulting transform vector */ + for (i = 0; i < 2; i++) { + if (u[i]) + d.v[1-i] = (t[i] * f - q[i]) / u[i]; + else if (w[1]) + d.v[1-i] = (p[i] * f - v[i]) / w[i]; + else + d.v[1-i] = 0; + } + *new_pan_x = old_pan_x - floor (d.v[0] + 0.5); + *new_pan_y = old_pan_y - floor (d.v[1] + 0.5); + } else { + *new_pan_x = screen_x - crtc_x; + *new_pan_y = screen_y - crtc_y; + } +} + +static void +xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) +{ + int newX, newY; + int width, height; + Bool panned = FALSE; + + if (crtc->version < 2) + return; + + if (! crtc->enabled || + (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 && + crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)) + return; + + newX = crtc->x; + newY = crtc->y; + width = crtc->mode.HDisplay; + height = crtc->mode.VDisplay; + + if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 || + (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) && + (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 || + (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) + { + struct pict_f_vector c; + + /* + * Pre-clip the mouse position to the panning area so that we don't + * push the crtc outside. This doesn't deal with changes to the + * panning values, only mouse position changes. + */ + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) + { + if (x < crtc->panningTotalArea.x1) + x = crtc->panningTotalArea.x1; + if (x >= crtc->panningTotalArea.x2) + x = crtc->panningTotalArea.x2 - 1; + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) + { + if (y < crtc->panningTotalArea.y1) + y = crtc->panningTotalArea.y1; + if (y >= crtc->panningTotalArea.y2) + y = crtc->panningTotalArea.y2 - 1; + } + + c.v[0] = x; + c.v[1] = y; + c.v[2] = 1.0; + if (crtc->transform_in_use) { + pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); + } else { + c.v[0] -= crtc->x; + c.v[1] -= crtc->y; + } + + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { + if (c.v[0] < crtc->panningBorder[0]) { + c.v[0] = crtc->panningBorder[0]; + panned = TRUE; + } + if (c.v[0] >= width - crtc->panningBorder[2]) { + c.v[0] = width - crtc->panningBorder[2] - 1; + panned = TRUE; + } + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (c.v[1] < crtc->panningBorder[1]) { + c.v[1] = crtc->panningBorder[1]; + panned = TRUE; + } + if (c.v[1] >= height - crtc->panningBorder[3]) { + c.v[1] = height - crtc->panningBorder[3] - 1; + panned = TRUE; + } + } + if (panned) + xf86ComputeCrtcPan (crtc->transform_in_use, + &crtc->f_framebuffer_to_crtc, + x, y, c.v[0], c.v[1], + newX, newY, &newX, &newY); + } + + /* + * Ensure that the crtc is within the panning region. + * + * XXX This computation only works when we do not have a transform + * in use. + */ + if (!crtc->transform_in_use) + { + /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { + if (newX > crtc->panningTotalArea.x2 - width) + newX = crtc->panningTotalArea.x2 - width; + if (newX < crtc->panningTotalArea.x1) + newX = crtc->panningTotalArea.x1; + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (newY > crtc->panningTotalArea.y2 - height) + newY = crtc->panningTotalArea.y2 - height; + if (newY < crtc->panningTotalArea.y1) + newY = crtc->panningTotalArea.y1; + } + } + if (newX != crtc->x || newY != crtc->y) + xf86CrtcSetOrigin (crtc, newX, newY); +} + static Bool xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) { @@ -247,7 +610,7 @@ xf86RandR12SetConfig (ScreenPtr pScreen, randrp->virtualY = scrp->virtualY; } - miPointerPosition (&px, &py); + miPointerGetPosition (inputInfo.pointer, &px, &py); for (mode = scrp->modes; ; mode = mode->next) { if (randrp->maxX == 0 || randrp->maxY == 0) @@ -294,14 +657,14 @@ xf86RandR12SetConfig (ScreenPtr pScreen, /* * Move the cursor back where it belongs; SwitchMode repositions it */ - if (pScreen == miPointerCurrentScreen ()) + if (pScreen == miPointerGetScreen(inputInfo.pointer)) { px = (px >= pScreen->width ? (pScreen->width - 1) : px); py = (py >= pScreen->height ? (pScreen->height - 1) : py); xf86SetViewport(pScreen, px, py); - (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE); + (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); } return TRUE; @@ -320,14 +683,19 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen, WindowPtr pRoot = WindowTable[pScreen->myNum]; PixmapPtr pScrnPix = (*pScreen->GetScreenPixmap)(pScreen); Bool ret = FALSE; + int c; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) if (xf86RandR12Key) { +#endif if (randrp->virtualX == -1 || randrp->virtualY == -1) { randrp->virtualX = pScrn->virtualX; randrp->virtualY = pScrn->virtualY; } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) } +#endif if (pRoot && pScrn->vtSema) (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); @@ -336,6 +704,23 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen, goto finish; ret = TRUE; + /* Update panning information */ + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 || + crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1) + crtc->panningTotalArea.x2 += width - pScreen->width; + if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1) + crtc->panningTotalArea.y2 += height - pScreen->height; + if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1) + crtc->panningTrackingArea.x2 += width - pScreen->width; + if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1) + crtc->panningTrackingArea.y2 += height - pScreen->height; + xf86RandR13VerifyPanningArea (crtc, width, height); + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + } + } pScreen->width = pScrnPix->drawable.width = width; pScreen->height = pScrnPix->drawable.height = height; @@ -367,8 +752,8 @@ _X_EXPORT Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + xf86CrtcConfigPtr config; + XF86RandRInfoPtr randrp; int c; int width, height; int mmWidth, mmHeight; @@ -378,6 +763,8 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen) return TRUE; #endif + config = XF86_CRTC_CONFIG_PTR(pScrn); + randrp = XF86RANDRINFO(pScreen); /* * Compute size of screen */ @@ -388,10 +775,16 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen) int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); - if (crtc->enabled && crtc_width > width) - width = crtc_width; - if (crtc->enabled && crtc_height > height) - height = crtc_height; + if (crtc->enabled) { + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + if (crtc->panningTotalArea.x2 > width) + width = crtc->panningTotalArea.x2; + if (crtc->panningTotalArea.y2 > height) + height = crtc->panningTotalArea.y2; + } } if (width && height) @@ -442,6 +835,13 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting screen physical size to %d x %d\n", mmWidth, mmHeight); + /* + * This is the initial setting of the screen size. + * We have to pre-set it here, otherwise panning would be adapted + * to the new screen size. + */ + pScreen->width = width; + pScreen->height = height; xf86RandR12ScreenSetSize (pScreen, width, height, @@ -449,8 +849,10 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen) mmHeight); } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) if (xf86RandR12Key == NULL) return TRUE; +#endif if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -481,7 +883,11 @@ xf86RandR12Init (ScreenPtr pScreen) if (xf86RandR12Generation != serverGeneration) xf86RandR12Generation = serverGeneration; - xf86RandR12Key = &xf86RandR12Key; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + xf86RandR12Key = &xf86RandR12KeyIndex; +#else + xf86RandR12Index = AllocateScreenPrivateIndex(); +#endif randrp = xalloc (sizeof (XF86RandRInfoRec)); if (!randrp) @@ -507,7 +913,11 @@ xf86RandR12Init (ScreenPtr pScreen) randrp->maxX = randrp->maxY = 0; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); +#else + pScreen->devPrivates[xf86RandR12Index].ptr = randrp; +#endif #if RANDR_12_INTERFACE if (!xf86RandR12Init12 (pScreen)) @@ -526,8 +936,10 @@ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); #endif +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) if (xf86RandR12Key == NULL) return; +#endif randrp = XF86RANDRINFO(pScreen); #if RANDR_12_INTERFACE @@ -541,6 +953,31 @@ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) } _X_EXPORT void +xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms) +{ + XF86RandRInfoPtr randrp; +#if RANDR_13_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int c; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +#endif + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key == NULL) + return; +#endif + + randrp = XF86RANDRINFO(pScreen); +#if RANDR_13_INTERFACE + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcSetTransformSupport (crtc->randr_crtc, transforms); + } +#endif +} + +_X_EXPORT void xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) { ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; @@ -662,7 +1099,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) } } ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, - rotation, numOutputs, randr_outputs); + rotation, + crtc->transformPresent ? &crtc->transform : NULL, + numOutputs, randr_outputs); xfree(randr_outputs); return ret; } @@ -698,18 +1137,20 @@ xf86RandRModeConvert (ScrnInfoPtr scrn, } static Bool -xf86RandR12CrtcSet (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - RRModePtr randr_mode, - int x, - int y, - Rotation rotation, - int num_randr_outputs, - RROutputPtr *randr_outputs) +xf86RandR12CrtcSet (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + RRModePtr randr_mode, + int x, + int y, + Rotation rotation, + int num_randr_outputs, + RROutputPtr *randr_outputs) { + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc = randr_crtc->devPrivate; + RRTransformPtr transform; Bool changed = FALSE; int o, ro; xf86CrtcPtr *save_crtcs; @@ -727,6 +1168,13 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, if (rotation != crtc->rotation) changed = TRUE; + transform = RRCrtcGetTransform (randr_crtc); + if ((transform != NULL) != crtc->transformPresent) + changed = TRUE; + else if (transform && memcmp (&transform->transform, &crtc->transform.transform, + sizeof (transform->transform)) != 0) + changed = TRUE; + if (x != crtc->x || y != crtc->y) changed = TRUE; for (o = 0; o < config->num_output; o++) @@ -764,9 +1212,10 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, if (randr_mode) { DisplayModeRec mode; + RRTransformPtr transform = RRCrtcGetTransform (randr_crtc); xf86RandRModeConvert (pScrn, randr_mode, &mode); - if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y)) + if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y)) { crtc->enabled = save_enabled; for (o = 0; o < config->num_output; o++) @@ -777,11 +1226,19 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, xfree(save_crtcs); return FALSE; } + xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height); + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); /* * Save the last successful setting for EnterVT */ crtc->desiredMode = mode; crtc->desiredRotation = rotation; + if (transform) { + crtc->desiredTransform = *transform; + crtc->desiredTransformPresent = TRUE; + } else + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = x; crtc->desiredY = y; } @@ -832,6 +1289,20 @@ xf86RandR12OutputSetProperty (ScreenPtr pScreen, } static Bool +xf86RandR13OutputGetProperty (ScreenPtr pScreen, + RROutputPtr randr_output, + Atom property) +{ + xf86OutputPtr output = randr_output->devPrivate; + + if (output->funcs->get_property == NULL) + return TRUE; + + /* Should be safe even w/o vtSema */ + return output->funcs->get_property(output, property); +} + +static Bool xf86RandR12OutputValidateMode (ScreenPtr pScreen, RROutputPtr randr_output, RRModePtr randr_mode) @@ -1060,8 +1531,10 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) if (xf86RandR12Key == NULL) return TRUE; +#endif for (c = 0; c < config->num_crtc; c++) xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); @@ -1083,8 +1556,13 @@ xf86RandR12TellChanged (ScreenPtr pScreen) xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); int c; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) if (xf86RandR12Key == NULL) return; +#else + if (!XF86RANDRINFO(pScreen)) + return; +#endif xf86RandR12SetInfo12 (pScreen); for (c = 0; c < config->num_crtc; c++) @@ -1096,6 +1574,77 @@ xf86RandR12TellChanged (ScreenPtr pScreen) static void xf86RandR12PointerMoved (int scrnIndex, int x, int y) { + ScreenPtr pScreen = screenInfo.screens[scrnIndex]; + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; + + randrp->pointerX = x; + randrp->pointerY = y; + for (c = 0; c < config->num_crtc; c++) + xf86RandR13Pan (config->crtc[c], x, y); +} + +static Bool +xf86RandR13GetPanning (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->version < 2) + return FALSE; + if (totalArea) + memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec)); + if (trackingArea) + memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); + if (border) + memcpy (border, crtc->panningBorder, 4*sizeof(INT16)); + + return TRUE; +} + +static Bool +xf86RandR13SetPanning (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + xf86CrtcPtr crtc = randr_crtc->devPrivate; + BoxRec oldTotalArea; + BoxRec oldTrackingArea; + INT16 oldBorder[4]; + + + if (crtc->version < 2) + return FALSE; + + memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec)); + memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); + memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16)); + + if (totalArea) + memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec)); + if (trackingArea) + memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec)); + if (border) + memcpy (crtc->panningBorder, border, 4*sizeof(INT16)); + + if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) { + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + return TRUE; + } else { + /* Restore old settings */ + memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16)); + return FALSE; + } } static Bool @@ -1110,6 +1659,11 @@ xf86RandR12Init12 (ScreenPtr pScreen) rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; rp->rrOutputValidateMode = xf86RandR12OutputValidateMode; +#if RANDR_13_INTERFACE + rp->rrOutputGetProperty = xf86RandR13OutputGetProperty; + rp->rrGetPanning = xf86RandR13GetPanning; + rp->rrSetPanning = xf86RandR13SetPanning; +#endif rp->rrModeDestroy = xf86RandR12ModeDestroy; rp->rrSetConfig = NULL; pScrn->PointerMoved = xf86RandR12PointerMoved; diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.h b/xorg-server/hw/xfree86/modes/xf86RandR12.h index 4fd855cf5..17a2dcc7f 100644 --- a/xorg-server/hw/xfree86/modes/xf86RandR12.h +++ b/xorg-server/hw/xfree86/modes/xf86RandR12.h @@ -31,6 +31,7 @@ Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen); Bool xf86RandR12Init(ScreenPtr pScreen); void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation); +void xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms); Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); Rotation xf86RandR12GetRotation(ScreenPtr pScreen); diff --git a/xorg-server/hw/xfree86/modes/xf86Rename.h b/xorg-server/hw/xfree86/modes/xf86Rename.h index b8c1d70ef..e3418caad 100644 --- a/xorg-server/hw/xfree86/modes/xf86Rename.h +++ b/xorg-server/hw/xfree86/modes/xf86Rename.h @@ -38,6 +38,7 @@ #define xf86CrtcInUse XF86NAME(xf86CrtcInUse) #define xf86CrtcRotate XF86NAME(xf86CrtcRotate) #define xf86CrtcScreenInit XF86NAME(xf86CrtcScreenInit) +#define xf86CrtcSetModeTransform XF86NAME(xf86CrtcSetModeTransform) #define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode) #define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange) #define xf86CVTMode XF86NAME(xf86CVTMode) diff --git a/xorg-server/hw/xfree86/modes/xf86Rotate.c b/xorg-server/hw/xfree86/modes/xf86Rotate.c index e2d6295b9..6be77d556 100644 --- a/xorg-server/hw/xfree86/modes/xf86Rotate.c +++ b/xorg-server/hw/xfree86/modes/xf86Rotate.c @@ -70,205 +70,9 @@ compWindowFormat (WindowPtr pWin) #define F(x) IntToxFixed(x) -static void -PictureTransformIdentity (PictTransformPtr matrix) -{ - int i; - memset (matrix, '\0', sizeof (PictTransform)); - for (i = 0; i < 3; i++) - matrix->matrix[i][i] = F(1); -} - -static Bool -PictureTransformMultiply (PictTransformPtr dst, PictTransformPtr l, PictTransformPtr r) -{ - PictTransform d; - int dx, dy; - int o; - - for (dy = 0; dy < 3; dy++) - for (dx = 0; dx < 3; dx++) - { - xFixed_48_16 v; - xFixed_32_32 partial; - v = 0; - for (o = 0; o < 3; o++) - { - partial = (xFixed_32_32) l->matrix[dy][o] * (xFixed_32_32) r->matrix[o][dx]; - v += partial >> 16; - } - if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) - return FALSE; - d.matrix[dy][dx] = (xFixed) v; - } - *dst = d; - return TRUE; -} - -static void -PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy) -{ - memset (t, '\0', sizeof (PictTransform)); - t->matrix[0][0] = sx; - t->matrix[1][1] = sy; - t->matrix[2][2] = F (1); -} - -static xFixed -fixed_inverse (xFixed x) -{ - return (xFixed) ((((xFixed_48_16) F(1)) * F(1)) / x); -} - -static Bool -PictureTransformScale (PictTransformPtr forward, - PictTransformPtr reverse, - xFixed sx, xFixed sy) -{ - PictTransform t; - - PictureTransformInitScale (&t, sx, sy); - if (!PictureTransformMultiply (forward, &t, forward)) - return FALSE; - PictureTransformInitScale (&t, fixed_inverse (sx), fixed_inverse (sy)); - if (!PictureTransformMultiply (reverse, reverse, &t)) - return FALSE; - return TRUE; -} - -static void -PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s) -{ - memset (t, '\0', sizeof (PictTransform)); - t->matrix[0][0] = c; - t->matrix[0][1] = -s; - t->matrix[1][0] = s; - t->matrix[1][1] = c; - t->matrix[2][2] = F (1); -} - -static Bool -PictureTransformRotate (PictTransformPtr forward, - PictTransformPtr reverse, - xFixed c, xFixed s) -{ - PictTransform t; - PictureTransformInitRotate (&t, c, s); - if (!PictureTransformMultiply (forward, &t, forward)) - return FALSE; - - PictureTransformInitRotate (&t, c, -s); - if (!PictureTransformMultiply (reverse, reverse, &t)) - return FALSE; - return TRUE; -} - -static void -PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty) -{ - memset (t, '\0', sizeof (PictTransform)); - t->matrix[0][0] = F (1); - t->matrix[0][2] = tx; - t->matrix[1][1] = F (1); - t->matrix[1][2] = ty; - t->matrix[2][2] = F (1); -} - -static Bool -PictureTransformTranslate (PictTransformPtr forward, - PictTransformPtr reverse, - xFixed tx, xFixed ty) -{ - PictTransform t; - PictureTransformInitTranslate (&t, tx, ty); - if (!PictureTransformMultiply (forward, &t, forward)) - return FALSE; - - PictureTransformInitTranslate (&t, -tx, -ty); - if (!PictureTransformMultiply (reverse, reverse, &t)) - return FALSE; - return TRUE; -} - -static void -PictureTransformBounds (BoxPtr b, PictTransformPtr matrix) -{ - PictVector v[4]; - int i; - int x1, y1, x2, y2; - - v[0].vector[0] = F (b->x1); v[0].vector[1] = F (b->y1); v[0].vector[2] = F(1); - v[1].vector[0] = F (b->x2); v[1].vector[1] = F (b->y1); v[1].vector[2] = F(1); - v[2].vector[0] = F (b->x2); v[2].vector[1] = F (b->y2); v[2].vector[2] = F(1); - v[3].vector[0] = F (b->x1); v[3].vector[1] = F (b->y2); v[3].vector[2] = F(1); - for (i = 0; i < 4; i++) - { - PictureTransformPoint (matrix, &v[i]); - x1 = xFixedToInt (v[i].vector[0]); - y1 = xFixedToInt (v[i].vector[1]); - x2 = xFixedToInt (xFixedCeil (v[i].vector[0])); - y2 = xFixedToInt (xFixedCeil (v[i].vector[1])); - if (i == 0) - { - b->x1 = x1; b->y1 = y1; - b->x2 = x2; b->y2 = y2; - } - else - { - if (x1 < b->x1) b->x1 = x1; - if (y1 < b->y1) b->y1 = y1; - if (x2 > b->x2) b->x2 = x2; - if (y2 > b->y2) b->y2 = y2; - } - } -} - -static Bool -PictureTransformIsIdentity(PictTransform *t) -{ - return ((t->matrix[0][0] == t->matrix[1][1]) && - (t->matrix[0][0] == t->matrix[2][2]) && - (t->matrix[0][0] != 0) && - (t->matrix[0][1] == 0) && - (t->matrix[0][2] == 0) && - (t->matrix[1][0] == 0) && - (t->matrix[1][2] == 0) && - (t->matrix[2][0] == 0) && - (t->matrix[2][1] == 0)); -} - #define toF(x) ((float) (x) / 65536.0f) static void -PictureTransformErrorF (PictTransform *t) -{ - ErrorF ("{ { %f %f %f } { %f %f %f } { %f %f %f } }", - toF(t->matrix[0][0]), toF(t->matrix[0][1]), toF(t->matrix[0][2]), - toF(t->matrix[1][0]), toF(t->matrix[1][1]), toF(t->matrix[1][2]), - toF(t->matrix[2][0]), toF(t->matrix[2][1]), toF(t->matrix[2][2])); -} - -static Bool -PictureTransformIsInverse (char *where, PictTransform *a, PictTransform *b) -{ - PictTransform t; - - PictureTransformMultiply (&t, a, b); - if (!PictureTransformIsIdentity (&t)) - { - ErrorF ("%s: ", where); - PictureTransformErrorF (a); - ErrorF (" * "); - PictureTransformErrorF (b); - ErrorF (" = "); - PictureTransformErrorF (a); - ErrorF ("\n"); - return FALSE; - } - return TRUE; -} - -static void xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) { ScrnInfoPtr scrn = crtc->scrn; @@ -305,19 +109,37 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) error = SetPictureTransform (src, &crtc->crtc_to_framebuffer); if (error) return; + if (crtc->transform_in_use && crtc->filter) + SetPicturePictFilter (src, crtc->filter, + crtc->params, crtc->nparams); - while (n--) + if (crtc->shadowClear) { - BoxRec dst_box; - - dst_box = *b; - PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc); CompositePicture (PictOpSrc, src, NULL, dst, - dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, - dst_box.x2 - dst_box.x1, - dst_box.y2 - dst_box.y1); - b++; + 0, 0, 0, 0, 0, 0, + crtc->mode.HDisplay, crtc->mode.VDisplay); + crtc->shadowClear = FALSE; + } + else + { + while (n--) + { + BoxRec dst_box; + + dst_box = *b; + dst_box.x1 -= crtc->filter_width >> 1; + dst_box.x2 += crtc->filter_width >> 1; + dst_box.y1 -= crtc->filter_height >> 1; + dst_box.y2 += crtc->filter_height >> 1; + pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box); + CompositePicture (PictOpSrc, + src, NULL, dst, + dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, + dst_box.x2 - dst_box.x1, + dst_box.y2 - dst_box.y1); + b++; + } } FreePicture (src, None); FreePicture (dst, None); @@ -331,14 +153,26 @@ xf86CrtcDamageShadow (xf86CrtcPtr crtc) RegionRec damage_region; ScreenPtr pScreen = pScrn->pScreen; - damage_box.x1 = crtc->x; - damage_box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); - damage_box.y1 = crtc->y; - damage_box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); + damage_box.x1 = 0; + damage_box.x2 = crtc->mode.HDisplay; + damage_box.y1 = 0; + damage_box.y2 = crtc->mode.VDisplay; + if (!pixman_transform_bounds (&crtc->crtc_to_framebuffer, &damage_box)) + { + damage_box.x1 = 0; + damage_box.y1 = 0; + damage_box.x2 = pScreen->width; + damage_box.y2 = pScreen->height; + } + if (damage_box.x1 < 0) damage_box.x1 = 0; + if (damage_box.y1 < 0) damage_box.y1 = 0; + if (damage_box.x2 > pScreen->width) damage_box.x2 = pScreen->width; + if (damage_box.y2 > pScreen->height) damage_box.y2 = pScreen->height; REGION_INIT (pScreen, &damage_region, &damage_box, 1); - DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + DamageRegionAppend (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, &damage_region); REGION_UNINIT (pScreen, &damage_region); + crtc->shadowClear = TRUE; } static void @@ -401,7 +235,7 @@ xf86RotateRedisplay(ScreenPtr pScreen) { xf86CrtcPtr crtc = xf86_config->crtc[c]; - if (crtc->rotation != RR_Rotate_0 && crtc->enabled) + if (crtc->transform_in_use && crtc->enabled) { RegionRec crtc_damage; @@ -437,10 +271,12 @@ xf86RotateBlockHandler(int screenNum, pointer blockData, /* Re-wrap if rotation is still happening */ xf86_config->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = xf86RotateBlockHandler; + } else { + xf86_config->BlockHandler = NULL; } } -static void +void xf86RotateDestroy (xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; @@ -457,8 +293,7 @@ xf86RotateDestroy (xf86CrtcPtr crtc) } for (c = 0; c < xf86_config->num_crtc; c++) - if (xf86_config->crtc[c]->rotatedPixmap || - xf86_config->crtc[c]->rotatedData) + if (xf86_config->crtc[c]->transform_in_use) return; /* @@ -479,6 +314,24 @@ xf86RotateDestroy (xf86CrtcPtr crtc) } _X_EXPORT void +xf86RotateFreeShadow(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + if (crtc->rotatedPixmap || crtc->rotatedData) { + crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, + crtc->rotatedData); + crtc->rotatedPixmap = NULL; + crtc->rotatedData = NULL; + } + } +} + +_X_EXPORT void xf86RotateCloseScreen (ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; @@ -489,112 +342,93 @@ xf86RotateCloseScreen (ScreenPtr screen) xf86RotateDestroy (xf86_config->crtc[c]); } +static Bool +xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb) +{ + ScrnInfoPtr pScrn = crtc->scrn; + BoxRec b; + + /* When called before PreInit, the driver is + * presumably doing load detect + */ + if (pScrn->virtualX == 0 || pScrn->virtualY == 0) + return TRUE; + + b.x1 = 0; + b.y1 = 0; + b.x2 = crtc->mode.HDisplay; + b.y2 = crtc->mode.VDisplay; + if (crtc_to_fb) + pixman_f_transform_bounds (crtc_to_fb, &b); + else { + b.x1 += crtc->x; + b.y1 += crtc->y; + b.x2 += crtc->x; + b.y2 += crtc->y; + } + + return (0 <= b.x1 && b.x2 <= pScrn->virtualX && + 0 <= b.y1 && b.y2 <= pScrn->virtualY); +} + _X_EXPORT Bool -xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) +xf86CrtcRotate (xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; - PictTransform crtc_to_fb, fb_to_crtc; - - PictureTransformIdentity (&crtc_to_fb); - PictureTransformIdentity (&fb_to_crtc); - PictureTransformIsInverse ("identity", &crtc_to_fb, &fb_to_crtc); - if (rotation != RR_Rotate_0) + PictTransform crtc_to_fb; + struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc; + xFixed *new_params = NULL; + int new_nparams = 0; + PictFilterPtr new_filter = NULL; + int new_width = 0; + int new_height = 0; + RRTransformPtr transform = NULL; + Bool damage = FALSE; + + if (crtc->transformPresent) + transform = &crtc->transform; + + if (!RRTransformCompute (crtc->x, crtc->y, + crtc->mode.HDisplay, crtc->mode.VDisplay, + crtc->rotation, + transform, + + &crtc_to_fb, + &f_crtc_to_fb, + &f_fb_to_crtc) && + xf86CrtcFitsScreen (crtc, &f_crtc_to_fb)) { - xFixed rot_cos, rot_sin, rot_dx, rot_dy; - xFixed scale_x, scale_y, scale_dx, scale_dy; - int mode_w = crtc->mode.HDisplay; - int mode_h = crtc->mode.VDisplay; - - /* rotation */ - switch (rotation & 0xf) { - default: - case RR_Rotate_0: - rot_cos = F ( 1); rot_sin = F ( 0); - rot_dx = F ( 0); rot_dy = F ( 0); - break; - case RR_Rotate_90: - rot_cos = F ( 0); rot_sin = F ( 1); - rot_dx = F ( mode_h); rot_dy = F (0); - break; - case RR_Rotate_180: - rot_cos = F (-1); rot_sin = F ( 0); - rot_dx = F (mode_w); rot_dy = F ( mode_h); - break; - case RR_Rotate_270: - rot_cos = F ( 0); rot_sin = F (-1); - rot_dx = F ( 0); rot_dy = F ( mode_w); - break; - } - - PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin); - PictureTransformIsInverse ("rotate", &crtc_to_fb, &fb_to_crtc); - - PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy); - PictureTransformIsInverse ("rotate translate", &crtc_to_fb, &fb_to_crtc); - - /* reflection */ - scale_x = F (1); - scale_dx = 0; - scale_y = F (1); - scale_dy = 0; - if (rotation & RR_Reflect_X) - { - scale_x = F(-1); - if (rotation & (RR_Rotate_0|RR_Rotate_180)) - scale_dx = F(mode_w); - else - scale_dx = F(mode_h); - } - if (rotation & RR_Reflect_Y) - { - scale_y = F(-1); - if (rotation & (RR_Rotate_0|RR_Rotate_180)) - scale_dy = F(mode_h); - else - scale_dy = F(mode_w); - } - - PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y); - PictureTransformIsInverse ("scale", &crtc_to_fb, &fb_to_crtc); - - PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy); - PictureTransformIsInverse ("scale translate", &crtc_to_fb, &fb_to_crtc); - - } - - /* - * If the untranslated transformation is the identity, - * disable the shadow buffer - */ - if (PictureTransformIsIdentity (&crtc_to_fb)) - { - crtc->transform_in_use = FALSE; - PictureTransformInitTranslate (&crtc->crtc_to_framebuffer, - F (-crtc->x), F (-crtc->y)); - PictureTransformInitTranslate (&crtc->framebuffer_to_crtc, - F ( crtc->x), F ( crtc->y)); + /* + * If the untranslated transformation is the identity, + * disable the shadow buffer + */ xf86RotateDestroy (crtc); + crtc->transform_in_use = FALSE; + if (new_params) + xfree (new_params); + new_params = NULL; + new_nparams = 0; + new_filter = NULL; + new_width = 0; + new_height = 0; } else { - PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, F(crtc->x), F(crtc->y)); - PictureTransformIsInverse ("offset", &crtc_to_fb, &fb_to_crtc); - - /* + /* * these are the size of the shadow pixmap, which * matches the mode, not the pre-rotated copy in the * frame buffer */ - int width = mode->HDisplay; - int height = mode->VDisplay; + int width = crtc->mode.HDisplay; + int height = crtc->mode.VDisplay; void *shadowData = crtc->rotatedData; PixmapPtr shadow = crtc->rotatedPixmap; int old_width = shadow ? shadow->drawable.width : 0; int old_height = shadow ? shadow->drawable.height : 0; - + /* Allocate memory for rotation */ if (old_width != width || old_height != height) { @@ -613,9 +447,9 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) else { /* mark shadowed area as damaged so it will be repainted */ - xf86CrtcDamageShadow (crtc); + damage = TRUE; } - + if (!xf86_config->rotation_damage) { /* Create damage structure */ @@ -626,9 +460,32 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) goto bail2; /* Wrap block handler */ - xf86_config->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = xf86RotateBlockHandler; + if (!xf86_config->BlockHandler) { + xf86_config->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = xf86RotateBlockHandler; + } } +#ifdef RANDR_12_INTERFACE + if (transform) + { + if (transform->nparams) { + new_params = xalloc (transform->nparams * sizeof (xFixed)); + if (new_params) { + memcpy (new_params, transform->params, + transform->nparams * sizeof (xFixed)); + new_nparams = transform->nparams; + new_filter = transform->filter; + } + } else + new_filter = transform->filter; + if (new_filter) + { + new_width = new_filter->width; + new_height = new_filter->height; + } + } +#endif + if (0) { bail2: @@ -647,15 +504,26 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) return FALSE; } crtc->transform_in_use = TRUE; - crtc->crtc_to_framebuffer = crtc_to_fb; - crtc->framebuffer_to_crtc = fb_to_crtc; - crtc->bounds.x1 = 0; - crtc->bounds.x2 = crtc->mode.HDisplay; - crtc->bounds.y1 = 0; - crtc->bounds.y2 = crtc->mode.VDisplay; - PictureTransformBounds (&crtc->bounds, &crtc_to_fb); } - + crtc->crtc_to_framebuffer = crtc_to_fb; + crtc->f_crtc_to_framebuffer = f_crtc_to_fb; + crtc->f_framebuffer_to_crtc = f_fb_to_crtc; + if (crtc->params) + xfree (crtc->params); + crtc->params = new_params; + crtc->nparams = new_nparams; + crtc->filter = new_filter; + crtc->filter_width = new_width; + crtc->filter_height = new_height; + crtc->bounds.x1 = 0; + crtc->bounds.x2 = crtc->mode.HDisplay; + crtc->bounds.y1 = 0; + crtc->bounds.y2 = crtc->mode.VDisplay; + pixman_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds); + + if (damage) + xf86CrtcDamageShadow (crtc); + /* All done */ return TRUE; } diff --git a/xorg-server/hw/xfree86/modes/xf86gtf.c b/xorg-server/hw/xfree86/modes/xf86gtf.c index acbac83b6..fed56bd12 100644 --- a/xorg-server/hw/xfree86/modes/xf86gtf.c +++ b/xorg-server/hw/xfree86/modes/xf86gtf.c @@ -62,6 +62,10 @@ #ifdef HAVE_XORG_CONFIG_H # include <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #endif #include "xf86.h" |