xorg_crtc.c revision b2e94d05c9602e2814a513a51eed67d014b338f3
1/* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * 26 * Author: Alan Hourihane <alanh@tungstengraphics.com> 27 * Author: Jakob Bornecrantz <wallbraker@gmail.com> 28 * 29 */ 30 31#include <unistd.h> 32#include <string.h> 33#include <assert.h> 34#include <stdlib.h> 35#include <math.h> 36#include <stdint.h> 37 38#include "xorg-server.h" 39#include <xf86.h> 40#include <xf86i2c.h> 41#include <xf86Crtc.h> 42#include "xorg_tracker.h" 43#include "xf86Modes.h" 44 45#ifdef HAVE_XEXTPROTO_71 46#include <X11/extensions/dpmsconst.h> 47#else 48#define DPMS_SERVER 49#include <X11/extensions/dpms.h> 50#endif 51 52#include "util/u_inlines.h" 53#include "util/u_rect.h" 54 55#ifdef HAVE_LIBKMS 56#include "libkms.h" 57#endif 58 59struct crtc_private 60{ 61 drmModeCrtcPtr drm_crtc; 62 63 /* hwcursor */ 64 struct pipe_texture *cursor_tex; 65 struct kms_bo *cursor_bo; 66 67 unsigned cursor_handle; 68}; 69 70static void 71crtc_dpms(xf86CrtcPtr crtc, int mode) 72{ 73 /* ScrnInfoPtr pScrn = crtc->scrn; */ 74 75 switch (mode) { 76 case DPMSModeOn: 77 case DPMSModeStandby: 78 case DPMSModeSuspend: 79 break; 80 case DPMSModeOff: 81 break; 82 } 83} 84 85static Bool 86crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 87 Rotation rotation, int x, int y) 88{ 89 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 90 modesettingPtr ms = modesettingPTR(crtc->scrn); 91 xf86OutputPtr output = NULL; 92 drmModeConnectorPtr drm_connector; 93 struct crtc_private *crtcp = crtc->driver_private; 94 drmModeCrtcPtr drm_crtc = crtcp->drm_crtc; 95 drmModeModeInfo drm_mode; 96 int i, ret; 97 98 for (i = 0; i < config->num_output; output = NULL, i++) { 99 output = config->output[i]; 100 101 if (output->crtc == crtc) 102 break; 103 } 104 105 if (!output) 106 return FALSE; 107 108 drm_connector = output->driver_private; 109 110 drm_mode.clock = mode->Clock; 111 drm_mode.hdisplay = mode->HDisplay; 112 drm_mode.hsync_start = mode->HSyncStart; 113 drm_mode.hsync_end = mode->HSyncEnd; 114 drm_mode.htotal = mode->HTotal; 115 drm_mode.vdisplay = mode->VDisplay; 116 drm_mode.vsync_start = mode->VSyncStart; 117 drm_mode.vsync_end = mode->VSyncEnd; 118 drm_mode.vtotal = mode->VTotal; 119 drm_mode.flags = mode->Flags; 120 drm_mode.hskew = mode->HSkew; 121 drm_mode.vscan = mode->VScan; 122 drm_mode.vrefresh = mode->VRefresh; 123 if (!mode->name) 124 xf86SetModeDefaultName(mode); 125 strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1); 126 drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0'; 127 128 ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y, 129 &drm_connector->connector_id, 1, &drm_mode); 130 131 if (ret) 132 return FALSE; 133 134 crtc->x = x; 135 crtc->y = y; 136 crtc->mode = *mode; 137 crtc->rotation = rotation; 138 139 return TRUE; 140} 141 142static void 143crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue, 144 int size) 145{ 146 /* XXX: hockup */ 147} 148 149static void * 150crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 151{ 152 /* ScrnInfoPtr pScrn = crtc->scrn; */ 153 154 return NULL; 155} 156 157static PixmapPtr 158crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 159{ 160 /* ScrnInfoPtr pScrn = crtc->scrn; */ 161 162 return NULL; 163} 164 165static void 166crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 167{ 168 /* ScrnInfoPtr pScrn = crtc->scrn; */ 169} 170 171/* 172 * Cursor functions 173 */ 174 175static void 176crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 177{ 178 /* XXX: See if this one is needed, as we only support ARGB cursors */ 179} 180 181static void 182crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) 183{ 184 modesettingPtr ms = modesettingPTR(crtc->scrn); 185 struct crtc_private *crtcp = crtc->driver_private; 186 187 drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y); 188} 189 190static void 191crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) 192{ 193 unsigned char *ptr; 194 modesettingPtr ms = modesettingPTR(crtc->scrn); 195 struct crtc_private *crtcp = crtc->driver_private; 196 struct pipe_transfer *transfer; 197 198 if (!crtcp->cursor_tex) { 199 struct pipe_texture templat; 200 struct winsys_handle whandle; 201 202 memset(&templat, 0, sizeof(templat)); 203 templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; 204 templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; 205 templat.target = PIPE_TEXTURE_2D; 206 templat.last_level = 0; 207 templat.depth0 = 1; 208 templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; 209 templat.width0 = 64; 210 templat.height0 = 64; 211 212 memset(&whandle, 0, sizeof(whandle)); 213 whandle.type = DRM_API_HANDLE_TYPE_KMS; 214 215 crtcp->cursor_tex = ms->screen->texture_create(ms->screen, 216 &templat); 217 ms->screen->texture_get_handle(ms->screen, crtcp->cursor_tex, &whandle); 218 219 crtcp->cursor_handle = whandle.handle; 220 } 221 222 transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex, 223 0, 0, 0, 224 PIPE_TRANSFER_WRITE, 225 0, 0, 64, 64); 226 ptr = ms->screen->transfer_map(ms->screen, transfer); 227 util_copy_rect(ptr, crtcp->cursor_tex->format, 228 transfer->stride, 0, 0, 229 64, 64, (void*)image, 64 * 4, 0, 0); 230 ms->screen->transfer_unmap(ms->screen, transfer); 231 ms->screen->tex_transfer_destroy(transfer); 232} 233 234#if HAVE_LIBKMS 235static void 236crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) 237{ 238 modesettingPtr ms = modesettingPTR(crtc->scrn); 239 struct crtc_private *crtcp = crtc->driver_private; 240 unsigned char *ptr; 241 242 if (!crtcp->cursor_bo) { 243 unsigned attr[8]; 244 245 attr[0] = KMS_BO_TYPE; 246#ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8 247 attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; 248#else 249 attr[1] = KMS_BO_TYPE_CURSOR; 250#endif 251 attr[2] = KMS_WIDTH; 252 attr[3] = 64; 253 attr[4] = KMS_HEIGHT; 254 attr[5] = 64; 255 attr[6] = 0; 256 257 if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo)) 258 return; 259 260 if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE, 261 &crtcp->cursor_handle)) 262 goto err_bo_destroy; 263 } 264 265 kms_bo_map(crtcp->cursor_bo, (void**)&ptr); 266 memcpy(ptr, image, 64*64*4); 267 kms_bo_unmap(crtcp->cursor_bo); 268 269 return; 270 271err_bo_destroy: 272 kms_bo_destroy(&crtcp->cursor_bo); 273} 274#endif 275 276static void 277crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) 278{ 279 modesettingPtr ms = modesettingPTR(crtc->scrn); 280 if (ms->screen) 281 crtc_load_cursor_argb_ga3d(crtc, image); 282#ifdef HAVE_LIBKMS 283 else if (ms->kms) 284 crtc_load_cursor_argb_kms(crtc, image); 285#endif 286} 287 288static void 289crtc_show_cursor(xf86CrtcPtr crtc) 290{ 291 modesettingPtr ms = modesettingPTR(crtc->scrn); 292 struct crtc_private *crtcp = crtc->driver_private; 293 294 if (crtcp->cursor_tex || crtcp->cursor_bo) 295 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 296 crtcp->cursor_handle, 64, 64); 297} 298 299static void 300crtc_hide_cursor(xf86CrtcPtr crtc) 301{ 302 modesettingPtr ms = modesettingPTR(crtc->scrn); 303 struct crtc_private *crtcp = crtc->driver_private; 304 305 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0); 306} 307 308/** 309 * Called at vt leave 310 */ 311void 312xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) 313{ 314 struct crtc_private *crtcp = crtc->driver_private; 315 316 if (crtcp->cursor_tex) 317 pipe_texture_reference(&crtcp->cursor_tex, NULL); 318#ifdef HAVE_LIBKMS 319 if (crtcp->cursor_bo) 320 kms_bo_destroy(&crtcp->cursor_bo); 321#endif 322} 323 324/* 325 * Misc functions 326 */ 327 328static void 329crtc_destroy(xf86CrtcPtr crtc) 330{ 331 struct crtc_private *crtcp = crtc->driver_private; 332 333 xorg_crtc_cursor_destroy(crtc); 334 335 drmModeFreeCrtc(crtcp->drm_crtc); 336 337 xfree(crtcp); 338 crtc->driver_private = NULL; 339} 340 341static const xf86CrtcFuncsRec crtc_funcs = { 342 .dpms = crtc_dpms, 343 .set_mode_major = crtc_set_mode_major, 344 345 .set_cursor_colors = crtc_set_cursor_colors, 346 .set_cursor_position = crtc_set_cursor_position, 347 .show_cursor = crtc_show_cursor, 348 .hide_cursor = crtc_hide_cursor, 349 .load_cursor_argb = crtc_load_cursor_argb, 350 351 .shadow_create = crtc_shadow_create, 352 .shadow_allocate = crtc_shadow_allocate, 353 .shadow_destroy = crtc_shadow_destroy, 354 355 .gamma_set = crtc_gamma_set, 356 .destroy = crtc_destroy, 357}; 358 359void 360xorg_crtc_init(ScrnInfoPtr pScrn) 361{ 362 modesettingPtr ms = modesettingPTR(pScrn); 363 xf86CrtcPtr crtc; 364 drmModeResPtr res; 365 drmModeCrtcPtr drm_crtc = NULL; 366 struct crtc_private *crtcp; 367 int c; 368 369 res = drmModeGetResources(ms->fd); 370 if (res == 0) { 371 ErrorF("Failed drmModeGetResources %d\n", errno); 372 return; 373 } 374 375 for (c = 0; c < res->count_crtcs; c++) { 376 drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]); 377 378 if (!drm_crtc) 379 continue; 380 381 crtc = xf86CrtcCreate(pScrn, &crtc_funcs); 382 if (crtc == NULL) 383 goto out; 384 385 crtcp = xcalloc(1, sizeof(struct crtc_private)); 386 if (!crtcp) { 387 xf86CrtcDestroy(crtc); 388 goto out; 389 } 390 391 crtcp->drm_crtc = drm_crtc; 392 393 crtc->driver_private = crtcp; 394 } 395 396 out: 397 drmModeFreeResources(res); 398} 399 400/* vim: set sw=4 ts=8 sts=4: */ 401