xorg_crtc.c revision ee40b20e7aff5dc9d11230e991355c338a64da00
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 "pipe/p_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 switch (mode) { 74 case DPMSModeOn: 75 case DPMSModeStandby: 76 case DPMSModeSuspend: 77 break; 78 case DPMSModeOff: 79 break; 80 } 81} 82 83static Bool 84crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 85 Rotation rotation, int x, int y) 86{ 87 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 88 modesettingPtr ms = modesettingPTR(crtc->scrn); 89 xf86OutputPtr output = NULL; 90 drmModeConnectorPtr drm_connector; 91 struct crtc_private *crtcp = crtc->driver_private; 92 drmModeCrtcPtr drm_crtc = crtcp->drm_crtc; 93 drmModeModeInfo drm_mode; 94 int i, ret; 95 96 for (i = 0; i < config->num_output; output = NULL, i++) { 97 output = config->output[i]; 98 99 if (output->crtc == crtc) 100 break; 101 } 102 103 if (!output) 104 return FALSE; 105 106 drm_connector = output->driver_private; 107 108 drm_mode.clock = mode->Clock; 109 drm_mode.hdisplay = mode->HDisplay; 110 drm_mode.hsync_start = mode->HSyncStart; 111 drm_mode.hsync_end = mode->HSyncEnd; 112 drm_mode.htotal = mode->HTotal; 113 drm_mode.vdisplay = mode->VDisplay; 114 drm_mode.vsync_start = mode->VSyncStart; 115 drm_mode.vsync_end = mode->VSyncEnd; 116 drm_mode.vtotal = mode->VTotal; 117 drm_mode.flags = mode->Flags; 118 drm_mode.hskew = mode->HSkew; 119 drm_mode.vscan = mode->VScan; 120 drm_mode.vrefresh = mode->VRefresh; 121 if (!mode->name) 122 xf86SetModeDefaultName(mode); 123 strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN); 124 125 ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y, 126 &drm_connector->connector_id, 1, &drm_mode); 127 128 if (ret) 129 return FALSE; 130 131 crtc->x = x; 132 crtc->y = y; 133 crtc->mode = *mode; 134 crtc->rotation = rotation; 135 136 return TRUE; 137} 138 139static void 140crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue, 141 int size) 142{ 143 /* XXX: hockup */ 144} 145 146static void * 147crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 148{ 149 return NULL; 150} 151 152static PixmapPtr 153crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 154{ 155 return NULL; 156} 157 158static void 159crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 160{ 161} 162 163/* 164 * Cursor functions 165 */ 166 167static void 168crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 169{ 170 /* XXX: See if this one is needed, as we only support ARGB cursors */ 171} 172 173static void 174crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) 175{ 176 modesettingPtr ms = modesettingPTR(crtc->scrn); 177 struct crtc_private *crtcp = crtc->driver_private; 178 179 drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y); 180} 181 182static void 183crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) 184{ 185 unsigned char *ptr; 186 modesettingPtr ms = modesettingPTR(crtc->scrn); 187 struct crtc_private *crtcp = crtc->driver_private; 188 struct pipe_transfer *transfer; 189 190 if (!crtcp->cursor_tex) { 191 struct pipe_texture templat; 192 unsigned pitch; 193 194 memset(&templat, 0, sizeof(templat)); 195 templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; 196 templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; 197 templat.target = PIPE_TEXTURE_2D; 198 templat.last_level = 0; 199 templat.depth[0] = 1; 200 templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; 201 templat.width[0] = 64; 202 templat.height[0] = 64; 203 pf_get_block(templat.format, &templat.block); 204 205 crtcp->cursor_tex = ms->screen->texture_create(ms->screen, 206 &templat); 207 ms->api->local_handle_from_texture(ms->api, 208 ms->screen, 209 crtcp->cursor_tex, 210 &pitch, 211 &crtcp->cursor_handle); 212 } 213 214 transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex, 215 0, 0, 0, 216 PIPE_TRANSFER_WRITE, 217 0, 0, 64, 64); 218 ptr = ms->screen->transfer_map(ms->screen, transfer); 219 util_copy_rect(ptr, &crtcp->cursor_tex->block, 220 transfer->stride, 0, 0, 221 64, 64, (void*)image, 64 * 4, 0, 0); 222 ms->screen->transfer_unmap(ms->screen, transfer); 223 ms->screen->tex_transfer_destroy(transfer); 224} 225 226#if HAVE_LIBKMS 227static void 228crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) 229{ 230 modesettingPtr ms = modesettingPTR(crtc->scrn); 231 struct crtc_private *crtcp = crtc->driver_private; 232 unsigned char *ptr; 233 234 if (!crtcp->cursor_bo) { 235 unsigned attr[8]; 236 237 attr[0] = KMS_BO_TYPE; 238 attr[1] = KMS_BO_TYPE_CURSOR; 239 attr[2] = KMS_WIDTH; 240 attr[3] = 64; 241 attr[4] = KMS_HEIGHT; 242 attr[5] = 64; 243 attr[6] = 0; 244 245 if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo)) 246 return; 247 248 if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE, 249 &crtcp->cursor_handle)) 250 goto err_bo_destroy; 251 } 252 253 kms_bo_map(crtcp->cursor_bo, (void**)&ptr); 254 memcpy(ptr, image, 64*64*4); 255 kms_bo_unmap(crtcp->cursor_bo); 256 257 return; 258 259err_bo_destroy: 260 kms_bo_destroy(crtcp->cursor_bo); 261} 262#endif 263 264static void 265crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) 266{ 267 modesettingPtr ms = modesettingPTR(crtc->scrn); 268 if (ms->screen) 269 crtc_load_cursor_argb_ga3d(crtc, image); 270#ifdef HAVE_LIBKMS 271 else if (ms->kms) 272 crtc_load_cursor_argb_kms(crtc, image); 273#endif 274} 275 276static void 277crtc_show_cursor(xf86CrtcPtr crtc) 278{ 279 modesettingPtr ms = modesettingPTR(crtc->scrn); 280 struct crtc_private *crtcp = crtc->driver_private; 281 282 if (crtcp->cursor_tex || crtcp->cursor_bo) 283 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 284 crtcp->cursor_handle, 64, 64); 285} 286 287static void 288crtc_hide_cursor(xf86CrtcPtr crtc) 289{ 290 modesettingPtr ms = modesettingPTR(crtc->scrn); 291 struct crtc_private *crtcp = crtc->driver_private; 292 293 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0); 294} 295 296/** 297 * Called at vt leave 298 */ 299void 300xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) 301{ 302 struct crtc_private *crtcp = crtc->driver_private; 303 304 if (crtcp->cursor_tex) 305 pipe_texture_reference(&crtcp->cursor_tex, NULL); 306#ifdef HAVE_LIBKMS 307 if (crtcp->cursor_bo) 308 kms_bo_destroy(crtcp->cursor_bo); 309#endif 310 311 xfree(crtcp); 312} 313 314/* 315 * Misc functions 316 */ 317 318static void 319crtc_destroy(xf86CrtcPtr crtc) 320{ 321 struct crtc_private *crtcp = crtc->driver_private; 322 323 if (crtcp->cursor_tex) 324 pipe_texture_reference(&crtcp->cursor_tex, NULL); 325 326 drmModeFreeCrtc(crtcp->drm_crtc); 327 xfree(crtcp); 328} 329 330static const xf86CrtcFuncsRec crtc_funcs = { 331 .dpms = crtc_dpms, 332 .set_mode_major = crtc_set_mode_major, 333 334 .set_cursor_colors = crtc_set_cursor_colors, 335 .set_cursor_position = crtc_set_cursor_position, 336 .show_cursor = crtc_show_cursor, 337 .hide_cursor = crtc_hide_cursor, 338 .load_cursor_argb = crtc_load_cursor_argb, 339 340 .shadow_create = crtc_shadow_create, 341 .shadow_allocate = crtc_shadow_allocate, 342 .shadow_destroy = crtc_shadow_destroy, 343 344 .gamma_set = crtc_gamma_set, 345 .destroy = crtc_destroy, 346}; 347 348void 349xorg_crtc_init(ScrnInfoPtr pScrn) 350{ 351 modesettingPtr ms = modesettingPTR(pScrn); 352 xf86CrtcPtr crtc; 353 drmModeResPtr res; 354 drmModeCrtcPtr drm_crtc = NULL; 355 struct crtc_private *crtcp; 356 int c; 357 358 res = drmModeGetResources(ms->fd); 359 if (res == 0) { 360 ErrorF("Failed drmModeGetResources %d\n", errno); 361 return; 362 } 363 364 for (c = 0; c < res->count_crtcs; c++) { 365 drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]); 366 367 if (!drm_crtc) 368 continue; 369 370 crtc = xf86CrtcCreate(pScrn, &crtc_funcs); 371 if (crtc == NULL) 372 goto out; 373 374 crtcp = xcalloc(1, sizeof(struct crtc_private)); 375 if (!crtcp) { 376 xf86CrtcDestroy(crtc); 377 goto out; 378 } 379 380 crtcp->drm_crtc = drm_crtc; 381 382 crtc->driver_private = crtcp; 383 } 384 385 out: 386 drmModeFreeResources(res); 387} 388 389/* vim: set sw=4 ts=8 sts=4: */ 390