Merge branch '7.8'
[mesa.git] / src / gallium / state_trackers / xorg / xorg_crtc.c
index 85b9162d4cf5cde3fb95e0e2559a009900c2be62..7268a79a23d2209472b236f2d9c433faca2f4b91 100644 (file)
 #include <X11/extensions/dpms.h>
 #endif
 
-#include "pipe/p_inlines.h"
+#include "util/u_inlines.h"
 #include "util/u_rect.h"
 
+#ifdef HAVE_LIBKMS
+#include "libkms.h"
+#endif
+
 struct crtc_private
 {
     drmModeCrtcPtr drm_crtc;
 
     /* hwcursor */
     struct pipe_texture *cursor_tex;
+    struct kms_bo *cursor_bo;
+
     unsigned cursor_handle;
 };
 
 static void
 crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
+    /* ScrnInfoPtr pScrn = crtc->scrn; */
+
     switch (mode) {
     case DPMSModeOn:
     case DPMSModeStandby:
@@ -114,7 +122,8 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
     drm_mode.vrefresh = mode->VRefresh;
     if (!mode->name)
        xf86SetModeDefaultName(mode);
-    strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN);
+    strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1);
+    drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0';
 
     ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
                         &drm_connector->connector_id, 1, &drm_mode);
@@ -134,23 +143,29 @@ static void
 crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
               int size)
 {
+    /* XXX: hockup */
 }
 
 static void *
 crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
 {
+    /* ScrnInfoPtr pScrn = crtc->scrn; */
+
     return NULL;
 }
 
 static PixmapPtr
 crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 {
+    /* ScrnInfoPtr pScrn = crtc->scrn; */
+
     return NULL;
 }
 
 static void
 crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 {
+    /* ScrnInfoPtr pScrn = crtc->scrn; */
 }
 
 /*
@@ -160,6 +175,7 @@ crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 static void
 crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
 {
+    /* XXX: See if this one is needed, as we only support ARGB cursors */
 }
 
 static void
@@ -170,8 +186,9 @@ crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
 
     drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
 }
+
 static void
-crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
+crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image)
 {
     unsigned char *ptr;
     modesettingPtr ms = modesettingPTR(crtc->scrn);
@@ -180,26 +197,26 @@ crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
 
     if (!crtcp->cursor_tex) {
        struct pipe_texture templat;
-       unsigned pitch;
+       struct winsys_handle whandle;
 
        memset(&templat, 0, sizeof(templat));
        templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
-       templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+       templat.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT;
        templat.target = PIPE_TEXTURE_2D;
        templat.last_level = 0;
-       templat.depth[0] = 1;
-       templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
-       templat.width[0] = 64;
-       templat.height[0] = 64;
-       pf_get_block(templat.format, &templat.block);
+       templat.depth0 = 1;
+       templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+       templat.width0 = 64;
+       templat.height0 = 64;
+
+       memset(&whandle, 0, sizeof(whandle));
+       whandle.type = DRM_API_HANDLE_TYPE_KMS;
 
        crtcp->cursor_tex = ms->screen->texture_create(ms->screen,
                                                       &templat);
-       ms->api->local_handle_from_texture(ms->api,
-                                          ms->screen,
-                                          crtcp->cursor_tex,
-                                          &pitch,
-                                          &crtcp->cursor_handle);
+       ms->screen->texture_get_handle(ms->screen, crtcp->cursor_tex, &whandle);
+
+       crtcp->cursor_handle = whandle.handle;
     }
 
     transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex,
@@ -207,20 +224,88 @@ crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
                                            PIPE_TRANSFER_WRITE,
                                            0, 0, 64, 64);
     ptr = ms->screen->transfer_map(ms->screen, transfer);
-    util_copy_rect(ptr, &crtcp->cursor_tex->block,
+    util_copy_rect(ptr, crtcp->cursor_tex->format,
                   transfer->stride, 0, 0,
                   64, 64, (void*)image, 64 * 4, 0, 0);
     ms->screen->transfer_unmap(ms->screen, transfer);
     ms->screen->tex_transfer_destroy(transfer);
 }
 
