103b705cfSriastradh/************************************************************************** 203b705cfSriastradh 303b705cfSriastradhCopyright 2001 VA Linux Systems Inc., Fremont, California. 403b705cfSriastradhCopyright © 2002 by David Dawes 503b705cfSriastradh 603b705cfSriastradhAll Rights Reserved. 703b705cfSriastradh 803b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a 903b705cfSriastradhcopy of this software and associated documentation files (the "Software"), 1003b705cfSriastradhto deal in the Software without restriction, including without limitation 1103b705cfSriastradhon the rights to use, copy, modify, merge, publish, distribute, sub 1203b705cfSriastradhlicense, and/or sell copies of the Software, and to permit persons to whom 1303b705cfSriastradhthe Software is furnished to do so, subject to the following conditions: 1403b705cfSriastradh 1503b705cfSriastradhThe above copyright notice and this permission notice (including the next 1603b705cfSriastradhparagraph) shall be included in all copies or substantial portions of the 1703b705cfSriastradhSoftware. 1803b705cfSriastradh 1903b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2003b705cfSriastradhIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2103b705cfSriastradhFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 2203b705cfSriastradhTHE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 2303b705cfSriastradhDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2403b705cfSriastradhOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2503b705cfSriastradhUSE OR OTHER DEALINGS IN THE SOFTWARE. 2603b705cfSriastradh 2703b705cfSriastradh**************************************************************************/ 2803b705cfSriastradh 2903b705cfSriastradh/* 3003b705cfSriastradh * Authors: Jeff Hartmann <jhartmann@valinux.com> 3103b705cfSriastradh * Abraham van der Merwe <abraham@2d3d.co.za> 3203b705cfSriastradh * David Dawes <dawes@xfree86.org> 3303b705cfSriastradh * Alan Hourihane <alanh@tungstengraphics.com> 3403b705cfSriastradh */ 3503b705cfSriastradh 3603b705cfSriastradh#ifdef HAVE_CONFIG_H 3703b705cfSriastradh#include "config.h" 3803b705cfSriastradh#endif 3903b705cfSriastradh 4003b705cfSriastradh#include <string.h> 4103b705cfSriastradh#include <stdio.h> 4203b705cfSriastradh#include <unistd.h> 4303b705cfSriastradh#include <stdlib.h> 4403b705cfSriastradh#include <stdio.h> 4503b705cfSriastradh#include <errno.h> 4603b705cfSriastradh 4703b705cfSriastradh#include "sna.h" 4803b705cfSriastradh#include "sna_module.h" 4903b705cfSriastradh#include "sna_video.h" 5003b705cfSriastradh 5103b705cfSriastradh#include "intel_driver.h" 5203b705cfSriastradh#include "intel_options.h" 5303b705cfSriastradh 5442542f5fSchristos#include <xf86cmap.h> 5542542f5fSchristos#include <xf86drm.h> 5642542f5fSchristos#include <xf86RandR12.h> 5742542f5fSchristos#include <mi.h> 5842542f5fSchristos#include <micmap.h> 5942542f5fSchristos 6063ef14f0Smrg#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H) 6163ef14f0Smrg#include <X11/extensions/dpmsconst.h> 6263ef14f0Smrg#else 6363ef14f0Smrg#define DPMSModeOn 0 6463ef14f0Smrg#define DPMSModeOff 3 6563ef14f0Smrg#endif 6663ef14f0Smrg 6703b705cfSriastradh#include <sys/ioctl.h> 6803b705cfSriastradh#include <sys/fcntl.h> 6913496ba1Ssnj#include <sys/poll.h> 7003b705cfSriastradh#include "i915_drm.h" 7103b705cfSriastradh 7203b705cfSriastradh#ifdef HAVE_VALGRIND 7303b705cfSriastradh#include <valgrind.h> 7403b705cfSriastradh#include <memcheck.h> 7503b705cfSriastradh#endif 7603b705cfSriastradh 7703b705cfSriastradh#if HAVE_DOT_GIT 7803b705cfSriastradh#include "git_version.h" 7963ef14f0Smrg#else 8063ef14f0Smrg#define git_version "not compiled from git" 8103b705cfSriastradh#endif 8203b705cfSriastradh 8342542f5fSchristos#ifdef TEARFREE 8442542f5fSchristos#define ENABLE_TEAR_FREE TRUE 8542542f5fSchristos#else 8642542f5fSchristos#define ENABLE_TEAR_FREE FALSE 8742542f5fSchristos#endif 8842542f5fSchristos 8903b705cfSriastradhDevPrivateKeyRec sna_pixmap_key; 9003b705cfSriastradhDevPrivateKeyRec sna_gc_key; 9103b705cfSriastradhDevPrivateKeyRec sna_window_key; 9203b705cfSriastradhDevPrivateKeyRec sna_glyph_key; 9303b705cfSriastradhDevPrivateKeyRec sna_client_key; 9403b705cfSriastradh 9503b705cfSriastradhstatic void 9603b705cfSriastradhsna_load_palette(ScrnInfoPtr scrn, int numColors, int *indices, 9703b705cfSriastradh LOCO * colors, VisualPtr pVisual) 9803b705cfSriastradh{ 9903b705cfSriastradh xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 10042542f5fSchristos int p, n, i, j; 10103b705cfSriastradh uint16_t lut_r[256], lut_g[256], lut_b[256]; 10203b705cfSriastradh 10303b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 10403b705cfSriastradh 10503b705cfSriastradh for (p = 0; p < xf86_config->num_crtc; p++) { 10603b705cfSriastradh xf86CrtcPtr crtc = xf86_config->crtc[p]; 10703b705cfSriastradh 10842542f5fSchristos#define C(I,RGB) (colors[I].RGB << 8 | colors[I].RGB) 10903b705cfSriastradh switch (scrn->depth) { 11003b705cfSriastradh case 15: 11142542f5fSchristos for (n = 0; n < numColors; n++) { 11242542f5fSchristos i = indices[n]; 11303b705cfSriastradh for (j = 0; j < 8; j++) { 11442542f5fSchristos lut_r[8*i + j] = C(i, red); 11542542f5fSchristos lut_g[8*i + j] = C(i, green); 11642542f5fSchristos lut_b[8*i + j] = C(i, blue); 11703b705cfSriastradh } 11803b705cfSriastradh } 11903b705cfSriastradh break; 12003b705cfSriastradh case 16: 12142542f5fSchristos for (n = 0; n < numColors; n++) { 12242542f5fSchristos i = indices[n]; 12303b705cfSriastradh 12442542f5fSchristos if (i <= 31) { 12503b705cfSriastradh for (j = 0; j < 8; j++) { 12642542f5fSchristos lut_r[8*i + j] = C(i, red); 12742542f5fSchristos lut_b[8*i + j] = C(i, blue); 12803b705cfSriastradh } 12903b705cfSriastradh } 13003b705cfSriastradh 13142542f5fSchristos for (j = 0; j < 4; j++) 13242542f5fSchristos lut_g[4*i + j] = C(i, green); 13303b705cfSriastradh } 13403b705cfSriastradh break; 13503b705cfSriastradh default: 13642542f5fSchristos for (n = 0; n < numColors; n++) { 13742542f5fSchristos i = indices[n]; 13842542f5fSchristos lut_r[i] = C(i, red); 13942542f5fSchristos lut_g[i] = C(i, green); 14042542f5fSchristos lut_b[i] = C(i, blue); 14103b705cfSriastradh } 14203b705cfSriastradh break; 14303b705cfSriastradh } 14442542f5fSchristos#undef C 14503b705cfSriastradh 14603b705cfSriastradh /* Make the change through RandR */ 14703b705cfSriastradh#ifdef RANDR_12_INTERFACE 14803b705cfSriastradh RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 14903b705cfSriastradh#else 15003b705cfSriastradh crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 15103b705cfSriastradh#endif 15203b705cfSriastradh } 15303b705cfSriastradh} 15403b705cfSriastradh 15503b705cfSriastradhstatic void 15603b705cfSriastradhsna_set_fallback_mode(ScrnInfoPtr scrn) 15703b705cfSriastradh{ 15803b705cfSriastradh xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 15903b705cfSriastradh xf86OutputPtr output = NULL; 16003b705cfSriastradh xf86CrtcPtr crtc = NULL; 16103b705cfSriastradh int n; 16203b705cfSriastradh 16303b705cfSriastradh if ((unsigned)config->compat_output < config->num_output) { 16403b705cfSriastradh output = config->output[config->compat_output]; 16503b705cfSriastradh crtc = output->crtc; 16603b705cfSriastradh } 16703b705cfSriastradh 16803b705cfSriastradh for (n = 0; n < config->num_output; n++) 16903b705cfSriastradh config->output[n]->crtc = NULL; 17003b705cfSriastradh for (n = 0; n < config->num_crtc; n++) 17103b705cfSriastradh config->crtc[n]->enabled = FALSE; 17203b705cfSriastradh 17303b705cfSriastradh if (output && crtc) { 17403b705cfSriastradh DisplayModePtr mode; 17503b705cfSriastradh 17603b705cfSriastradh output->crtc = crtc; 17703b705cfSriastradh 17803b705cfSriastradh mode = xf86OutputFindClosestMode(output, scrn->currentMode); 17903b705cfSriastradh if (mode && 18003b705cfSriastradh xf86CrtcSetModeTransform(crtc, mode, RR_Rotate_0, NULL, 0, 0)) { 18103b705cfSriastradh crtc->desiredMode = *mode; 18203b705cfSriastradh crtc->desiredMode.prev = crtc->desiredMode.next = NULL; 18303b705cfSriastradh crtc->desiredMode.name = NULL; 18403b705cfSriastradh crtc->desiredMode.PrivSize = 0; 18503b705cfSriastradh crtc->desiredMode.PrivFlags = 0; 18603b705cfSriastradh crtc->desiredMode.Private = NULL; 18703b705cfSriastradh crtc->desiredRotation = RR_Rotate_0; 18803b705cfSriastradh crtc->desiredTransformPresent = FALSE; 18903b705cfSriastradh crtc->desiredX = 0; 19003b705cfSriastradh crtc->desiredY = 0; 19103b705cfSriastradh crtc->enabled = TRUE; 19203b705cfSriastradh } 19303b705cfSriastradh } 19403b705cfSriastradh 19503b705cfSriastradh xf86DisableUnusedFunctions(scrn); 19603b705cfSriastradh#ifdef RANDR_12_INTERFACE 19763ef14f0Smrg if (get_root_window(xf86ScrnToScreen(scrn))) 19863ef14f0Smrg xf86RandR12TellChanged(xf86ScrnToScreen(scrn)); 19903b705cfSriastradh#endif 20003b705cfSriastradh} 20103b705cfSriastradh 20263ef14f0Smrgstatic void sna_set_desired_mode(struct sna *sna) 20303b705cfSriastradh{ 20403b705cfSriastradh ScrnInfoPtr scrn = sna->scrn; 20503b705cfSriastradh 20603b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 20703b705cfSriastradh 20803b705cfSriastradh if (!xf86SetDesiredModes(scrn)) { 20903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 21003b705cfSriastradh "failed to restore desired modes on VT switch\n"); 21103b705cfSriastradh sna_set_fallback_mode(scrn); 21203b705cfSriastradh } 21303b705cfSriastradh 21442542f5fSchristos sna_mode_check(sna); 21503b705cfSriastradh} 21603b705cfSriastradh 21703b705cfSriastradh/** 21803b705cfSriastradh * Adjust the screen pixmap for the current location of the front buffer. 21903b705cfSriastradh * This is done at EnterVT when buffers are bound as long as the resources 22003b705cfSriastradh * have already been created, but the first EnterVT happens before 22103b705cfSriastradh * CreateScreenResources. 22203b705cfSriastradh */ 22303b705cfSriastradhstatic Bool sna_create_screen_resources(ScreenPtr screen) 22403b705cfSriastradh{ 22503b705cfSriastradh struct sna *sna = to_sna_from_screen(screen); 22642542f5fSchristos PixmapPtr new_front; 22742542f5fSchristos unsigned hint; 22803b705cfSriastradh 22903b705cfSriastradh DBG(("%s(%dx%d@%d)\n", __FUNCTION__, 23003b705cfSriastradh screen->width, screen->height, screen->rootDepth)); 23103b705cfSriastradh 23203b705cfSriastradh assert(sna->scrn == xf86ScreenToScrn(screen)); 23363ef14f0Smrg assert(to_screen_from_sna(sna) == screen); 23403b705cfSriastradh 23542542f5fSchristos /* free the data used during miInitScreen */ 23603b705cfSriastradh free(screen->devPrivate); 23703b705cfSriastradh screen->devPrivate = NULL; 23803b705cfSriastradh 23903b705cfSriastradh sna_accel_create(sna); 24003b705cfSriastradh 24142542f5fSchristos hint = SNA_CREATE_FB; 24242542f5fSchristos if (sna->flags & SNA_IS_HOSTED) 24342542f5fSchristos hint = 0; 24442542f5fSchristos 24542542f5fSchristos new_front = screen->CreatePixmap(screen, 24642542f5fSchristos screen->width, 24742542f5fSchristos screen->height, 24842542f5fSchristos screen->rootDepth, 24942542f5fSchristos hint); 25042542f5fSchristos if (!new_front) { 25103b705cfSriastradh xf86DrvMsg(screen->myNum, X_ERROR, 25203b705cfSriastradh "[intel] Unable to create front buffer %dx%d at depth %d\n", 25303b705cfSriastradh screen->width, 25403b705cfSriastradh screen->height, 25503b705cfSriastradh screen->rootDepth); 25603b705cfSriastradh 25703b705cfSriastradh return FALSE; 25803b705cfSriastradh } 25903b705cfSriastradh 26013496ba1Ssnj /* Prefer to use the GPU for rendering into the eventual scanout 26113496ba1Ssnj * bo so that we do not unduly stall when it is time to attach 26213496ba1Ssnj * it to the CRTCs. 26313496ba1Ssnj */ 26413496ba1Ssnj (void)sna_pixmap_force_to_gpu(new_front, MOVE_READ | __MOVE_SCANOUT); 26503b705cfSriastradh 26642542f5fSchristos screen->SetScreenPixmap(new_front); 26742542f5fSchristos assert(screen->GetScreenPixmap(screen) == new_front); 26842542f5fSchristos assert(sna->front == new_front); 26942542f5fSchristos screen->DestroyPixmap(new_front); /* transfer ownership to screen */ 27042542f5fSchristos 27142542f5fSchristos sna_mode_set_primary(sna); 27203b705cfSriastradh 27313496ba1Ssnj /* Try to become master and copy the current fbcon before the 27413496ba1Ssnj * actual VT switch. If we fail here, we will try to reset the 27513496ba1Ssnj * mode in the eventual VT switch. This can fail if systemd has 27613496ba1Ssnj * already revoked our KMS privileges, so just carry on regardless, 27713496ba1Ssnj * and hope that everything is sorted after the VT switch. 27813496ba1Ssnj */ 27913496ba1Ssnj if (intel_get_master(sna->dev) == 0) { 28013496ba1Ssnj /* Only preserve the fbcon, not any subsequent server regens */ 28113496ba1Ssnj if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0) 28213496ba1Ssnj sna_copy_fbcon(sna); 28303b705cfSriastradh 28463ef14f0Smrg sna_set_desired_mode(sna); 28503b705cfSriastradh } 28603b705cfSriastradh 28703b705cfSriastradh return TRUE; 28803b705cfSriastradh} 28903b705cfSriastradh 29063ef14f0Smrgstatic void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags) 29103b705cfSriastradh{ 29263ef14f0Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 29363ef14f0Smrg struct sna *sna = to_sna(scrn); 29463ef14f0Smrg bool changed = false; 29563ef14f0Smrg int i; 29642542f5fSchristos 29763ef14f0Smrg DBG(("%s(mode=%d, flags=%d), vtSema=%d => off?=%d\n", 29863ef14f0Smrg __FUNCTION__, mode, flags, scrn->vtSema, mode!=DPMSModeOn)); 29942542f5fSchristos if (!scrn->vtSema) 30063ef14f0Smrg return; 30142542f5fSchristos 30263ef14f0Smrg /* Opencoded version of xf86DPMSSet(). 30363ef14f0Smrg * 30463ef14f0Smrg * The principle difference is to skip calling crtc->dpms() when 30563ef14f0Smrg * turning off the display. This (on recent enough kernels at 30663ef14f0Smrg * least) should be equivalent in power consumption, but require 30763ef14f0Smrg * less work (hence quicker and less likely to fail) when switching 30863ef14f0Smrg * back on. 30963ef14f0Smrg */ 31063ef14f0Smrg if (mode != DPMSModeOn) { 31163ef14f0Smrg if (sna->mode.hidden == 0 && !(sna->flags & SNA_NO_DPMS)) { 31263ef14f0Smrg DBG(("%s: hiding %d outputs\n", 31363ef14f0Smrg __FUNCTION__, config->num_output)); 31463ef14f0Smrg for (i = 0; i < config->num_output; i++) { 31563ef14f0Smrg xf86OutputPtr output = config->output[i]; 31663ef14f0Smrg if (output->crtc != NULL) 31763ef14f0Smrg output->funcs->dpms(output, mode); 31863ef14f0Smrg } 31963ef14f0Smrg sna->mode.hidden = sna->mode.front_active + 1; 32063ef14f0Smrg sna->mode.front_active = 0; 32163ef14f0Smrg changed = true; 32263ef14f0Smrg } 32363ef14f0Smrg } else { 32463ef14f0Smrg /* Re-enable CRTC that have been forced off via other means */ 32563ef14f0Smrg if (sna->mode.hidden != 0) { 32663ef14f0Smrg DBG(("%s: unhiding %d crtc, %d outputs\n", 32763ef14f0Smrg __FUNCTION__, config->num_crtc, config->num_output)); 32863ef14f0Smrg sna->mode.front_active = sna->mode.hidden - 1; 32963ef14f0Smrg sna->mode.hidden = 0; 33063ef14f0Smrg for (i = 0; i < config->num_crtc; i++) { 33163ef14f0Smrg xf86CrtcPtr crtc = config->crtc[i]; 33263ef14f0Smrg if (crtc->enabled) 33363ef14f0Smrg crtc->funcs->dpms(crtc, mode); 33463ef14f0Smrg } 33563ef14f0Smrg 33663ef14f0Smrg for (i = 0; i < config->num_output; i++) { 33763ef14f0Smrg xf86OutputPtr output = config->output[i]; 33863ef14f0Smrg if (output->crtc != NULL) 33963ef14f0Smrg output->funcs->dpms(output, mode); 34063ef14f0Smrg } 34163ef14f0Smrg changed = true; 34263ef14f0Smrg } 34363ef14f0Smrg } 34463ef14f0Smrg 34563ef14f0Smrg DBG(("%s: hiding outputs? %d, front active? %d, changed? %d\n", 34663ef14f0Smrg __FUNCTION__, sna->mode.hidden, sna->mode.front_active, changed)); 34763ef14f0Smrg 34863ef14f0Smrg if (changed) 34963ef14f0Smrg sna_crtc_config_notify(xf86ScrnToScreen(scrn)); 35003b705cfSriastradh} 35103b705cfSriastradh 35263ef14f0Smrgstatic Bool sna_save_screen(ScreenPtr screen, int mode) 35303b705cfSriastradh{ 35463ef14f0Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 35563ef14f0Smrg 35663ef14f0Smrg DBG(("%s(mode=%d [unblank=%d])\n", 35763ef14f0Smrg __FUNCTION__, mode, xf86IsUnblank(mode))); 35803b705cfSriastradh 35963ef14f0Smrg /* We have to unroll xf86SaveScreen() here as it is called 36063ef14f0Smrg * by DPMSSet() nullifying our special handling crtc->dpms() 36163ef14f0Smrg * in sna_dpms_set(). 36263ef14f0Smrg */ 36363ef14f0Smrg sna_dpms_set(scrn, 36463ef14f0Smrg xf86IsUnblank(mode) ? DPMSModeOn : DPMSModeOff, 36563ef14f0Smrg 0); 36663ef14f0Smrg return TRUE; 36742542f5fSchristos} 36803b705cfSriastradh 36942542f5fSchristosstatic void sna_selftest(void) 37042542f5fSchristos{ 37142542f5fSchristos sna_damage_selftest(); 37242542f5fSchristos} 37303b705cfSriastradh 37442542f5fSchristosstatic bool has_vsync(struct sna *sna) 37542542f5fSchristos{ 37642542f5fSchristos if (sna->flags & SNA_IS_HOSTED) 37703b705cfSriastradh return false; 37803b705cfSriastradh 37942542f5fSchristos return true; 38003b705cfSriastradh} 38103b705cfSriastradh 38203b705cfSriastradhstatic void sna_setup_capabilities(ScrnInfoPtr scrn, int fd) 38303b705cfSriastradh{ 38403b705cfSriastradh#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME) 38503b705cfSriastradh uint64_t value; 38603b705cfSriastradh 38703b705cfSriastradh scrn->capabilities = 0; 38803b705cfSriastradh if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0) { 38903b705cfSriastradh if (value & DRM_PRIME_CAP_EXPORT) 39003b705cfSriastradh scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; 39103b705cfSriastradh if (value & DRM_PRIME_CAP_IMPORT) 39203b705cfSriastradh scrn->capabilities |= RR_Capability_SinkOutput; 39303b705cfSriastradh } 39403b705cfSriastradh#endif 39503b705cfSriastradh} 39603b705cfSriastradh 39703b705cfSriastradhstatic Bool fb_supports_depth(int fd, int depth) 39803b705cfSriastradh{ 39903b705cfSriastradh struct drm_i915_gem_create create; 40003b705cfSriastradh struct drm_mode_fb_cmd fb; 40142542f5fSchristos struct drm_mode_card_res res; 40203b705cfSriastradh Bool ret; 40303b705cfSriastradh 40442542f5fSchristos memset(&res, 0, sizeof(res)); 40542542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); 40642542f5fSchristos if (res.count_crtcs == 0) 40742542f5fSchristos return TRUE; 40842542f5fSchristos 40903b705cfSriastradh VG_CLEAR(create); 41003b705cfSriastradh create.handle = 0; 41103b705cfSriastradh create.size = 4096; 41203b705cfSriastradh if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create)) 41303b705cfSriastradh return FALSE; 41403b705cfSriastradh 41503b705cfSriastradh VG_CLEAR(fb); 41603b705cfSriastradh fb.width = 64; 41703b705cfSriastradh fb.height = 16; 41803b705cfSriastradh fb.pitch = 256; 41903b705cfSriastradh fb.bpp = depth <= 8 ? 8 : depth <= 16 ? 16 : 32; 42003b705cfSriastradh fb.depth = depth; 42103b705cfSriastradh fb.handle = create.handle; 42203b705cfSriastradh 42303b705cfSriastradh ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &fb) == 0; 42403b705cfSriastradh drmModeRmFB(fd, fb.fb_id); 42503b705cfSriastradh 42642542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &create.handle); 42703b705cfSriastradh 42803b705cfSriastradh return ret; 42903b705cfSriastradh} 43003b705cfSriastradh 43142542f5fSchristosstatic void setup_dri(struct sna *sna) 43242542f5fSchristos{ 43342542f5fSchristos unsigned level; 43442542f5fSchristos 43542542f5fSchristos sna->dri2.available = false; 43663ef14f0Smrg sna->dri2.enable = false; 43742542f5fSchristos sna->dri3.available = false; 43863ef14f0Smrg sna->dri3.enable = false; 43963ef14f0Smrg sna->dri3.override = false; 44042542f5fSchristos 44163ef14f0Smrg level = intel_option_cast_to_unsigned(sna->Options, OPTION_DRI, DEFAULT_DRI_LEVEL); 44242542f5fSchristos#if HAVE_DRI3 44363ef14f0Smrg sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3"); 44463ef14f0Smrg sna->dri3.override = 44563ef14f0Smrg !sna->dri3.available || 44663ef14f0Smrg xf86IsOptionSet(sna->Options, OPTION_DRI); 44763ef14f0Smrg if (level >= 3 && sna->kgem.gen >= 040) 44863ef14f0Smrg sna->dri3.enable = sna->dri3.available; 44942542f5fSchristos#endif 45042542f5fSchristos#if HAVE_DRI2 45163ef14f0Smrg sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2"); 45242542f5fSchristos if (level >= 2) 45363ef14f0Smrg sna->dri2.enable = sna->dri2.available; 45442542f5fSchristos#endif 45542542f5fSchristos} 45642542f5fSchristos 45742542f5fSchristosstatic bool enable_tear_free(struct sna *sna) 45842542f5fSchristos{ 45942542f5fSchristos if (sna->flags & SNA_LINEAR_FB) 46042542f5fSchristos return false; 46142542f5fSchristos 46242542f5fSchristos /* Under certain conditions, we should enable TearFree by default, 46342542f5fSchristos * for example when the hardware requires pageflipping to run within 46442542f5fSchristos * its power/performance budget. 46542542f5fSchristos */ 46642542f5fSchristos if (sna_mode_wants_tear_free(sna)) 46742542f5fSchristos return true; 46842542f5fSchristos 46942542f5fSchristos return ENABLE_TEAR_FREE; 47042542f5fSchristos} 47142542f5fSchristos 47263ef14f0Smrgstatic bool setup_tear_free(struct sna *sna) 47342542f5fSchristos{ 47442542f5fSchristos MessageType from; 47542542f5fSchristos Bool enable; 47642542f5fSchristos 47742542f5fSchristos if (sna->flags & SNA_LINEAR_FB) 47863ef14f0Smrg return false; 47942542f5fSchristos 48042542f5fSchristos if ((sna->flags & SNA_HAS_FLIP) == 0) { 48142542f5fSchristos from = X_PROBED; 48242542f5fSchristos goto done; 48342542f5fSchristos } 48442542f5fSchristos 48542542f5fSchristos if (!xf86GetOptValBool(sna->Options, OPTION_TEAR_FREE, &enable)) { 48642542f5fSchristos enable = enable_tear_free(sna); 48742542f5fSchristos from = X_DEFAULT; 48842542f5fSchristos } else 48942542f5fSchristos from = X_CONFIG; 49042542f5fSchristos 49142542f5fSchristos if (enable) 49263ef14f0Smrg sna->flags |= SNA_WANT_TEAR_FREE | SNA_TEAR_FREE; 49342542f5fSchristos 49442542f5fSchristosdone: 49542542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n", 49642542f5fSchristos sna->flags & SNA_TEAR_FREE ? "en" : "dis"); 49763ef14f0Smrg return sna->flags & SNA_TEAR_FREE; 49842542f5fSchristos} 49942542f5fSchristos 50003b705cfSriastradh/** 50103b705cfSriastradh * This is called before ScreenInit to do any require probing of screen 50203b705cfSriastradh * configuration. 50303b705cfSriastradh * 50403b705cfSriastradh * This code generally covers probing, module loading, option handling 50503b705cfSriastradh * card mapping, and RandR setup. 50603b705cfSriastradh * 50703b705cfSriastradh * Since xf86InitialConfiguration ends up requiring that we set video modes 50803b705cfSriastradh * in order to detect configuration, we end up having to do a lot of driver 50903b705cfSriastradh * setup (talking to the DRM, mapping the device, etc.) in this function. 51003b705cfSriastradh * As a result, we want to set up that server initialization once rather 51103b705cfSriastradh * that doing it per generation. 51203b705cfSriastradh */ 51342542f5fSchristosstatic Bool sna_pre_init(ScrnInfoPtr scrn, int probe) 51403b705cfSriastradh{ 51503b705cfSriastradh struct sna *sna; 51603b705cfSriastradh char buf[1024]; 51703b705cfSriastradh rgb defaultWeight = { 0, 0, 0 }; 51803b705cfSriastradh EntityInfoPtr pEnt; 51903b705cfSriastradh Gamma zeros = { 0.0, 0.0, 0.0 }; 52003b705cfSriastradh int fd; 52103b705cfSriastradh 52203b705cfSriastradh DBG(("%s flags=%x, numEntities=%d\n", 52342542f5fSchristos __FUNCTION__, probe, scrn->numEntities)); 52403b705cfSriastradh 52503b705cfSriastradh if (scrn->numEntities != 1) 52603b705cfSriastradh return FALSE; 52703b705cfSriastradh 52803b705cfSriastradh pEnt = xf86GetEntityInfo(scrn->entityList[0]); 52942542f5fSchristos if (pEnt == NULL) { 53042542f5fSchristos ERR(("%s: no EntityInfo found for scrn\n", __FUNCTION__)); 53103b705cfSriastradh return FALSE; 53242542f5fSchristos } 53303b705cfSriastradh 53403b705cfSriastradh if (pEnt->location.type != BUS_PCI 53503b705cfSriastradh#ifdef XSERVER_PLATFORM_BUS 53603b705cfSriastradh && pEnt->location.type != BUS_PLATFORM 53703b705cfSriastradh#endif 53842542f5fSchristos ) { 53942542f5fSchristos ERR(("%s: invalid EntityInfo found for scrn, location=%d\n", __FUNCTION__, pEnt->location.type)); 54003b705cfSriastradh return FALSE; 54142542f5fSchristos } 54203b705cfSriastradh 54342542f5fSchristos if (probe & PROBE_DETECT) 54403b705cfSriastradh return TRUE; 54503b705cfSriastradh 54603b705cfSriastradh sna_selftest(); 54703b705cfSriastradh 54842542f5fSchristos probe = 0; 54942542f5fSchristos if (((uintptr_t)scrn->driverPrivate) & 3) { 55003b705cfSriastradh if (posix_memalign((void **)&sna, 4096, sizeof(*sna))) 55103b705cfSriastradh return FALSE; 55203b705cfSriastradh 55303b705cfSriastradh memset(sna, 0, sizeof(*sna)); /* should be unnecessary */ 55442542f5fSchristos probe = (uintptr_t)scrn->driverPrivate & 1; 55542542f5fSchristos sna->info = (void *)((uintptr_t)scrn->driverPrivate & ~3); 55603b705cfSriastradh scrn->driverPrivate = sna; 55763ef14f0Smrg sna->scrn = scrn; 55803b705cfSriastradh 55903b705cfSriastradh sna->cpu_features = sna_cpu_detect(); 56042542f5fSchristos sna->acpi.fd = sna_acpi_open(); 56103b705cfSriastradh } 56203b705cfSriastradh sna = to_sna(scrn); 56303b705cfSriastradh sna->pEnt = pEnt; 56442542f5fSchristos sna->flags = probe; 56503b705cfSriastradh 56603b705cfSriastradh scrn->displayWidth = 640; /* default it */ 56703b705cfSriastradh 56803b705cfSriastradh scrn->monitor = scrn->confScreen->monitor; 56903b705cfSriastradh scrn->progClock = TRUE; 57003b705cfSriastradh scrn->rgbBits = 8; 57103b705cfSriastradh 57213496ba1Ssnj sna->dev = intel_get_device(scrn, &fd); 57313496ba1Ssnj if (sna->dev == NULL) { 57403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 57503b705cfSriastradh "Failed to claim DRM device.\n"); 57603b705cfSriastradh goto cleanup; 57703b705cfSriastradh } 57803b705cfSriastradh 57903b705cfSriastradh /* Sanity check */ 58003b705cfSriastradh if (hosted() && (sna->flags & SNA_IS_HOSTED) == 0) { 58103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 58203b705cfSriastradh "Failed to setup hosted device.\n"); 58303b705cfSriastradh goto cleanup; 58403b705cfSriastradh } 58503b705cfSriastradh 58613496ba1Ssnj intel_detect_chipset(scrn, sna->dev); 58763ef14f0Smrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, 58863ef14f0Smrg "CPU: %s; using a maximum of %d threads\n", 58963ef14f0Smrg sna_cpu_features_to_string(sna->cpu_features, buf), 59063ef14f0Smrg sna_use_threads(64*1024, 64*1024, 1)); 59103b705cfSriastradh 59242542f5fSchristos if (!xf86SetDepthBpp(scrn, 24, 0, 0, 59303b705cfSriastradh Support32bppFb | 59403b705cfSriastradh SupportConvert24to32 | PreferConvert24to32)) 59503b705cfSriastradh goto cleanup; 59603b705cfSriastradh 59703b705cfSriastradh switch (scrn->depth) { 59803b705cfSriastradh case 8: 59903b705cfSriastradh case 15: 60003b705cfSriastradh case 16: 60103b705cfSriastradh case 24: 60203b705cfSriastradh case 30: 60342542f5fSchristos if ((sna->flags & SNA_IS_HOSTED) || 60442542f5fSchristos fb_supports_depth(fd, scrn->depth)) 60503b705cfSriastradh break; 60603b705cfSriastradh default: 60703b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 60803b705cfSriastradh "Given depth (%d) is not supported by the Intel driver and this chipset.\n", 60903b705cfSriastradh scrn->depth); 61003b705cfSriastradh goto cleanup; 61103b705cfSriastradh } 61203b705cfSriastradh xf86PrintDepthBpp(scrn); 61303b705cfSriastradh 61403b705cfSriastradh if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 61503b705cfSriastradh goto cleanup; 61603b705cfSriastradh if (!xf86SetDefaultVisual(scrn, -1)) 61703b705cfSriastradh goto cleanup; 61803b705cfSriastradh 61903b705cfSriastradh sna->Options = intel_options_get(scrn); 62003b705cfSriastradh if (sna->Options == NULL) 62103b705cfSriastradh goto cleanup; 62203b705cfSriastradh 62303b705cfSriastradh sna_setup_capabilities(scrn, fd); 62403b705cfSriastradh 62542542f5fSchristos kgem_init(&sna->kgem, fd, 62642542f5fSchristos xf86GetPciInfoForEntity(pEnt->index), 62742542f5fSchristos sna->info->gen); 62803b705cfSriastradh 62903b705cfSriastradh if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE)) 63042542f5fSchristos sna->flags |= SNA_LINEAR_FB; 63163ef14f0Smrg if (!sna->kgem.can_fence) 63263ef14f0Smrg sna->flags |= SNA_LINEAR_FB; 63303b705cfSriastradh 63403b705cfSriastradh if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE)) 63503b705cfSriastradh sna->flags |= SNA_NO_WAIT; 63642542f5fSchristos DBG(("%s: swapbuffer wait? %s\n", __FUNCTION__, sna->flags & SNA_NO_WAIT ? "disabled" : "enabled")); 63742542f5fSchristos 63842542f5fSchristos if (!has_vsync(sna) || 63942542f5fSchristos !xf86ReturnOptValBool(sna->Options, OPTION_VSYNC, TRUE)) 64042542f5fSchristos sna->flags |= SNA_NO_VSYNC; 64142542f5fSchristos DBG(("%s: vsync? %s\n", __FUNCTION__, sna->flags & SNA_NO_VSYNC ? "disabled" : "enabled")); 64242542f5fSchristos 64342542f5fSchristos if (sna->flags & SNA_IS_HOSTED || 64442542f5fSchristos !xf86ReturnOptValBool(sna->Options, OPTION_PAGEFLIP, TRUE)) 64503b705cfSriastradh sna->flags |= SNA_NO_FLIP; 64642542f5fSchristos DBG(("%s: page flips? %s\n", __FUNCTION__, sna->flags & SNA_NO_FLIP ? "disabled" : "enabled")); 64703b705cfSriastradh 64842542f5fSchristos if ((sna->flags & (SNA_NO_VSYNC | SNA_NO_FLIP | SNA_NO_WAIT)) == 0 && 64942542f5fSchristos xf86ReturnOptValBool(sna->Options, OPTION_TRIPLE_BUFFER, TRUE)) 65042542f5fSchristos sna->flags |= SNA_TRIPLE_BUFFER; 65142542f5fSchristos DBG(("%s: triple buffer? %s\n", __FUNCTION__, sna->flags & SNA_TRIPLE_BUFFER ? "enabled" : "disabled")); 65203b705cfSriastradh 65342542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_CRTC_PIXMAPS, FALSE)) { 65442542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Forcing per-crtc-pixmaps.\n"); 65542542f5fSchristos sna->flags |= SNA_FORCE_SHADOW; 65642542f5fSchristos } 65703b705cfSriastradh 65803b705cfSriastradh if (!sna_mode_pre_init(scrn, sna)) { 65903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 66003b705cfSriastradh "No outputs and no modes.\n"); 66103b705cfSriastradh goto cleanup; 66203b705cfSriastradh } 66303b705cfSriastradh scrn->currentMode = scrn->modes; 66403b705cfSriastradh 66563ef14f0Smrg if (!setup_tear_free(sna) && sna_mode_wants_tear_free(sna)) 66663ef14f0Smrg sna->kgem.needs_dirtyfb = sna->kgem.has_dirtyfb; 66742542f5fSchristos 66803b705cfSriastradh xf86SetGamma(scrn, zeros); 66903b705cfSriastradh xf86SetDpi(scrn, 0, 0); 67003b705cfSriastradh 67142542f5fSchristos setup_dri(sna); 67242542f5fSchristos 67342542f5fSchristos sna->present.available = false; 67442542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_PRESENT, TRUE)) { 67542542f5fSchristos#if HAVE_PRESENT 67642542f5fSchristos sna->present.available = !!xf86LoadSubModule(scrn, "present"); 67742542f5fSchristos#endif 67842542f5fSchristos } 67942542f5fSchristos 68042542f5fSchristos sna_acpi_init(sna); 68103b705cfSriastradh 68203b705cfSriastradh return TRUE; 68303b705cfSriastradh 68403b705cfSriastradhcleanup: 68542542f5fSchristos scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2); 68613496ba1Ssnj if (sna->dev) 68713496ba1Ssnj intel_put_device(sna->dev); 68803b705cfSriastradh free(sna); 68903b705cfSriastradh return FALSE; 69003b705cfSriastradh} 69103b705cfSriastradh 69242542f5fSchristosstatic bool has_shadow(struct sna *sna) 69342542f5fSchristos{ 69463ef14f0Smrg if (!sna->mode.shadow_enabled) 69542542f5fSchristos return false; 69642542f5fSchristos 69763ef14f0Smrg assert(sna->mode.shadow_damage); 69842542f5fSchristos if (RegionNil(DamageRegion(sna->mode.shadow_damage))) 69942542f5fSchristos return false; 70042542f5fSchristos 70142542f5fSchristos return sna->mode.flip_active == 0; 70242542f5fSchristos} 70342542f5fSchristos 70463ef14f0Smrg#if !HAVE_NOTIFY_FD 70503b705cfSriastradhstatic void 70603b705cfSriastradhsna_block_handler(BLOCKHANDLER_ARGS_DECL) 70703b705cfSriastradh{ 70803b705cfSriastradh#ifndef XF86_SCRN_INTERFACE 70903b705cfSriastradh struct sna *sna = to_sna(xf86Screens[arg]); 71003b705cfSriastradh#else 71103b705cfSriastradh struct sna *sna = to_sna_from_screen(arg); 71203b705cfSriastradh#endif 71303b705cfSriastradh struct timeval **tv = timeout; 71403b705cfSriastradh 71563ef14f0Smrg DBG(("%s (tv=%ld.%06ld), has_shadow?=%d\n", __FUNCTION__, 71663ef14f0Smrg *tv ? (*tv)->tv_sec : -1, *tv ? (*tv)->tv_usec : 0, 71763ef14f0Smrg has_shadow(sna))); 71803b705cfSriastradh 71903b705cfSriastradh sna->BlockHandler(BLOCKHANDLER_ARGS); 72003b705cfSriastradh 72142542f5fSchristos if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna)) 72263ef14f0Smrg sna_accel_block(sna, tv); 72303b705cfSriastradh} 72403b705cfSriastradh 72503b705cfSriastradhstatic void 72603b705cfSriastradhsna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL) 72703b705cfSriastradh{ 72803b705cfSriastradh#ifndef XF86_SCRN_INTERFACE 72903b705cfSriastradh struct sna *sna = to_sna(xf86Screens[arg]); 73003b705cfSriastradh#else 73103b705cfSriastradh struct sna *sna = to_sna_from_screen(arg); 73203b705cfSriastradh#endif 73303b705cfSriastradh 73403b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 73503b705cfSriastradh 73603b705cfSriastradh /* despite all appearances, result is just a signed int */ 73703b705cfSriastradh if ((int)result < 0) 73803b705cfSriastradh return; 73903b705cfSriastradh 74063ef14f0Smrg sna_acpi_wakeup(sna, read_mask); 74142542f5fSchristos 74203b705cfSriastradh sna->WakeupHandler(WAKEUPHANDLER_ARGS); 74303b705cfSriastradh 74463ef14f0Smrg if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) { 74563ef14f0Smrg sna_mode_wakeup(sna); 74663ef14f0Smrg /* Clear the flag so that subsequent ZaphodHeads don't block */ 74763ef14f0Smrg FD_CLR(sna->kgem.fd, (fd_set*)read_mask); 74863ef14f0Smrg } 74963ef14f0Smrg} 75063ef14f0Smrg#else 75163ef14f0Smrgstatic void 75263ef14f0Smrgsna_block_handler(void *data, void *_timeout) 75363ef14f0Smrg{ 75463ef14f0Smrg struct sna *sna = data; 75563ef14f0Smrg int *timeout = _timeout; 75663ef14f0Smrg struct timeval tv, *tvp; 75763ef14f0Smrg 75863ef14f0Smrg DBG(("%s (timeout=%d, has_shadow=%d)\n", __FUNCTION__, 75963ef14f0Smrg *timeout, has_shadow(sna))); 76063ef14f0Smrg 76163ef14f0Smrg if (*timeout < 0) { 76263ef14f0Smrg tvp = NULL; 76363ef14f0Smrg } else if (*timeout == 0) { 76463ef14f0Smrg if (!has_shadow(sna)) 76563ef14f0Smrg return; 76663ef14f0Smrg 76763ef14f0Smrg tv.tv_sec = 0; 76863ef14f0Smrg tv.tv_usec = 0; 76963ef14f0Smrg tvp = &tv; 77063ef14f0Smrg } else { 77163ef14f0Smrg tv.tv_sec = *timeout / 1000; 77263ef14f0Smrg tv.tv_usec = (*timeout % 1000) * 1000; 77363ef14f0Smrg tvp = &tv; 77463ef14f0Smrg } 77503b705cfSriastradh 77663ef14f0Smrg sna_accel_block(sna, &tvp); 77763ef14f0Smrg if (tvp) 77863ef14f0Smrg *timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000; 77903b705cfSriastradh} 78063ef14f0Smrg#endif 78103b705cfSriastradh 78203b705cfSriastradh#if HAVE_UDEV 78363ef14f0Smrg#include <sys/stat.h> 78463ef14f0Smrg 78503b705cfSriastradhstatic void 78603b705cfSriastradhsna_handle_uevents(int fd, void *closure) 78703b705cfSriastradh{ 78842542f5fSchristos struct sna *sna = closure; 78903b705cfSriastradh struct stat s; 79063ef14f0Smrg struct pollfd pfd; 79163ef14f0Smrg bool hotplug = false; 79203b705cfSriastradh 79303b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 79403b705cfSriastradh 79563ef14f0Smrg pfd.fd = udev_monitor_get_fd(sna->uevent_monitor); 79663ef14f0Smrg pfd.events = POLLIN; 79763ef14f0Smrg 79863ef14f0Smrg if (fstat(sna->kgem.fd, &s)) 79963ef14f0Smrg memset(&s, 0, sizeof(s)); 80063ef14f0Smrg 80163ef14f0Smrg while (poll(&pfd, 1, 0) > 0) { 80263ef14f0Smrg struct udev_device *dev; 80363ef14f0Smrg dev_t devnum; 80463ef14f0Smrg 80563ef14f0Smrg errno = 0; 80663ef14f0Smrg dev = udev_monitor_receive_device(sna->uevent_monitor); 80763ef14f0Smrg if (dev == NULL) { 80863ef14f0Smrg if (errno == EINTR || errno == EAGAIN) 80963ef14f0Smrg continue; 81063ef14f0Smrg 81163ef14f0Smrg break; 81263ef14f0Smrg } 81363ef14f0Smrg 81463ef14f0Smrg devnum = udev_device_get_devnum(dev); 81563ef14f0Smrg if (memcmp(&s.st_rdev, &devnum, sizeof(dev_t)) == 0) { 81663ef14f0Smrg const char *str; 81763ef14f0Smrg 81863ef14f0Smrg str = udev_device_get_property_value(dev, "HOTPLUG"); 81963ef14f0Smrg if (str && atoi(str) == 1) { 82063ef14f0Smrg str = udev_device_get_property_value(dev, "CONNECTOR"); 82163ef14f0Smrg if (str) { 82263ef14f0Smrg hotplug |= sna_mode_find_hotplug_connector(sna, atoi(str)); 82363ef14f0Smrg } else { 82463ef14f0Smrg sna->flags |= SNA_REPROBE; 82563ef14f0Smrg hotplug = true; 82663ef14f0Smrg } 82763ef14f0Smrg } 82863ef14f0Smrg } 82903b705cfSriastradh 83003b705cfSriastradh udev_device_unref(dev); 83103b705cfSriastradh } 83203b705cfSriastradh 83363ef14f0Smrg if (hotplug) { 83463ef14f0Smrg DBG(("%s: hotplug event (vtSema?=%d)\n", 83563ef14f0Smrg __FUNCTION__, sna->scrn->vtSema)); 83603b705cfSriastradh 83763ef14f0Smrg if (sna->scrn->vtSema) 83863ef14f0Smrg sna_mode_discover(sna, true); 83963ef14f0Smrg else 84003b705cfSriastradh sna->flags |= SNA_REPROBE; 84103b705cfSriastradh } 84263ef14f0Smrg} 84303b705cfSriastradh 84463ef14f0Smrgstatic bool has_randr(void) 84563ef14f0Smrg{ 84663ef14f0Smrg#if HAS_DIXREGISTERPRIVATEKEY 84763ef14f0Smrg return dixPrivateKeyRegistered(rrPrivKey); 84863ef14f0Smrg#else 84963ef14f0Smrg return *rrPrivKey; 85063ef14f0Smrg#endif 85103b705cfSriastradh} 85203b705cfSriastradh 85303b705cfSriastradhstatic void 85442542f5fSchristossna_uevent_init(struct sna *sna) 85503b705cfSriastradh{ 85603b705cfSriastradh struct udev *u; 85703b705cfSriastradh struct udev_monitor *mon; 85803b705cfSriastradh MessageType from = X_CONFIG; 85903b705cfSriastradh 86003b705cfSriastradh if (sna->flags & SNA_IS_HOSTED) 86103b705cfSriastradh return; 86203b705cfSriastradh 86303b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 86403b705cfSriastradh 86503b705cfSriastradh /* RandR will be disabled if Xinerama is active, and so generating 86603b705cfSriastradh * RR hotplug events is then verboten. 86703b705cfSriastradh */ 86863ef14f0Smrg if (!has_randr()) 86942542f5fSchristos goto out; 87003b705cfSriastradh 87142542f5fSchristos u = NULL; 87242542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_HOTPLUG, TRUE)) 87342542f5fSchristos u = udev_new(); 87403b705cfSriastradh if (!u) 87542542f5fSchristos goto out; 87642542f5fSchristos 87742542f5fSchristos from = X_DEFAULT; 87803b705cfSriastradh 87903b705cfSriastradh mon = udev_monitor_new_from_netlink(u, "udev"); 88042542f5fSchristos if (!mon) 88142542f5fSchristos goto err_dev; 88203b705cfSriastradh 88342542f5fSchristos if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0) 88442542f5fSchristos goto err_monitor; 88503b705cfSriastradh 88642542f5fSchristos if (udev_monitor_enable_receiving(mon) < 0) 88742542f5fSchristos goto err_monitor; 88803b705cfSriastradh 88942542f5fSchristos sna->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), 89042542f5fSchristos sna_handle_uevents, sna); 89142542f5fSchristos if (!sna->uevent_handler) 89242542f5fSchristos goto err_monitor; 89303b705cfSriastradh 89442542f5fSchristos sna->uevent_monitor = mon; 89542542f5fSchristosout: 89663ef14f0Smrg xf86DrvMsg(sna->scrn->scrnIndex, from, 89763ef14f0Smrg "Display hotplug detection %s\n", 89842542f5fSchristos sna->uevent_monitor ? "enabled" : "disabled"); 89942542f5fSchristos return; 90042542f5fSchristos 90142542f5fSchristoserr_monitor: 90242542f5fSchristos udev_monitor_unref(mon); 90342542f5fSchristoserr_dev: 90442542f5fSchristos udev_unref(u); 90542542f5fSchristos goto out; 90603b705cfSriastradh} 90703b705cfSriastradh 90813496ba1Ssnjstatic bool sna_uevent_poll(struct sna *sna) 90913496ba1Ssnj{ 91013496ba1Ssnj if (sna->uevent_monitor == NULL) 91113496ba1Ssnj return false; 91213496ba1Ssnj 91363ef14f0Smrg sna_handle_uevents(udev_monitor_get_fd(sna->uevent_monitor), sna); 91413496ba1Ssnj return true; 91513496ba1Ssnj} 91613496ba1Ssnj 91703b705cfSriastradhstatic void 91842542f5fSchristossna_uevent_fini(struct sna *sna) 91903b705cfSriastradh{ 92003b705cfSriastradh struct udev *u; 92103b705cfSriastradh 92203b705cfSriastradh if (sna->uevent_handler == NULL) 92303b705cfSriastradh return; 92403b705cfSriastradh 92503b705cfSriastradh xf86RemoveGeneralHandler(sna->uevent_handler); 92603b705cfSriastradh 92703b705cfSriastradh u = udev_monitor_get_udev(sna->uevent_monitor); 92803b705cfSriastradh udev_monitor_unref(sna->uevent_monitor); 92903b705cfSriastradh udev_unref(u); 93003b705cfSriastradh 93103b705cfSriastradh sna->uevent_handler = NULL; 93203b705cfSriastradh sna->uevent_monitor = NULL; 93303b705cfSriastradh 93403b705cfSriastradh DBG(("%s: removed uvent handler\n", __FUNCTION__)); 93503b705cfSriastradh} 93603b705cfSriastradh#else 93742542f5fSchristosstatic void sna_uevent_init(struct sna *sna) { } 93813496ba1Ssnjstatic bool sna_uevent_poll(struct sna *sna) { return false; } 93942542f5fSchristosstatic void sna_uevent_fini(struct sna *sna) { } 94003b705cfSriastradh#endif /* HAVE_UDEV */ 94103b705cfSriastradh 94213496ba1Ssnjstatic Bool 94313496ba1Ssnjsna_randr_getinfo(ScreenPtr screen, Rotation *rotations) 94413496ba1Ssnj{ 94513496ba1Ssnj struct sna *sna = to_sna_from_screen(screen); 94613496ba1Ssnj 94763ef14f0Smrg DBG(("%s()\n", __FUNCTION__)); 94863ef14f0Smrg 94913496ba1Ssnj if (!sna_uevent_poll(sna)) 95063ef14f0Smrg sna_mode_discover(sna, false); 95113496ba1Ssnj 95213496ba1Ssnj return sna->mode.rrGetInfo(screen, rotations); 95313496ba1Ssnj} 95413496ba1Ssnj 95503b705cfSriastradhstatic void sna_leave_vt(VT_FUNC_ARGS_DECL) 95603b705cfSriastradh{ 95703b705cfSriastradh SCRN_INFO_PTR(arg); 95842542f5fSchristos struct sna *sna = to_sna(scrn); 95903b705cfSriastradh 96063ef14f0Smrg DBG(("%s(vtSema=%d)\n", __FUNCTION__, scrn->vtSema)); 96103b705cfSriastradh 96242542f5fSchristos sna_mode_reset(sna); 96363ef14f0Smrg sna_accel_leave(sna); 96403b705cfSriastradh 96563ef14f0Smrg if (scrn->vtSema && intel_put_master(sna->dev)) 96603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 96703b705cfSriastradh "drmDropMaster failed: %s\n", strerror(errno)); 96863ef14f0Smrg 96963ef14f0Smrg scrn->vtSema = FALSE; 97003b705cfSriastradh} 97103b705cfSriastradh 97203b705cfSriastradhstatic Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL) 97303b705cfSriastradh{ 97403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 97503b705cfSriastradh struct sna *sna = to_sna(scrn); 97603b705cfSriastradh 97703b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 97803b705cfSriastradh 97903b705cfSriastradh /* XXX Note that we will leak kernel resources if !vtSema */ 98003b705cfSriastradh 98163ef14f0Smrg#if HAVE_NOTIFY_FD 98263ef14f0Smrg RemoveBlockAndWakeupHandlers(sna_block_handler, 98363ef14f0Smrg (ServerWakeupHandlerProcPtr)NoopDDA, 98463ef14f0Smrg sna); 98563ef14f0Smrg#endif 98663ef14f0Smrg 98742542f5fSchristos sna_uevent_fini(sna); 98803b705cfSriastradh sna_mode_close(sna); 98903b705cfSriastradh 99042542f5fSchristos if (sna->present.open) { 99142542f5fSchristos sna_present_close(sna, screen); 99242542f5fSchristos sna->present.open = false; 99342542f5fSchristos } 99442542f5fSchristos 99542542f5fSchristos if (sna->dri3.open) { 99642542f5fSchristos sna_dri3_close(sna, screen); 99742542f5fSchristos sna->dri3.open = false; 99842542f5fSchristos } 99942542f5fSchristos 100042542f5fSchristos if (sna->dri2.open) { 100142542f5fSchristos sna_dri2_close(sna, screen); 100242542f5fSchristos sna->dri2.open = false; 100303b705cfSriastradh } 100403b705cfSriastradh 100503b705cfSriastradh if (sna->front) { 100603b705cfSriastradh screen->DestroyPixmap(sna->front); 100703b705cfSriastradh sna->front = NULL; 100803b705cfSriastradh } 100903b705cfSriastradh 101003b705cfSriastradh if (scrn->vtSema) { 101113496ba1Ssnj intel_put_master(sna->dev); 101203b705cfSriastradh scrn->vtSema = FALSE; 101303b705cfSriastradh } 101403b705cfSriastradh 101503b705cfSriastradh return sna->CloseScreen(CLOSE_SCREEN_ARGS); 101603b705cfSriastradh} 101703b705cfSriastradh 101803b705cfSriastradhstatic Bool sna_late_close_screen(CLOSE_SCREEN_ARGS_DECL) 101903b705cfSriastradh{ 102003b705cfSriastradh struct sna *sna = to_sna_from_screen(screen); 102103b705cfSriastradh DepthPtr depths; 102203b705cfSriastradh int d; 102303b705cfSriastradh 102403b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 102503b705cfSriastradh 102603b705cfSriastradh sna_accel_close(sna); 102742542f5fSchristos sna_video_close(sna); 102803b705cfSriastradh 102903b705cfSriastradh depths = screen->allowedDepths; 103003b705cfSriastradh for (d = 0; d < screen->numDepths; d++) 103103b705cfSriastradh free(depths[d].vids); 103203b705cfSriastradh free(depths); 103303b705cfSriastradh 103403b705cfSriastradh free(screen->visuals); 103503b705cfSriastradh 103603b705cfSriastradh return TRUE; 103703b705cfSriastradh} 103803b705cfSriastradh 103903b705cfSriastradhstatic Bool 104003b705cfSriastradhsna_register_all_privates(void) 104103b705cfSriastradh{ 104203b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY 104303b705cfSriastradh if (!dixRegisterPrivateKey(&sna_pixmap_key, PRIVATE_PIXMAP, 104403b705cfSriastradh 3*sizeof(void *))) 104503b705cfSriastradh return FALSE; 104603b705cfSriastradh 104703b705cfSriastradh if (!dixRegisterPrivateKey(&sna_gc_key, PRIVATE_GC, 104803b705cfSriastradh sizeof(FbGCPrivate))) 104903b705cfSriastradh return FALSE; 105003b705cfSriastradh 105103b705cfSriastradh if (!dixRegisterPrivateKey(&sna_glyph_key, PRIVATE_GLYPH, 105203b705cfSriastradh sizeof(struct sna_glyph))) 105303b705cfSriastradh return FALSE; 105403b705cfSriastradh 105503b705cfSriastradh if (!dixRegisterPrivateKey(&sna_window_key, PRIVATE_WINDOW, 105603b705cfSriastradh 3*sizeof(void *))) 105703b705cfSriastradh return FALSE; 105803b705cfSriastradh 105903b705cfSriastradh if (!dixRegisterPrivateKey(&sna_client_key, PRIVATE_CLIENT, 106003b705cfSriastradh sizeof(struct sna_client))) 106103b705cfSriastradh return FALSE; 106203b705cfSriastradh#else 106303b705cfSriastradh if (!dixRequestPrivate(&sna_pixmap_key, 3*sizeof(void *))) 106403b705cfSriastradh return FALSE; 106503b705cfSriastradh 106603b705cfSriastradh if (!dixRequestPrivate(&sna_gc_key, sizeof(FbGCPrivate))) 106703b705cfSriastradh return FALSE; 106803b705cfSriastradh 106903b705cfSriastradh if (!dixRequestPrivate(&sna_glyph_key, sizeof(struct sna_glyph))) 107003b705cfSriastradh return FALSE; 107103b705cfSriastradh 107203b705cfSriastradh if (!dixRequestPrivate(&sna_window_key, 3*sizeof(void *))) 107303b705cfSriastradh return FALSE; 107403b705cfSriastradh 107503b705cfSriastradh if (!dixRequestPrivate(&sna_client_key, sizeof(struct sna_client))) 107603b705cfSriastradh return FALSE; 107703b705cfSriastradh#endif 107803b705cfSriastradh 107903b705cfSriastradh return TRUE; 108003b705cfSriastradh} 108103b705cfSriastradh 108242542f5fSchristosstatic void sna_dri_init(struct sna *sna, ScreenPtr screen) 108342542f5fSchristos{ 108442542f5fSchristos char str[128] = ""; 108542542f5fSchristos 108663ef14f0Smrg if (sna->dri2.enable) 108742542f5fSchristos sna->dri2.open = sna_dri2_open(sna, screen); 108842542f5fSchristos if (sna->dri2.open) 108942542f5fSchristos strcat(str, "DRI2 "); 109042542f5fSchristos 109163ef14f0Smrg /* Load DRI3 in case DRI2 doesn't work, e.g. vgaarb */ 109263ef14f0Smrg if (sna->dri3.enable || (!sna->dri2.open && !sna->dri3.override)) 109342542f5fSchristos sna->dri3.open = sna_dri3_open(sna, screen); 109442542f5fSchristos if (sna->dri3.open) 109542542f5fSchristos strcat(str, "DRI3 "); 109642542f5fSchristos 109742542f5fSchristos if (*str) 109842542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 109942542f5fSchristos "direct rendering: %senabled\n", str); 110042542f5fSchristos} 110142542f5fSchristos 110213496ba1Ssnjstatic Bool 110313496ba1Ssnjsna_mode_init(struct sna *sna, ScreenPtr screen) 110403b705cfSriastradh{ 110513496ba1Ssnj rrScrPrivPtr rp; 110613496ba1Ssnj 110713496ba1Ssnj if (!xf86CrtcScreenInit(screen)) 110813496ba1Ssnj return FALSE; 110913496ba1Ssnj 111013496ba1Ssnj xf86RandR12SetRotations(screen, RR_Rotate_All | RR_Reflect_All); 111113496ba1Ssnj xf86RandR12SetTransformSupport(screen, TRUE); 111213496ba1Ssnj 111313496ba1Ssnj /* Wrap RR queries to catch pending MST topology changes */ 111413496ba1Ssnj rp = rrGetScrPriv(screen); 111513496ba1Ssnj if (rp) { 111613496ba1Ssnj sna->mode.rrGetInfo = rp->rrGetInfo; 111713496ba1Ssnj rp->rrGetInfo = sna_randr_getinfo; 111863ef14f0Smrg 111963ef14f0Smrg /* Simulate a hotplug event on wakeup to force a RR probe */ 112063ef14f0Smrg TimerSet(NULL, 0, COLDPLUG_DELAY_MS, sna_mode_coldplug, sna); 112113496ba1Ssnj } 112213496ba1Ssnj 112313496ba1Ssnj return TRUE; 112403b705cfSriastradh} 112503b705cfSriastradh 112603b705cfSriastradhstatic Bool 112703b705cfSriastradhsna_screen_init(SCREEN_INIT_ARGS_DECL) 112803b705cfSriastradh{ 112903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 113003b705cfSriastradh struct sna *sna = to_sna(scrn); 113103b705cfSriastradh VisualPtr visuals; 113203b705cfSriastradh DepthPtr depths; 113303b705cfSriastradh int nvisuals; 113403b705cfSriastradh int ndepths; 113503b705cfSriastradh int rootdepth; 113603b705cfSriastradh VisualID defaultVisual; 113703b705cfSriastradh 113803b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 113903b705cfSriastradh 114003b705cfSriastradh assert(sna->scrn == scrn); 114163ef14f0Smrg assert(to_screen_from_sna(sna) == NULL || /* set afterwards */ 114263ef14f0Smrg to_screen_from_sna(sna) == screen); 114303b705cfSriastradh 114403b705cfSriastradh assert(sna->freed_pixmap == NULL); 114503b705cfSriastradh 114603b705cfSriastradh if (!sna_register_all_privates()) 114703b705cfSriastradh return FALSE; 114803b705cfSriastradh 114913496ba1Ssnj scrn->videoRam = sna->kgem.aperture_mappable * 4; /* Page to KiB */ 115003b705cfSriastradh 115103b705cfSriastradh miClearVisualTypes(); 115203b705cfSriastradh if (!miSetVisualTypes(scrn->depth, 115303b705cfSriastradh miGetDefaultVisualMask(scrn->depth), 115403b705cfSriastradh scrn->rgbBits, scrn->defaultVisual)) 115503b705cfSriastradh return FALSE; 115603b705cfSriastradh if (!miSetPixmapDepths()) 115703b705cfSriastradh return FALSE; 115803b705cfSriastradh 115903b705cfSriastradh rootdepth = 0; 116003b705cfSriastradh if (!miInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth, 116103b705cfSriastradh &defaultVisual, 116203b705cfSriastradh ((unsigned long)1 << (scrn->bitsPerPixel - 1)), 116363ef14f0Smrg scrn->rgbBits, -1)) 116403b705cfSriastradh return FALSE; 116503b705cfSriastradh 116603b705cfSriastradh if (!miScreenInit(screen, NULL, 116703b705cfSriastradh scrn->virtualX, scrn->virtualY, 116803b705cfSriastradh scrn->xDpi, scrn->yDpi, 0, 116903b705cfSriastradh rootdepth, ndepths, depths, 117003b705cfSriastradh defaultVisual, nvisuals, visuals)) 117103b705cfSriastradh return FALSE; 117203b705cfSriastradh 117303b705cfSriastradh if (scrn->bitsPerPixel > 8) { 117403b705cfSriastradh /* Fixup RGB ordering */ 117503b705cfSriastradh VisualPtr visual = screen->visuals + screen->numVisuals; 117603b705cfSriastradh while (--visual >= screen->visuals) { 117703b705cfSriastradh if ((visual->class | DynamicClass) == DirectColor) { 117803b705cfSriastradh visual->offsetRed = scrn->offset.red; 117903b705cfSriastradh visual->offsetGreen = scrn->offset.green; 118003b705cfSriastradh visual->offsetBlue = scrn->offset.blue; 118103b705cfSriastradh visual->redMask = scrn->mask.red; 118203b705cfSriastradh visual->greenMask = scrn->mask.green; 118303b705cfSriastradh visual->blueMask = scrn->mask.blue; 118403b705cfSriastradh } 118503b705cfSriastradh } 118603b705cfSriastradh } 118703b705cfSriastradh 118803b705cfSriastradh assert(screen->CloseScreen == NULL); 118903b705cfSriastradh screen->CloseScreen = sna_late_close_screen; 119003b705cfSriastradh if (!sna_accel_init(screen, sna)) { 119103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 119203b705cfSriastradh "Hardware acceleration initialization failed\n"); 119303b705cfSriastradh return FALSE; 119403b705cfSriastradh } 119503b705cfSriastradh 119603b705cfSriastradh xf86SetBlackWhitePixels(screen); 119703b705cfSriastradh 119803b705cfSriastradh xf86SetBackingStore(screen); 119903b705cfSriastradh xf86SetSilkenMouse(screen); 120003b705cfSriastradh if (!miDCInitialize(screen, xf86GetPointerScreenFuncs())) 120103b705cfSriastradh return FALSE; 120203b705cfSriastradh 120342542f5fSchristos if (sna_cursors_init(screen, sna)) 120403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, "HW Cursor enabled\n"); 120503b705cfSriastradh 120603b705cfSriastradh /* Must force it before EnterVT, so we are in control of VT and 120703b705cfSriastradh * later memory should be bound when allocating, e.g rotate_mem */ 120803b705cfSriastradh scrn->vtSema = TRUE; 120903b705cfSriastradh 121063ef14f0Smrg#if !HAVE_NOTIFY_FD 121103b705cfSriastradh sna->BlockHandler = screen->BlockHandler; 121203b705cfSriastradh screen->BlockHandler = sna_block_handler; 121303b705cfSriastradh 121403b705cfSriastradh sna->WakeupHandler = screen->WakeupHandler; 121503b705cfSriastradh screen->WakeupHandler = sna_wakeup_handler; 121663ef14f0Smrg#else 121763ef14f0Smrg RegisterBlockAndWakeupHandlers(sna_block_handler, 121863ef14f0Smrg (ServerWakeupHandlerProcPtr)NoopDDA, 121963ef14f0Smrg sna); 122063ef14f0Smrg#endif 122103b705cfSriastradh 122242542f5fSchristos screen->SaveScreen = sna_save_screen; 122303b705cfSriastradh screen->CreateScreenResources = sna_create_screen_resources; 122403b705cfSriastradh 122503b705cfSriastradh sna->CloseScreen = screen->CloseScreen; 122603b705cfSriastradh screen->CloseScreen = sna_early_close_screen; 122703b705cfSriastradh 122813496ba1Ssnj if (!sna_mode_init(sna, screen)) 122903b705cfSriastradh return FALSE; 123003b705cfSriastradh 123103b705cfSriastradh if (!miCreateDefColormap(screen)) 123203b705cfSriastradh return FALSE; 123303b705cfSriastradh 123463ef14f0Smrg /* X-Server < 1.20 mishandles > 256 slots / > 8 bpc color maps. */ 123563ef14f0Smrg if (sna->mode.num_real_crtc && (scrn->rgbBits <= 8 || 123663ef14f0Smrg XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,20,0,0,0)) && 123763ef14f0Smrg !xf86HandleColormaps(screen, 1 << scrn->rgbBits, scrn->rgbBits, 123863ef14f0Smrg sna_load_palette, NULL, 123903b705cfSriastradh CMAP_RELOAD_ON_MODE_SWITCH | 124042542f5fSchristos CMAP_PALETTED_TRUECOLOR)) 124103b705cfSriastradh return FALSE; 124203b705cfSriastradh 124363ef14f0Smrg if (!xf86CheckBoolOption(scrn->options, "dpms", TRUE)) 124463ef14f0Smrg sna->flags |= SNA_NO_DPMS; 124542542f5fSchristos xf86DPMSInit(screen, sna_dpms_set, 0); 124603b705cfSriastradh 124713496ba1Ssnj sna_uevent_init(sna); 124803b705cfSriastradh sna_video_init(sna, screen); 124942542f5fSchristos sna_dri_init(sna, screen); 125042542f5fSchristos 125142542f5fSchristos if (sna->present.available) 125242542f5fSchristos sna->present.open = sna_present_open(sna, screen); 125342542f5fSchristos if (sna->present.open) 125442542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 125542542f5fSchristos "hardware support for Present enabled\n"); 125603b705cfSriastradh 125703b705cfSriastradh if (serverGeneration == 1) 125803b705cfSriastradh xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 125903b705cfSriastradh 126003b705cfSriastradh sna->suspended = FALSE; 126103b705cfSriastradh 126203b705cfSriastradh return TRUE; 126303b705cfSriastradh} 126403b705cfSriastradh 126503b705cfSriastradhstatic void sna_adjust_frame(ADJUST_FRAME_ARGS_DECL) 126603b705cfSriastradh{ 126703b705cfSriastradh SCRN_INFO_PTR(arg); 126803b705cfSriastradh DBG(("%s(%d, %d)\n", __FUNCTION__, x, y)); 126903b705cfSriastradh sna_mode_adjust_frame(to_sna(scrn), x, y); 127003b705cfSriastradh} 127103b705cfSriastradh 127203b705cfSriastradhstatic void sna_free_screen(FREE_SCREEN_ARGS_DECL) 127303b705cfSriastradh{ 127403b705cfSriastradh SCRN_INFO_PTR(arg); 127503b705cfSriastradh struct sna *sna = to_sna(scrn); 127603b705cfSriastradh 127742542f5fSchristos DBG(("%s [scrn=%p, sna=%p]\n", __FUNCTION__, scrn, sna)); 127842542f5fSchristos if (sna == NULL || (uintptr_t)sna & 3) /* beware thieves */ 127903b705cfSriastradh return; 128003b705cfSriastradh 128142542f5fSchristos scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2); 128203b705cfSriastradh 128303b705cfSriastradh sna_mode_fini(sna); 128442542f5fSchristos sna_acpi_fini(sna); 128503b705cfSriastradh 128613496ba1Ssnj intel_put_device(sna->dev); 128713496ba1Ssnj free(sna); 128803b705cfSriastradh} 128903b705cfSriastradh 129003b705cfSriastradhstatic Bool sna_enter_vt(VT_FUNC_ARGS_DECL) 129103b705cfSriastradh{ 129203b705cfSriastradh SCRN_INFO_PTR(arg); 129303b705cfSriastradh struct sna *sna = to_sna(scrn); 129403b705cfSriastradh 129563ef14f0Smrg DBG(("%s(vtSema=%d)\n", __FUNCTION__, scrn->vtSema)); 129613496ba1Ssnj if (intel_get_master(sna->dev)) 129703b705cfSriastradh return FALSE; 129803b705cfSriastradh 129963ef14f0Smrg scrn->vtSema = TRUE; 130063ef14f0Smrg sna_accel_enter(sna); 130163ef14f0Smrg 130203b705cfSriastradh if (sna->flags & SNA_REPROBE) { 130363ef14f0Smrg DBG(("%s: reporting deferred hotplug event\n", __FUNCTION__)); 130463ef14f0Smrg sna_mode_discover(sna, true); 130503b705cfSriastradh } 130603b705cfSriastradh 130763ef14f0Smrg sna_set_desired_mode(sna); 130842542f5fSchristos 130903b705cfSriastradh return TRUE; 131003b705cfSriastradh} 131103b705cfSriastradh 131203b705cfSriastradhstatic Bool sna_switch_mode(SWITCH_MODE_ARGS_DECL) 131303b705cfSriastradh{ 131403b705cfSriastradh SCRN_INFO_PTR(arg); 131503b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 131603b705cfSriastradh return xf86SetSingleMode(scrn, mode, RR_Rotate_0); 131703b705cfSriastradh} 131803b705cfSriastradh 131903b705cfSriastradhstatic ModeStatus 132003b705cfSriastradhsna_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 132103b705cfSriastradh{ 132203b705cfSriastradh return MODE_OK; 132303b705cfSriastradh} 132403b705cfSriastradh 132503b705cfSriastradh#ifndef SUSPEND_SLEEP 132603b705cfSriastradh#define SUSPEND_SLEEP 0 132703b705cfSriastradh#endif 132803b705cfSriastradh#ifndef RESUME_SLEEP 132903b705cfSriastradh#define RESUME_SLEEP 0 133003b705cfSriastradh#endif 133103b705cfSriastradh 133203b705cfSriastradh/* 133303b705cfSriastradh * This function is only required if we need to do anything differently from 133403b705cfSriastradh * DoApmEvent() in common/xf86PM.c, including if we want to see events other 133503b705cfSriastradh * than suspend/resume. 133603b705cfSriastradh */ 133703b705cfSriastradhstatic Bool sna_pm_event(SCRN_ARG_TYPE arg, pmEvent event, Bool undo) 133803b705cfSriastradh{ 133903b705cfSriastradh SCRN_INFO_PTR(arg); 134003b705cfSriastradh struct sna *sna = to_sna(scrn); 134103b705cfSriastradh 134203b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 134303b705cfSriastradh 134403b705cfSriastradh switch (event) { 134503b705cfSriastradh case XF86_APM_SYS_SUSPEND: 134603b705cfSriastradh case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */ 134703b705cfSriastradh case XF86_APM_USER_SUSPEND: 134803b705cfSriastradh case XF86_APM_SYS_STANDBY: 134903b705cfSriastradh case XF86_APM_USER_STANDBY: 135003b705cfSriastradh if (!undo && !sna->suspended) { 135103b705cfSriastradh scrn->LeaveVT(VT_FUNC_ARGS(0)); 135203b705cfSriastradh sna->suspended = TRUE; 135303b705cfSriastradh sleep(SUSPEND_SLEEP); 135403b705cfSriastradh } else if (undo && sna->suspended) { 135503b705cfSriastradh sleep(RESUME_SLEEP); 135603b705cfSriastradh scrn->EnterVT(VT_FUNC_ARGS(0)); 135703b705cfSriastradh sna->suspended = FALSE; 135803b705cfSriastradh } 135903b705cfSriastradh break; 136003b705cfSriastradh case XF86_APM_STANDBY_RESUME: 136103b705cfSriastradh case XF86_APM_NORMAL_RESUME: 136203b705cfSriastradh case XF86_APM_CRITICAL_RESUME: 136303b705cfSriastradh if (sna->suspended) { 136403b705cfSriastradh sleep(RESUME_SLEEP); 136503b705cfSriastradh scrn->EnterVT(VT_FUNC_ARGS(0)); 136603b705cfSriastradh sna->suspended = FALSE; 136703b705cfSriastradh /* 136803b705cfSriastradh * Turn the screen saver off when resuming. This seems to be 136903b705cfSriastradh * needed to stop xscreensaver kicking in (when used). 137003b705cfSriastradh * 137103b705cfSriastradh * XXX DoApmEvent() should probably call this just like 137203b705cfSriastradh * xf86VTSwitch() does. Maybe do it here only in 4.2 137303b705cfSriastradh * compatibility mode. 137403b705cfSriastradh */ 137503b705cfSriastradh SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 137603b705cfSriastradh } 137703b705cfSriastradh break; 137803b705cfSriastradh /* This is currently used for ACPI */ 137903b705cfSriastradh case XF86_APM_CAPABILITY_CHANGED: 138003b705cfSriastradh SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 138103b705cfSriastradh break; 138203b705cfSriastradh 138303b705cfSriastradh default: 138442542f5fSchristos ERR(("sna_pm_event: received APM event %d\n", event)); 138503b705cfSriastradh } 138603b705cfSriastradh return TRUE; 138703b705cfSriastradh} 138803b705cfSriastradh 138903b705cfSriastradhstatic Bool sna_enter_vt__hosted(VT_FUNC_ARGS_DECL) 139003b705cfSriastradh{ 139103b705cfSriastradh return TRUE; 139203b705cfSriastradh} 139303b705cfSriastradh 139403b705cfSriastradhstatic void sna_leave_vt__hosted(VT_FUNC_ARGS_DECL) 139503b705cfSriastradh{ 139603b705cfSriastradh} 139703b705cfSriastradh 139842542f5fSchristosstatic void describe_kms(ScrnInfoPtr scrn) 139942542f5fSchristos{ 140042542f5fSchristos int fd = __intel_peek_fd(scrn); 140142542f5fSchristos drm_version_t version; 140242542f5fSchristos char name[128] = ""; 140342542f5fSchristos char date[128] = ""; 140442542f5fSchristos 140542542f5fSchristos memset(&version, 0, sizeof(version)); 140642542f5fSchristos version.name_len = sizeof(name) - 1; 140742542f5fSchristos version.name = name; 140842542f5fSchristos version.date_len = sizeof(date) - 1; 140942542f5fSchristos version.date = date; 141042542f5fSchristos 141142542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_VERSION, &version)) 141242542f5fSchristos return; 141342542f5fSchristos 141442542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_INFO, 141542542f5fSchristos "Using Kernel Mode Setting driver: %s, version %d.%d.%d %s\n", 141642542f5fSchristos version.name, 141742542f5fSchristos version.version_major, version.version_minor, version.version_patchlevel, 141842542f5fSchristos version.date); 141942542f5fSchristos} 142042542f5fSchristos 142142542f5fSchristosstatic void describe_sna(ScrnInfoPtr scrn) 142203b705cfSriastradh{ 142303b705cfSriastradh#if defined(USE_GIT_DESCRIBE) 142403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 142503b705cfSriastradh "SNA compiled from %s\n", git_version); 142603b705cfSriastradh#elif defined(BUILDER_DESCRIPTION) 142703b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 142803b705cfSriastradh "SNA compiled: %s\n", BUILDER_DESCRIPTION); 142903b705cfSriastradh#endif 143063ef14f0Smrg#if HAS_DEBUG_FULL 143163ef14f0Smrg ErrorF("SNA compiled with full debug logging; expect to run slowly\n"); 143263ef14f0Smrg#endif 143303b705cfSriastradh#if !NDEBUG 143403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 143503b705cfSriastradh "SNA compiled with assertions enabled\n"); 143603b705cfSriastradh#endif 143703b705cfSriastradh#if DEBUG_SYNC 143803b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 143903b705cfSriastradh "SNA compiled with synchronous rendering\n"); 144003b705cfSriastradh#endif 144103b705cfSriastradh#if DEBUG_MEMORY 144203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 144303b705cfSriastradh "SNA compiled with memory allocation reporting enabled\n"); 144403b705cfSriastradh#endif 144503b705cfSriastradh#if DEBUG_PIXMAP 144603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 144703b705cfSriastradh "SNA compiled with extra pixmap/damage validation\n"); 144842542f5fSchristos#endif 144942542f5fSchristos#ifdef HAVE_VALGRIND 145042542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_INFO, 145142542f5fSchristos "SNA compiled for use with valgrind\n"); 145242542f5fSchristos VALGRIND_PRINTF("SNA compiled for use with valgrind\n"); 145303b705cfSriastradh#endif 145463ef14f0Smrg DBG(("xf86-video-intel version: %s\n", git_version)); 145503b705cfSriastradh DBG(("pixman version: %s\n", pixman_version_string())); 145642542f5fSchristos} 145742542f5fSchristos 145842542f5fSchristosBool sna_init_scrn(ScrnInfoPtr scrn, int entity_num) 145942542f5fSchristos{ 146042542f5fSchristos DBG(("%s: entity_num=%d\n", __FUNCTION__, entity_num)); 146142542f5fSchristos describe_kms(scrn); 146242542f5fSchristos describe_sna(scrn); 146303b705cfSriastradh 146403b705cfSriastradh scrn->PreInit = sna_pre_init; 146503b705cfSriastradh scrn->ScreenInit = sna_screen_init; 146603b705cfSriastradh if (!hosted()) { 146703b705cfSriastradh scrn->SwitchMode = sna_switch_mode; 146803b705cfSriastradh scrn->AdjustFrame = sna_adjust_frame; 146903b705cfSriastradh scrn->EnterVT = sna_enter_vt; 147003b705cfSriastradh scrn->LeaveVT = sna_leave_vt; 147103b705cfSriastradh scrn->ValidMode = sna_valid_mode; 147203b705cfSriastradh scrn->PMEvent = sna_pm_event; 147303b705cfSriastradh } else { 147403b705cfSriastradh scrn->EnterVT = sna_enter_vt__hosted; 147503b705cfSriastradh scrn->LeaveVT = sna_leave_vt__hosted; 147603b705cfSriastradh } 147703b705cfSriastradh scrn->FreeScreen = sna_free_screen; 147803b705cfSriastradh 147903b705cfSriastradh xf86SetEntitySharable(entity_num); 148003b705cfSriastradh xf86SetEntityInstanceForScreen(scrn, entity_num, 148103b705cfSriastradh xf86GetNumEntityInstances(entity_num)-1); 148203b705cfSriastradh 148303b705cfSriastradh sna_threads_init(); 148403b705cfSriastradh 148503b705cfSriastradh return TRUE; 148603b705cfSriastradh} 148742542f5fSchristos 148842542f5fSchristos#if HAS_DEBUG_FULL 148942542f5fSchristos_X_ATTRIBUTE_PRINTF(1, 0) void LogF(const char *f, ...) 149042542f5fSchristos{ 149142542f5fSchristos va_list ap; 149242542f5fSchristos 149342542f5fSchristos /* As we not only may be called from any context, we may also 149442542f5fSchristos * be called from a thread whilst the main thread is handling 149542542f5fSchristos * signals, therefore we have to use the signal-safe variants 149642542f5fSchristos * or else we trip over false positive assertions. 149742542f5fSchristos */ 149842542f5fSchristos 149942542f5fSchristos va_start(ap, f); 150042542f5fSchristos#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0) 150142542f5fSchristos LogVMessageVerbSigSafe(X_NONE, 1, f, ap); 150242542f5fSchristos#else 150342542f5fSchristos LogVMessageVerb(X_NONE, 1, f, ap); 150442542f5fSchristos#endif 150542542f5fSchristos va_end(ap); 150642542f5fSchristos} 150742542f5fSchristos#endif 1508