2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
38 #include "xorg-server.h"
42 #include <cursorstr.h>
43 #include "xorg_tracker.h"
44 #include "xf86Modes.h"
46 #ifdef HAVE_XEXTPROTO_71
47 #include <X11/extensions/dpmsconst.h>
50 #include <X11/extensions/dpms.h>
53 #include "state_tracker/drm_driver.h"
54 #include "util/u_inlines.h"
55 #include "util/u_rect.h"
58 #include "libkms/libkms.h"
63 drmModeCrtcPtr drm_crtc
;
66 struct pipe_resource
*cursor_tex
;
67 struct kms_bo
*cursor_bo
;
69 unsigned cursor_handle
;
73 crtc_dpms(xf86CrtcPtr crtc
, int mode
)
75 /* ScrnInfoPtr pScrn = crtc->scrn; */
88 crtc_set_mode_major(xf86CrtcPtr crtc
, DisplayModePtr mode
,
89 Rotation rotation
, int x
, int y
)
91 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(crtc
->scrn
);
92 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
93 xf86OutputPtr output
= NULL
;
94 struct crtc_private
*crtcp
= crtc
->driver_private
;
95 drmModeCrtcPtr drm_crtc
= crtcp
->drm_crtc
;
96 drmModeModeInfo drm_mode
;
98 unsigned int connector_id
;
100 for (i
= 0; i
< config
->num_output
; output
= NULL
, i
++) {
101 output
= config
->output
[i
];
103 if (output
->crtc
== crtc
)
110 connector_id
= xorg_output_get_id(output
);
112 drm_mode
.clock
= mode
->Clock
;
113 drm_mode
.hdisplay
= mode
->HDisplay
;
114 drm_mode
.hsync_start
= mode
->HSyncStart
;
115 drm_mode
.hsync_end
= mode
->HSyncEnd
;
116 drm_mode
.htotal
= mode
->HTotal
;
117 drm_mode
.vdisplay
= mode
->VDisplay
;
118 drm_mode
.vsync_start
= mode
->VSyncStart
;
119 drm_mode
.vsync_end
= mode
->VSyncEnd
;
120 drm_mode
.vtotal
= mode
->VTotal
;
121 drm_mode
.flags
= mode
->Flags
;
122 drm_mode
.hskew
= mode
->HSkew
;
123 drm_mode
.vscan
= mode
->VScan
;
124 drm_mode
.vrefresh
= mode
->VRefresh
;
127 xf86SetModeDefaultName(mode
);
128 strncpy(drm_mode
.name
, mode
->name
, DRM_DISPLAY_MODE_LEN
- 1);
129 drm_mode
.name
[DRM_DISPLAY_MODE_LEN
- 1] = '\0';
131 ret
= drmModeSetCrtc(ms
->fd
, drm_crtc
->crtc_id
, ms
->fb_id
, x
, y
,
132 &connector_id
, 1, &drm_mode
);
137 /* Only set gamma when needed, to avoid unneeded delays. */
138 #if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
139 if (!crtc
->active
&& crtc
->version
>= 3)
140 crtc
->funcs
->gamma_set(crtc
, crtc
->gamma_red
, crtc
->gamma_green
,
141 crtc
->gamma_blue
, crtc
->gamma_size
);
148 crtc
->rotation
= rotation
;
154 crtc_gamma_set(xf86CrtcPtr crtc
, CARD16
* red
, CARD16
* green
, CARD16
* blue
,
157 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
158 struct crtc_private
*crtcp
= crtc
->driver_private
;
160 drmModeCrtcSetGamma(ms
->fd
, crtcp
->drm_crtc
->crtc_id
, size
, red
, green
, blue
);
163 #if 0 /* Implement and enable to enable rotation and reflection. */
165 crtc_shadow_allocate(xf86CrtcPtr crtc
, int width
, int height
)
167 /* ScrnInfoPtr pScrn = crtc->scrn; */
173 crtc_shadow_create(xf86CrtcPtr crtc
, void *data
, int width
, int height
)
175 /* ScrnInfoPtr pScrn = crtc->scrn; */
181 crtc_shadow_destroy(xf86CrtcPtr crtc
, PixmapPtr rotate_pixmap
, void *data
)
183 /* ScrnInfoPtr pScrn = crtc->scrn; */
193 crtc_set_cursor_colors(xf86CrtcPtr crtc
, int bg
, int fg
)
195 /* XXX: See if this one is needed, as we only support ARGB cursors */
199 crtc_set_cursor_position(xf86CrtcPtr crtc
, int x
, int y
)
201 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
202 struct crtc_private
*crtcp
= crtc
->driver_private
;
204 drmModeMoveCursor(ms
->fd
, crtcp
->drm_crtc
->crtc_id
, x
, y
);
208 crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc
, CARD32
* image
)
211 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
212 struct crtc_private
*crtcp
= crtc
->driver_private
;
213 struct pipe_transfer
*transfer
;
214 struct pipe_fence_handle
*fence
= NULL
;
215 struct pipe_context
*ctx
= ms
->ctx
;
216 struct pipe_screen
*screen
= ms
->screen
;
218 if (!crtcp
->cursor_tex
) {
219 struct pipe_resource templat
;
220 struct winsys_handle whandle
;
222 memset(&templat
, 0, sizeof(templat
));
223 templat
.bind
|= PIPE_BIND_RENDER_TARGET
;
224 templat
.bind
|= PIPE_BIND_SCANOUT
;
225 templat
.bind
|= PIPE_BIND_CURSOR
;
226 templat
.target
= PIPE_TEXTURE_2D
;
227 templat
.last_level
= 0;
229 templat
.array_size
= 1;
230 templat
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
232 templat
.height0
= 64;
234 memset(&whandle
, 0, sizeof(whandle
));
235 whandle
.type
= DRM_API_HANDLE_TYPE_KMS
;
237 crtcp
->cursor_tex
= screen
->resource_create(screen
, &templat
);
238 screen
->resource_get_handle(screen
, crtcp
->cursor_tex
, &whandle
);
240 crtcp
->cursor_handle
= whandle
.handle
;
243 transfer
= pipe_get_transfer(ctx
, crtcp
->cursor_tex
,
247 ptr
= ctx
->transfer_map(ctx
, transfer
);
248 util_copy_rect(ptr
, crtcp
->cursor_tex
->format
,
249 transfer
->stride
, 0, 0,
250 64, 64, (void*)image
, 64 * 4, 0, 0);
251 ctx
->transfer_unmap(ctx
, transfer
);
252 ctx
->transfer_destroy(ctx
, transfer
);
253 ctx
->flush(ctx
, &fence
);
256 screen
->fence_finish(screen
, fence
, PIPE_TIMEOUT_INFINITE
);
257 screen
->fence_reference(screen
, &fence
, NULL
);
260 if (crtc
->cursor_shown
)
261 drmModeSetCursor(ms
->fd
, crtcp
->drm_crtc
->crtc_id
,
262 crtcp
->cursor_handle
, 64, 64);
267 crtc_load_cursor_argb_kms(xf86CrtcPtr crtc
, CARD32
* image
)
269 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
270 struct crtc_private
*crtcp
= crtc
->driver_private
;
273 if (!crtcp
->cursor_bo
) {
276 attr
[0] = KMS_BO_TYPE
;
277 #ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8
278 attr
[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8
;
280 attr
[1] = KMS_BO_TYPE_CURSOR
;
284 attr
[4] = KMS_HEIGHT
;
288 if (kms_bo_create(ms
->kms
, attr
, &crtcp
->cursor_bo
))
291 if (kms_bo_get_prop(crtcp
->cursor_bo
, KMS_HANDLE
,
292 &crtcp
->cursor_handle
))
296 kms_bo_map(crtcp
->cursor_bo
, (void**)&ptr
);
297 memcpy(ptr
, image
, 64*64*4);
298 kms_bo_unmap(crtcp
->cursor_bo
);
300 if (crtc
->cursor_shown
)
301 drmModeSetCursor(ms
->fd
, crtcp
->drm_crtc
->crtc_id
,
302 crtcp
->cursor_handle
, 64, 64);
307 kms_bo_destroy(&crtcp
->cursor_bo
);
312 crtc_load_cursor_argb(xf86CrtcPtr crtc
, CARD32
* image
)
314 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(crtc
->scrn
);
315 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
317 /* Older X servers have cursor reference counting bugs leading to use of
318 * freed memory and consequently random crashes. Should be fixed as of
319 * xserver 1.8, but this workaround shouldn't hurt anyway.
322 config
->cursor
->refcnt
++;
325 FreeCursor(ms
->cursor
, None
);
327 ms
->cursor
= config
->cursor
;
330 crtc_load_cursor_argb_ga3d(crtc
, image
);
333 crtc_load_cursor_argb_kms(crtc
, image
);
338 crtc_show_cursor(xf86CrtcPtr crtc
)
340 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
341 struct crtc_private
*crtcp
= crtc
->driver_private
;
343 if (crtcp
->cursor_tex
|| crtcp
->cursor_bo
)
344 drmModeSetCursor(ms
->fd
, crtcp
->drm_crtc
->crtc_id
,
345 crtcp
->cursor_handle
, 64, 64);
349 crtc_hide_cursor(xf86CrtcPtr crtc
)
351 modesettingPtr ms
= modesettingPTR(crtc
->scrn
);
352 struct crtc_private
*crtcp
= crtc
->driver_private
;
354 drmModeSetCursor(ms
->fd
, crtcp
->drm_crtc
->crtc_id
, 0, 0, 0);
361 xorg_crtc_cursor_destroy(xf86CrtcPtr crtc
)
363 struct crtc_private
*crtcp
= crtc
->driver_private
;
365 if (crtcp
->cursor_tex
)
366 pipe_resource_reference(&crtcp
->cursor_tex
, NULL
);
368 if (crtcp
->cursor_bo
)
369 kms_bo_destroy(&crtcp
->cursor_bo
);
378 crtc_destroy(xf86CrtcPtr crtc
)
380 struct crtc_private
*crtcp
= crtc
->driver_private
;
382 xorg_crtc_cursor_destroy(crtc
);
384 drmModeFreeCrtc(crtcp
->drm_crtc
);
387 crtc
->driver_private
= NULL
;
390 static const xf86CrtcFuncsRec crtc_funcs
= {
392 .set_mode_major
= crtc_set_mode_major
,
394 .set_cursor_colors
= crtc_set_cursor_colors
,
395 .set_cursor_position
= crtc_set_cursor_position
,
396 .show_cursor
= crtc_show_cursor
,
397 .hide_cursor
= crtc_hide_cursor
,
398 .load_cursor_argb
= crtc_load_cursor_argb
,
400 .shadow_create
= NULL
,
401 .shadow_allocate
= NULL
,
402 .shadow_destroy
= NULL
,
404 .gamma_set
= crtc_gamma_set
,
405 .destroy
= crtc_destroy
,
409 xorg_crtc_init(ScrnInfoPtr pScrn
)
411 modesettingPtr ms
= modesettingPTR(pScrn
);
414 drmModeCrtcPtr drm_crtc
= NULL
;
415 struct crtc_private
*crtcp
;
418 res
= drmModeGetResources(ms
->fd
);
420 ErrorF("Failed drmModeGetResources %d\n", errno
);
424 for (c
= 0; c
< res
->count_crtcs
; c
++) {
425 drm_crtc
= drmModeGetCrtc(ms
->fd
, res
->crtcs
[c
]);
430 crtc
= xf86CrtcCreate(pScrn
, &crtc_funcs
);
434 crtcp
= calloc(1, sizeof(struct crtc_private
));
436 xf86CrtcDestroy(crtc
);
440 crtcp
->drm_crtc
= drm_crtc
;
442 crtc
->driver_private
= crtcp
;
446 drmModeFreeResources(res
);
449 /* vim: set sw=4 ts=8 sts=4: */