Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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/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;
  98.     unsigned int connector_id;
  99.  
  100.     for (i = 0; i < config->num_output; output = NULL, i++) {
  101.         output = config->output[i];
  102.  
  103.         if (output->crtc == crtc)
  104.             break;
  105.     }
  106.  
  107.     if (!output)
  108.         return FALSE;
  109.  
  110.     connector_id = xorg_output_get_id(output);
  111.  
  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;
  125.     drm_mode.type = 0;
  126.     if (!mode->name)
  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';
  130.  
  131.     ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
  132.                          &connector_id, 1, &drm_mode);
  133.  
  134.     if (ret)
  135.         return FALSE;
  136.  
  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);
  142.     crtc->active = TRUE;
  143. #endif
  144.  
  145.     crtc->x = x;
  146.     crtc->y = y;
  147.     crtc->mode = *mode;
  148.     crtc->rotation = rotation;
  149.  
  150.     return TRUE;
  151. }
  152.  
  153. static void
  154. crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
  155.                int size)
  156. {
  157.     modesettingPtr ms = modesettingPTR(crtc->scrn);
  158.     struct crtc_private *crtcp = crtc->driver_private;
  159.  
  160.     drmModeCrtcSetGamma(ms->fd, crtcp->drm_crtc->crtc_id, size, red, green, blue);
  161. }
  162.  
  163. #if 0 /* Implement and enable to enable rotation and reflection. */
  164. static void *
  165. crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
  166. {
  167.     /* ScrnInfoPtr pScrn = crtc->scrn; */
  168.  
  169.     return NULL;
  170. }
  171.  
  172. static PixmapPtr
  173. crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
  174. {
  175.     /* ScrnInfoPtr pScrn = crtc->scrn; */
  176.  
  177.     return NULL;
  178. }
  179.  
  180. static void
  181. crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
  182. {
  183.     /* ScrnInfoPtr pScrn = crtc->scrn; */
  184. }
  185.  
  186. #endif
  187.  
  188. /*
  189.  * Cursor functions
  190.  */
  191.  
  192. static void
  193. crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
  194. {
  195.     /* XXX: See if this one is needed, as we only support ARGB cursors */
  196. }
  197.  
  198. static void
  199. crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
  200. {
  201.     modesettingPtr ms = modesettingPTR(crtc->scrn);
  202.     struct crtc_private *crtcp = crtc->driver_private;
  203.  
  204.     drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
  205. }
  206.  
  207. static void
  208. crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image)
  209. {
  210.     unsigned char *ptr;
  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;
  217.  
  218.     if (!crtcp->cursor_tex) {
  219.         struct pipe_resource templat;
  220.         struct winsys_handle whandle;
  221.  
  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;
  228.         templat.depth0 = 1;
  229.         templat.array_size = 1;
  230.         templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  231.         templat.width0 = 64;
  232.         templat.height0 = 64;
  233.  
  234.         memset(&whandle, 0, sizeof(whandle));
  235.         whandle.type = DRM_API_HANDLE_TYPE_KMS;
  236.  
  237.         crtcp->cursor_tex = screen->resource_create(screen, &templat);
  238.         screen->resource_get_handle(screen, crtcp->cursor_tex, &whandle);
  239.  
  240.         crtcp->cursor_handle = whandle.handle;
  241.     }
  242.  
  243.     ptr = pipe_transfer_map(ctx, crtcp->cursor_tex,
  244.                             0, 0,
  245.                             PIPE_TRANSFER_WRITE,
  246.                             0, 0, 64, 64, &transfer);
  247.     util_copy_rect(ptr, crtcp->cursor_tex->format,
  248.                    transfer->stride, 0, 0,
  249.                    64, 64, (void*)image, 64 * 4, 0, 0);
  250.     ctx->transfer_unmap(ctx, transfer);
  251.     ctx->flush(ctx, &fence, 0);
  252.  
  253.     if (fence) {
  254.         screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
  255.         screen->fence_reference(screen, &fence, NULL);
  256.     }
  257.  
  258.     if (crtc->cursor_shown)
  259.         drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
  260.                          crtcp->cursor_handle, 64, 64);
  261. }
  262.  
  263. #if HAVE_LIBKMS
  264. static void
  265. crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image)
  266. {
  267.     modesettingPtr ms = modesettingPTR(crtc->scrn);
  268.     struct crtc_private *crtcp = crtc->driver_private;
  269.     unsigned char *ptr;
  270.  
  271.     if (!crtcp->cursor_bo) {
  272.         unsigned attr[8];
  273.  
  274.         attr[0] = KMS_BO_TYPE;
  275. #ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8
  276.         attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
  277. #else
  278.         attr[1] = KMS_BO_TYPE_CURSOR;
  279. #endif
  280.         attr[2] = KMS_WIDTH;
  281.         attr[3] = 64;
  282.         attr[4] = KMS_HEIGHT;
  283.         attr[5] = 64;
  284.         attr[6] = 0;
  285.  
  286.         if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo))
  287.            return;
  288.  
  289.         if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE,
  290.                             &crtcp->cursor_handle))
  291.             goto err_bo_destroy;
  292.     }
  293.  
  294.     kms_bo_map(crtcp->cursor_bo, (void**)&ptr);
  295.     memcpy(ptr, image, 64*64*4);
  296.     kms_bo_unmap(crtcp->cursor_bo);
  297.  
  298.     if (crtc->cursor_shown)
  299.         drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
  300.                          crtcp->cursor_handle, 64, 64);
  301.  
  302.     return;
  303.  
  304. err_bo_destroy:
  305.     kms_bo_destroy(&crtcp->cursor_bo);
  306. }
  307. #endif
  308.  
  309. static void
  310. crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
  311. {
  312.     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
  313.     modesettingPtr ms = modesettingPTR(crtc->scrn);
  314.  
  315.     /* Older X servers have cursor reference counting bugs leading to use of
  316.      * freed memory and consequently random crashes. Should be fixed as of
  317.      * xserver 1.8, but this workaround shouldn't hurt anyway.
  318.      */
  319.     if (config->cursor)
  320.        config->cursor->refcnt++;
  321.  
  322.     if (ms->cursor)
  323.        FreeCursor(ms->cursor, None);
  324.  
  325.     ms->cursor = config->cursor;
  326.  
  327.     if (ms->screen)
  328.         crtc_load_cursor_argb_ga3d(crtc, image);
  329. #ifdef HAVE_LIBKMS
  330.     else if (ms->kms)
  331.         crtc_load_cursor_argb_kms(crtc, image);
  332. #endif
  333. }
  334.  
  335. static void
  336. crtc_show_cursor(xf86CrtcPtr crtc)
  337. {
  338.     modesettingPtr ms = modesettingPTR(crtc->scrn);
  339.     struct crtc_private *crtcp = crtc->driver_private;
  340.  
  341.     if (crtcp->cursor_tex || crtcp->cursor_bo)
  342.         drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
  343.                          crtcp->cursor_handle, 64, 64);
  344. }
  345.  
  346. static void
  347. crtc_hide_cursor(xf86CrtcPtr crtc)
  348. {
  349.     modesettingPtr ms = modesettingPTR(crtc->scrn);
  350.     struct crtc_private *crtcp = crtc->driver_private;
  351.  
  352.     drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
  353. }
  354.  
  355. /**
  356.  * Called at vt leave
  357.  */
  358. void
  359. xorg_crtc_cursor_destroy(xf86CrtcPtr crtc)
  360. {
  361.     struct crtc_private *crtcp = crtc->driver_private;
  362.  
  363.     if (crtcp->cursor_tex)
  364.         pipe_resource_reference(&crtcp->cursor_tex, NULL);
  365. #ifdef HAVE_LIBKMS
  366.     if (crtcp->cursor_bo)
  367.         kms_bo_destroy(&crtcp->cursor_bo);
  368. #endif
  369. }
  370.  
  371. /*
  372.  * Misc functions
  373.  */
  374.  
  375. static void
  376. crtc_destroy(xf86CrtcPtr crtc)
  377. {
  378.     struct crtc_private *crtcp = crtc->driver_private;
  379.  
  380.     xorg_crtc_cursor_destroy(crtc);
  381.  
  382.     drmModeFreeCrtc(crtcp->drm_crtc);
  383.  
  384.     free(crtcp);
  385.     crtc->driver_private = NULL;
  386. }
  387.  
  388. static const xf86CrtcFuncsRec crtc_funcs = {
  389.     .dpms = crtc_dpms,
  390.     .set_mode_major = crtc_set_mode_major,
  391.  
  392.     .set_cursor_colors = crtc_set_cursor_colors,
  393.     .set_cursor_position = crtc_set_cursor_position,
  394.     .show_cursor = crtc_show_cursor,
  395.     .hide_cursor = crtc_hide_cursor,
  396.     .load_cursor_argb = crtc_load_cursor_argb,
  397.  
  398.     .shadow_create = NULL,
  399.     .shadow_allocate = NULL,
  400.     .shadow_destroy = NULL,
  401.  
  402.     .gamma_set = crtc_gamma_set,
  403.     .destroy = crtc_destroy,
  404. };
  405.  
  406. void
  407. xorg_crtc_init(ScrnInfoPtr pScrn)
  408. {
  409.     modesettingPtr ms = modesettingPTR(pScrn);
  410.     xf86CrtcPtr crtc;
  411.     drmModeResPtr res;
  412.     drmModeCrtcPtr drm_crtc = NULL;
  413.     struct crtc_private *crtcp;
  414.     int c;
  415.  
  416.     res = drmModeGetResources(ms->fd);
  417.     if (res == 0) {
  418.         ErrorF("Failed drmModeGetResources %d\n", errno);
  419.         return;
  420.     }
  421.  
  422.     for (c = 0; c < res->count_crtcs; c++) {
  423.         drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]);
  424.  
  425.         if (!drm_crtc)
  426.             continue;
  427.  
  428.         crtc = xf86CrtcCreate(pScrn, &crtc_funcs);
  429.         if (crtc == NULL)
  430.             goto out;
  431.  
  432.         crtcp = calloc(1, sizeof(struct crtc_private));
  433.         if (!crtcp) {
  434.             xf86CrtcDestroy(crtc);
  435.             goto out;
  436.         }
  437.  
  438.         crtcp->drm_crtc = drm_crtc;
  439.  
  440.         crtc->driver_private = crtcp;
  441.     }
  442.  
  443.   out:
  444.     drmModeFreeResources(res);
  445. }
  446.  
  447. /* vim: set sw=4 ts=8 sts=4: */
  448.