sna_display_fake.c revision fe8aea9e
1/* 2 * Copyright © 2013 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Chris Wilson <chris@chris-wilson.co.uk> 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "sna.h" 33 34static bool add_fake_output(struct sna *sna, bool late); 35 36static void 37sna_crtc_dpms(xf86CrtcPtr crtc, int mode) 38{ 39} 40 41static char *outputs_for_crtc(xf86CrtcPtr crtc, char *outputs, int max) 42{ 43 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 44 int len, i; 45 46 for (i = len = 0; i < config->num_output; i++) { 47 xf86OutputPtr output = config->output[i]; 48 49 if (output->crtc != crtc) 50 continue; 51 52 len += snprintf(outputs+len, max-len, "%s, ", output->name); 53 } 54 assert(len >= 2); 55 outputs[len-2] = '\0'; 56 57 return outputs; 58} 59 60static const char *rotation_to_str(Rotation rotation) 61{ 62 switch (rotation & RR_Rotate_All) { 63 case 0: 64 case RR_Rotate_0: return "normal"; 65 case RR_Rotate_90: return "left"; 66 case RR_Rotate_180: return "inverted"; 67 case RR_Rotate_270: return "right"; 68 default: return "unknown"; 69 } 70} 71 72static const char *reflection_to_str(Rotation rotation) 73{ 74 switch (rotation & RR_Reflect_All) { 75 case 0: return "none"; 76 case RR_Reflect_X: return "X axis"; 77 case RR_Reflect_Y: return "Y axis"; 78 case RR_Reflect_X | RR_Reflect_Y: return "X and Y axes"; 79 default: return "invalid"; 80 } 81} 82 83static Bool 84sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 85 Rotation rotation, int x, int y) 86{ 87 char outputs[256]; 88 89 xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO, 90 "switch to mode %dx%d on %s, position (%d, %d), rotation %s, reflection %s\n", 91 mode->HDisplay, mode->VDisplay, 92 outputs_for_crtc(crtc, outputs, sizeof(outputs)), 93 x, y, rotation_to_str(rotation), reflection_to_str(rotation)); 94 95 return TRUE; 96} 97 98static void 99sna_crtc_destroy(xf86CrtcPtr crtc) 100{ 101} 102 103static const xf86CrtcFuncsRec sna_crtc_funcs = { 104 .dpms = sna_crtc_dpms, 105 .set_mode_major = sna_crtc_set_mode_major, 106 .destroy = sna_crtc_destroy, 107}; 108 109static void 110sna_output_create_resources(xf86OutputPtr output) 111{ 112} 113 114static Bool 115sna_output_set_property(xf86OutputPtr output, Atom property, 116 RRPropertyValuePtr value) 117{ 118 return TRUE; 119} 120 121static Bool 122sna_output_get_property(xf86OutputPtr output, Atom property) 123{ 124 return FALSE; 125} 126 127static void 128sna_output_dpms(xf86OutputPtr output, int dpms) 129{ 130} 131 132static xf86OutputStatus 133sna_output_detect(xf86OutputPtr output) 134{ 135 DBG(("%s(%s) has user modes? %d\n", 136 __FUNCTION__, output->name, 137 output->randr_output && output->randr_output->numUserModes)); 138 139 if (output->randr_output && output->randr_output->numUserModes) { 140 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(output->scrn); 141 142 if (xf86_config->output[xf86_config->num_output-1] == output) 143 add_fake_output(to_sna(output->scrn), true); 144 145 return XF86OutputStatusConnected; 146 } 147 148 return XF86OutputStatusDisconnected; 149} 150 151static Bool 152sna_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode) 153{ 154 if (mode->type & M_T_DEFAULT) 155 return MODE_BAD; 156 157 return MODE_OK; 158} 159 160static DisplayModePtr 161sna_output_get_modes(xf86OutputPtr output) 162{ 163 return NULL; 164} 165 166static void 167sna_output_destroy(xf86OutputPtr output) 168{ 169} 170 171static const xf86OutputFuncsRec sna_output_funcs = { 172 .create_resources = sna_output_create_resources, 173#ifdef RANDR_12_INTERFACE 174 .set_property = sna_output_set_property, 175 .get_property = sna_output_get_property, 176#endif 177 .dpms = sna_output_dpms, 178 .detect = sna_output_detect, 179 .mode_valid = sna_output_mode_valid, 180 181 .get_modes = sna_output_get_modes, 182 .destroy = sna_output_destroy 183}; 184 185static Bool 186sna_mode_resize(ScrnInfoPtr scrn, int width, int height) 187{ 188 ScreenPtr screen = xf86ScrnToScreen(scrn); 189 PixmapPtr new_front; 190 191 DBG(("%s (%d, %d) -> (%d, %d)\n", __FUNCTION__, 192 scrn->virtualX, scrn->virtualY, 193 width, height)); 194 195 if (scrn->virtualX == width && scrn->virtualY == height) 196 return TRUE; 197 198 assert(to_sna_from_screen(screen)->front); 199 assert(screen->GetScreenPixmap(screen) == to_sna_from_screen(screen)->front); 200 201 DBG(("%s: creating new framebuffer %dx%d\n", 202 __FUNCTION__, width, height)); 203 204 new_front = screen->CreatePixmap(screen, 205 width, height, scrn->depth, 206 0); 207 if (!new_front) 208 return FALSE; 209 210 scrn->virtualX = width; 211 scrn->virtualY = height; 212 scrn->displayWidth = width; 213 214 screen->SetScreenPixmap(new_front); 215 assert(screen->GetScreenPixmap(screen) == new_front); 216 assert(to_sna_from_screen(screen)->front == new_front); 217 218 screen->DestroyPixmap(new_front); 219 220 return TRUE; 221} 222 223static const xf86CrtcConfigFuncsRec sna_mode_funcs = { 224 sna_mode_resize 225}; 226 227static bool add_fake_output(struct sna *sna, bool late) 228{ 229 ScrnInfoPtr scrn = sna->scrn; 230 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 231 xf86OutputPtr output; 232 xf86CrtcPtr crtc; 233 RROutputPtr clones[32]; 234 RRCrtcPtr crtcs[32]; 235 char buf[80]; 236 int i, len; 237 238 if (sna->mode.num_fake >= 32) 239 return false; 240 241 DBG(("%s(late=%d, num_fake=%d)\n", __FUNCTION__, late, sna->mode.num_fake+1)); 242 243 crtc = xf86CrtcCreate(scrn, &sna_crtc_funcs); 244 if (crtc == NULL) 245 return false; 246 247 len = sprintf(buf, "VIRTUAL%d", sna->mode.num_fake+1); 248 output = xf86OutputCreate(scrn, &sna_output_funcs, buf); 249 if (!output) { 250 xf86CrtcDestroy(crtc); 251 return false; 252 } 253 254 output->mm_width = 0; 255 output->mm_height = 0; 256 output->interlaceAllowed = FALSE; 257 output->subpixel_order = SubPixelNone; 258 output->status = XF86OutputStatusDisconnected; 259 260 output->possible_crtcs = ~((1 << sna->mode.num_real_crtc) - 1); 261 output->possible_clones = ~((1 << sna->mode.num_real_output) - 1); 262 263 if (late) { 264 ScreenPtr screen = xf86ScrnToScreen(scrn); 265 266 crtc->randr_crtc = RRCrtcCreate(screen, crtc); 267 output->randr_output = RROutputCreate(screen, buf, len, output); 268 if (crtc->randr_crtc == NULL || output->randr_output == NULL) { 269 xf86OutputDestroy(output); 270 xf86CrtcDestroy(crtc); 271 return false; 272 } 273 274 RRPostPendingProperties(output->randr_output); 275 276 for (i = sna->mode.num_real_output; i < xf86_config->num_output; i++) 277 clones[i - sna->mode.num_real_output] = xf86_config->output[i]->randr_output; 278 assert(i - sna->mode.num_real_output == sna->mode.num_fake + 1); 279 280 for (i = sna->mode.num_real_crtc; i < xf86_config->num_crtc; i++) 281 crtcs[i - sna->mode.num_real_crtc] = xf86_config->crtc[i]->randr_crtc; 282 assert(i - sna->mode.num_real_crtc == sna->mode.num_fake + 1); 283 284 for (i = sna->mode.num_real_output; i < xf86_config->num_output; i++) { 285 RROutputPtr rr_output = xf86_config->output[i]->randr_output; 286 287 if (!RROutputSetCrtcs(rr_output, crtcs, sna->mode.num_fake + 1) || 288 !RROutputSetClones(rr_output, clones, sna->mode.num_fake + 1)) 289 goto err; 290 } 291 292 RRCrtcSetRotations(crtc->randr_crtc, 293 RR_Rotate_All | RR_Reflect_All); 294 if (!RRCrtcGammaSetSize(crtc->randr_crtc, 256)) 295 goto err; 296 } 297 298 sna->mode.num_fake++; 299 xf86DrvMsg(scrn->scrnIndex, X_INFO, 300 "Enabled output %s\n", 301 output->name); 302 return true; 303 304err: 305 for (i = 0; i < xf86_config->num_output; i++) { 306 output = xf86_config->output[i]; 307 if (output->driver_private) 308 continue; 309 310 xf86OutputDestroy(output); 311 i--; 312 } 313 314 for (i = 0; i < xf86_config->num_crtc; i++) { 315 crtc = xf86_config->crtc[i]; 316 if (crtc->driver_private) 317 continue; 318 319 xf86CrtcDestroy(crtc); 320 i--; 321 } 322 sna->mode.num_fake = -1; 323 return false; 324} 325 326bool sna_mode_fake_init(struct sna *sna, int num_fake) 327{ 328 bool ret; 329 330 if (num_fake == 0) 331 return true; 332 333 if (sna->mode.num_real_crtc == 0) { 334 xf86CrtcConfigInit(sna->scrn, &sna_mode_funcs); 335 xf86CrtcSetSizeRange(sna->scrn, 1, 1, INT16_MAX, INT16_MAX); 336 } 337 338 ret = true; 339 while (ret && num_fake--) 340 ret = add_fake_output(sna, false); 341 return ret; 342} 343