+#if HAVE_LIBKMS
+static void
+crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image)
+{
+    modesettingPtr ms = modesettingPTR(crtc->scrn);
+    struct crtc_private *crtcp = crtc->driver_private;
+    unsigned char *ptr;
+
+    if (!crtcp->cursor_bo) {
+       unsigned attr[8];
+
+       attr[0] = KMS_BO_TYPE;
+#ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8
+       attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
+#else
+       attr[1] = KMS_BO_TYPE_CURSOR;
+#endif
+       attr[2] = KMS_WIDTH;
+       attr[3] = 64;
+       attr[4] = KMS_HEIGHT;
+       attr[5] = 64;
+       attr[6] = 0;
+
+        if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo))
+          return;
+
+       if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE,
+                           &crtcp->cursor_handle))
+           goto err_bo_destroy;
+    }
+
+    kms_bo_map(crtcp->cursor_bo, (void**)&ptr);
+    memcpy(ptr, image, 64*64*4);
+    kms_bo_unmap(crtcp->cursor_bo);
+
+    return;
+
+err_bo_destroy:
+    kms_bo_destroy(&crtcp->cursor_bo);
+}
+#endif
+
+static void
+crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+    modesettingPtr ms = modesettingPTR(crtc->scrn);
+
+    /* Older X servers have cursor reference counting bugs leading to use of
+     * freed memory and consequently random crashes. Should be fixed as of
+     * xserver 1.8, but this workaround shouldn't hurt anyway.
+     */
+    if (config->cursor)
+       config->cursor->refcnt++;
+
+    if (ms->cursor)
+       FreeCursor(ms->cursor, None);
+
+    ms->cursor = config->cursor;
+
+    if (ms->screen)
+       crtc_load_cursor_argb_ga3d(crtc, image);
+#ifdef HAVE_LIBKMS
+    else if (ms->kms)
+       crtc_load_cursor_argb_kms(crtc, image);
+#endif
+}
+
 static void
 crtc_show_cursor(xf86CrtcPtr crtc)
 {
     modesettingPtr ms = modesettingPTR(crtc->scrn);
     struct crtc_private *crtcp = crtc->driver_private;
 
-    if (crtcp->cursor_tex)
+    if (crtcp->cursor_tex || crtcp->cursor_bo)
        drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
                         crtcp->cursor_handle, 64, 64);
 }
@@ -234,14 +319,20 @@ crtc_hide_cursor(xf86CrtcPtr crtc)
     drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
 }
 
+/**
+ * Called at vt leave
+ */
 void
-crtc_cursor_destroy(xf86CrtcPtr crtc)
+xorg_crtc_cursor_destroy(xf86CrtcPtr crtc)
 {
     struct crtc_private *crtcp = crtc->driver_private;
 
-    if (crtcp->cursor_tex) {
+    if (crtcp->cursor_tex)
        pipe_texture_reference(&crtcp->cursor_tex, NULL);
-    }
+#ifdef HAVE_LIBKMS
+    if (crtcp->cursor_bo)
+       kms_bo_destroy(&crtcp->cursor_bo);
+#endif
 }
 
 /*
@@ -253,11 +344,12 @@ crtc_destroy(xf86CrtcPtr crtc)
 {
     struct crtc_private *crtcp = crtc->driver_private;
 
-    if (crtcp->cursor_tex)
-       pipe_texture_reference(&crtcp->cursor_tex, NULL);
+    xorg_crtc_cursor_destroy(crtc);
 
     drmModeFreeCrtc(crtcp->drm_crtc);
+
     xfree(crtcp);
+    crtc->driver_private = NULL;
 }
 
 static const xf86CrtcFuncsRec crtc_funcs = {
@@ -279,7 +371,7 @@ static const xf86CrtcFuncsRec crtc_funcs = {
 };
 
 void
-crtc_init(ScrnInfoPtr pScrn)
+xorg_crtc_init(ScrnInfoPtr pScrn)
 {
     modesettingPtr ms = modesettingPTR(pScrn);
     xf86CrtcPtr crtc;