OSDN Git Service

gallium: Convert state trackers to drm driver interface
[android-x86/external-mesa.git] / src / gallium / state_trackers / xorg / xorg_crtc.c
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 <cursorstr.h>
43 #include "xorg_tracker.h"
44 #include "xf86Modes.h"
45
46 #ifdef HAVE_XEXTPROTO_71
47 #include <X11/extensions/dpmsconst.h>
48 #else
49 #define DPMS_SERVER
50 #include <X11/extensions/dpms.h>
51 #endif
52
53 #include "state_tracker/drm_driver.h"
54 #include "util/u_inlines.h"
55 #include "util/u_rect.h"
56
57 #ifdef HAVE_LIBKMS
58 #include "libkms.h"
59 #endif
60
61 struct crtc_private
62 {
63     drmModeCrtcPtr drm_crtc;
64
65     /* hwcursor */
66     struct pipe_resource *cursor_tex;
67     struct kms_bo *cursor_bo;
68
69     unsigned cursor_handle;
70 };
71
72 static void
73 crtc_dpms(xf86CrtcPtr crtc, int mode)
74 {
75     /* ScrnInfoPtr pScrn = crtc->scrn; */
76
77     switch (mode) {
78     case DPMSModeOn:
79     case DPMSModeStandby:
80     case DPMSModeSuspend:
81         break;
82     case DPMSModeOff:
83         break;
84     }
85 }
86
87 static Bool
88 crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
89                     Rotation rotation, int x, int y)
90 {
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;
97     int i, ret, connector_id;
98
99     for (i = 0; i < config->num_output; output = NULL, i++) {
100         output = config->output[i];
101
102         if (output->crtc == crtc)
103             break;
104     }
105
106     if (!output)
107         return FALSE;
108
109     connector_id = xorg_output_get_id(output);
110
111     drm_mode.clock = mode->Clock;
112     drm_mode.hdisplay = mode->HDisplay;
113     drm_mode.hsync_start = mode->HSyncStart;
114     drm_mode.hsync_end = mode->HSyncEnd;
115     drm_mode.htotal = mode->HTotal;
116     drm_mode.vdisplay = mode->VDisplay;
117     drm_mode.vsync_start = mode->VSyncStart;
118     drm_mode.vsync_end = mode->VSyncEnd;
119     drm_mode.vtotal = mode->VTotal;
120     drm_mode.flags = mode->Flags;
121     drm_mode.hskew = mode->HSkew;
122     drm_mode.vscan = mode->VScan;
123     drm_mode.vrefresh = mode->VRefresh;
124     if (!mode->name)
125         xf86SetModeDefaultName(mode);
126     strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1);
127     drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0';
128
129     ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
130                          &connector_id, 1, &drm_mode);
131
132     if (ret)
133         return FALSE;
134
135     crtc->x = x;
136     crtc->y = y;
137     crtc->mode = *mode;
138     crtc->rotation = rotation;
139
140     return TRUE;
141 }
142
143 static void
144 crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
145                int size)
146 {
147     /* XXX: hockup */
148 }
149
150 #if 0 /* Implement and enable to enable rotation and reflection. */
151 static void *
152 crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
153 {
154     /* ScrnInfoPtr pScrn = crtc->scrn; */
155
156     return NULL;
157 }
158
159 static PixmapPtr
160 crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
161 {
162     /* ScrnInfoPtr pScrn = crtc->scrn; */
163
164     return NULL;
165 }
166
167 static void
168 crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
169 {
170     /* ScrnInfoPtr pScrn = crtc->scrn; */
171 }
172
173 #endif
174
175 /*
176  * Cursor functions
177  */
178
179 static void
180 crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
181 {
182     /* XXX: See if this one is needed, as we only support ARGB cursors */
183 }
184
185 static void
186 crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
187 {
188     modesettingPtr ms = modesettingPTR(crtc->scrn);
189     struct crtc_private *crtcp = crtc->driver_private;
190
191     drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
192 }
193
194 static void
195 crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image)
196 {
197     unsigned char *ptr;
198     modesettingPtr ms = modesettingPTR(crtc->scrn);
199     struct crtc_private *crtcp = crtc->driver_private;
200     struct pipe_transfer *transfer;
201
202     if (!crtcp->cursor_tex) {
203         struct pipe_resource templat;
204         struct winsys_handle whandle;
205
206         memset(&templat, 0, sizeof(templat));
207         templat.bind |= PIPE_BIND_RENDER_TARGET;
208         templat.bind |= PIPE_BIND_SCANOUT;
209         templat.target = PIPE_TEXTURE_2D;
210         templat.last_level = 0;
211         templat.depth0 = 1;
212         templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
213         templat.width0 = 64;
214         templat.height0 = 64;
215
216         memset(&whandle, 0, sizeof(whandle));
217         whandle.type = DRM_API_HANDLE_TYPE_KMS;
218
219         crtcp->cursor_tex = ms->screen->resource_create(ms->screen,
220                                                        &templat);
221         ms->screen->resource_get_handle(ms->screen, crtcp->cursor_tex, &whandle);
222
223         crtcp->cursor_handle = whandle.handle;
224     }
225
226     transfer = pipe_get_transfer(ms->ctx, crtcp->cursor_tex,
227                                          0, 0, 0,
228                                          PIPE_TRANSFER_WRITE,
229                                          0, 0, 64, 64);
230     ptr = ms->ctx->transfer_map(ms->ctx, transfer);
231     util_copy_rect(ptr, crtcp->cursor_tex->format,
232                    transfer->stride, 0, 0,
233                    64, 64, (void*)image, 64 * 4, 0, 0);
234     ms->ctx->transfer_unmap(ms->ctx, transfer);
235     ms->ctx->transfer_destroy(ms->ctx, transfer);
236 }
237
238 #if HAVE_LIBKMS
239 static void
240 crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image)
241 {
242     modesettingPtr ms = modesettingPTR(crtc->scrn);
243     struct crtc_private *crtcp = crtc->driver_private;
244     unsigned char *ptr;
245
246     if (!crtcp->cursor_bo) {
247         unsigned attr[8];
248
249         attr[0] = KMS_BO_TYPE;
250 #ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8
251         attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
252 #else
253         attr[1] = KMS_BO_TYPE_CURSOR;
254 #endif
255         attr[2] = KMS_WIDTH;
256         attr[3] = 64;
257         attr[4] = KMS_HEIGHT;
258         attr[5] = 64;
259         attr[6] = 0;
260
261         if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo))
262            return;
263
264         if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE,
265                             &crtcp->cursor_handle))
266             goto err_bo_destroy;
267     }
268
269     kms_bo_map(crtcp->cursor_bo, (void**)&ptr);
270     memcpy(ptr, image, 64*64*4);
271     kms_bo_unmap(crtcp->cursor_bo);
272
273     return;
274
275 err_bo_destroy:
276     kms_bo_destroy(&crtcp->cursor_bo);
277 }
278 #endif
279
280 static void
281 crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
282 {
283     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
284     modesettingPtr ms = modesettingPTR(crtc->scrn);
285
286     /* Older X servers have cursor reference counting bugs leading to use of
287      * freed memory and consequently random crashes. Should be fixed as of
288      * xserver 1.8, but this workaround shouldn't hurt anyway.
289      */
290     if (config->cursor)
291        config->cursor->refcnt++;
292
293     if (ms->cursor)
294        FreeCursor(ms->cursor, None);
295
296     ms->cursor = config->cursor;
297
298     if (ms->screen)
299         crtc_load_cursor_argb_ga3d(crtc, image);
300 #ifdef HAVE_LIBKMS
301     else if (ms->kms)
302         crtc_load_cursor_argb_kms(crtc, image);
303 #endif
304 }
305
306 static void
307 crtc_show_cursor(xf86CrtcPtr crtc)
308 {
309     modesettingPtr ms = modesettingPTR(crtc->scrn);
310     struct crtc_private *crtcp = crtc->driver_private;
311
312     if (crtcp->cursor_tex || crtcp->cursor_bo)
313         drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
314                          crtcp->cursor_handle, 64, 64);
315 }
316
317 static void
318 crtc_hide_cursor(xf86CrtcPtr crtc)
319 {
320     modesettingPtr ms = modesettingPTR(crtc->scrn);
321     struct crtc_private *crtcp = crtc->driver_private;
322
323     drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
324 }
325
326 /**
327  * Called at vt leave
328  */
329 void
330 xorg_crtc_cursor_destroy(xf86CrtcPtr crtc)
331 {
332     struct crtc_private *crtcp = crtc->driver_private;
333
334     if (crtcp->cursor_tex)
335         pipe_resource_reference(&crtcp->cursor_tex, NULL);
336 #ifdef HAVE_LIBKMS
337     if (crtcp->cursor_bo)
338         kms_bo_destroy(&crtcp->cursor_bo);
339 #endif
340 }
341
342 /*
343  * Misc functions
344  */
345
346 static void
347 crtc_destroy(xf86CrtcPtr crtc)
348 {
349     struct crtc_private *crtcp = crtc->driver_private;
350
351     xorg_crtc_cursor_destroy(crtc);
352
353     drmModeFreeCrtc(crtcp->drm_crtc);
354
355     xfree(crtcp);
356     crtc->driver_private = NULL;
357 }
358
359 static const xf86CrtcFuncsRec crtc_funcs = {
360     .dpms = crtc_dpms,
361     .set_mode_major = crtc_set_mode_major,
362
363     .set_cursor_colors = crtc_set_cursor_colors,
364     .set_cursor_position = crtc_set_cursor_position,
365     .show_cursor = crtc_show_cursor,
366     .hide_cursor = crtc_hide_cursor,
367     .load_cursor_argb = crtc_load_cursor_argb,
368
369     .shadow_create = NULL,
370     .shadow_allocate = NULL,
371     .shadow_destroy = NULL,
372
373     .gamma_set = crtc_gamma_set,
374     .destroy = crtc_destroy,
375 };
376
377 void
378 xorg_crtc_init(ScrnInfoPtr pScrn)
379 {
380     modesettingPtr ms = modesettingPTR(pScrn);
381     xf86CrtcPtr crtc;
382     drmModeResPtr res;
383     drmModeCrtcPtr drm_crtc = NULL;
384     struct crtc_private *crtcp;
385     int c;
386
387     res = drmModeGetResources(ms->fd);
388     if (res == 0) {
389         ErrorF("Failed drmModeGetResources %d\n", errno);
390         return;
391     }
392
393     for (c = 0; c < res->count_crtcs; c++) {
394         drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]);
395
396         if (!drm_crtc)
397             continue;
398
399         crtc = xf86CrtcCreate(pScrn, &crtc_funcs);
400         if (crtc == NULL)
401             goto out;
402
403         crtcp = xcalloc(1, sizeof(struct crtc_private));
404         if (!crtcp) {
405             xf86CrtcDestroy(crtc);
406             goto out;
407         }
408
409         crtcp->drm_crtc = drm_crtc;
410
411         crtc->driver_private = crtcp;
412     }
413
414   out:
415     drmModeFreeResources(res);
416 }
417
418 /* vim: set sw=4 ts=8 sts=4: */