xorg_crtc.c revision 28486880ca3ec39419ccee0cb1a3bedc9ef7117c
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 unsigned pitch; 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 crtcp->cursor_tex = ms->screen->texture_create(ms->screen, 213 &templat); 214 ms->api->local_handle_from_texture(ms->api, 215 ms->screen, 216 crtcp->cursor_tex, 217 &pitch, 218 &crtcp->cursor_handle); 219 } 220 221 transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex, 222 0, 0, 0, 223 PIPE_TRANSFER_WRITE, 224 0, 0, 64, 64); 225 ptr = ms->screen->transfer_map(ms->screen, transfer); 226 util_copy_rect(ptr, crtcp->cursor_tex->format, 227 transfer->stride, 0, 0, 228 64, 64, (void*)image, 64 * 4, 0, 0); 229 ms->screen->transfer_unmap(ms->screen, transfer); 230 ms->screen->tex_transfer_destroy(transfer); 231} 232 233#if HAVE_LIBKMS 234static void 235crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) 236{ 237 modesettingPtr ms = modesettingPTR(crtc->scrn); 238 struct crtc_private *crtcp = crtc->driver_private; 239 unsigned char *ptr; 240 241 if (!crtcp->cursor_bo) { 242 unsigned attr[8]; 243 244 attr[0] = KMS_BO_TYPE; 245#ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8 246 attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; 247#else 248 attr[1] = KMS_BO_TYPE_CURSOR; 249#endif 250 attr[2] = KMS_WIDTH; 251 attr[3] = 64; 252 attr[4] = KMS_HEIGHT; 253 attr[5] = 64; 254 attr[6] = 0; 255 256 if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo)) 257 return; 258 259 if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE, 260 &crtcp->cursor_handle)) 261 goto err_bo_destroy; 262 } 263 264 kms_bo_map(crtcp->cursor_bo, (void**)&ptr); 265 memcpy(ptr, image, 64*64*4); 266 kms_bo_unmap(crtcp->cursor_bo); 267 268 return; 269 270err_bo_destroy: 271 kms_bo_destroy(&crtcp->cursor_bo); 272} 273#endif 274 275static void 276crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) 277{ 278 modesettingPtr ms = modesettingPTR(crtc->scrn); 279 if (ms->screen) 280 crtc_load_cursor_argb_ga3d(crtc, image); 281#ifdef HAVE_LIBKMS 282 else if (ms->kms) 283 crtc_load_cursor_argb_kms(crtc, image); 284#endif 285} 286 287static void 288crtc_show_cursor(xf86CrtcPtr crtc) 289{ 290 modesettingPtr ms = modesettingPTR(crtc->scrn); 291 struct crtc_private *crtcp = crtc->driver_private; 292 293 if (crtcp->cursor_tex || crtcp->cursor_bo) 294 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 295 crtcp->cursor_handle, 64, 64); 296} 297 298static void 299crtc_hide_cursor(xf86CrtcPtr crtc) 300{ 301 modesettingPtr ms = modesettingPTR(crtc->scrn); 302 struct crtc_private *crtcp = crtc->driver_private; 303 304 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0); 305} 306 307/** 308 * Called at vt leave 309 */ 310void 311xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) 312{ 313 struct crtc_private *crtcp = crtc->driver_private; 314 315 if (crtcp->cursor_tex) 316 pipe_texture_reference(&crtcp->cursor_tex, NULL); 317#ifdef HAVE_LIBKMS 318 if (crtcp->cursor_bo) 319 kms_bo_destroy(&crtcp->cursor_bo); 320#endif 321} 322 323/* 324 * Misc functions 325 */ 326 327static void 328crtc_destroy(xf86CrtcPtr crtc) 329{ 330 struct crtc_private *crtcp = crtc->driver_private; 331 332 xorg_crtc_cursor_destroy(crtc); 333 334 drmModeFreeCrtc(crtcp->drm_crtc); 335 336 xfree(crtcp); 337 crtc->driver_private = NULL; 338} 339 340static const xf86CrtcFuncsRec crtc_funcs = { 341 .dpms = crtc_dpms, 342 .set_mode_major = crtc_set_mode_major, 343 344 .set_cursor_colors = crtc_set_cursor_colors, 345 .set_cursor_position = crtc_set_cursor_position, 346 .show_cursor = crtc_show_cursor, 347 .hide_cursor = crtc_hide_cursor, 348 .load_cursor_argb = crtc_load_cursor_argb, 349 350 .shadow_create = crtc_shadow_create, 351 .shadow_allocate = crtc_shadow_allocate, 352 .shadow_destroy = crtc_shadow_destroy, 353 354 .gamma_set = crtc_gamma_set, 355 .destroy = crtc_destroy, 356}; 357 358void 359xorg_crtc_init(ScrnInfoPtr pScrn) 360{ 361 modesettingPtr ms = modesettingPTR(pScrn); 362 xf86CrtcPtr crtc; 363 drmModeResPtr res; 364 drmModeCrtcPtr drm_crtc = NULL; 365 struct crtc_private *crtcp; 366 int c; 367 368 res = drmModeGetResources(ms->fd); 369 if (res == 0) { 370 ErrorF("Failed drmModeGetResources %d\n", errno); 371 return; 372 } 373 374 for (c = 0; c < res->count_crtcs; c++) { 375 drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]); 376 377 if (!drm_crtc) 378 continue; 379 380 crtc = xf86CrtcCreate(pScrn, &crtc_funcs); 381 if (crtc == NULL) 382 goto out; 383 384 crtcp = xcalloc(1, sizeof(struct crtc_private)); 385 if (!crtcp) { 386 xf86CrtcDestroy(crtc); 387 goto out; 388 } 389 390 crtcp->drm_crtc = drm_crtc; 391 392 crtc->driver_private = crtcp; 393 } 394 395 out: 396 drmModeFreeResources(res); 397} 398 399/* vim: set sw=4 ts=8 sts=4: */ 400