meta-cursor-renderer-native.c 36.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

/*
 * Copyright (C) 2014 Red Hat
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Written by:
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 */

#include "config.h"

#include "meta-cursor-renderer-native.h"

29
#include <string.h>
30
#include <gbm.h>
31
#include <xf86drm.h>
32
#include <errno.h>
33

34
#include <meta/util.h>
35 36
#include <meta/meta-backend.h>

37
#include "backends/meta-backend-private.h"
38 39
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor.h"
40
#include "backends/meta-monitor-manager-private.h"
Jonas Ådahl's avatar
Jonas Ådahl committed
41
#include "backends/meta-output.h"
42
#include "backends/native/meta-renderer-native.h"
43
#include "core/boxes-private.h"
44
#include "meta/boxes.h"
45

46 47 48 49 50 51 52
#ifndef DRM_CAP_CURSOR_WIDTH
#define DRM_CAP_CURSOR_WIDTH 0x8
#endif
#ifndef DRM_CAP_CURSOR_HEIGHT
#define DRM_CAP_CURSOR_HEIGHT 0x9
#endif

53 54 55 56 57 58 59 60 61 62 63 64 65
/* When animating a cursor, we usually call drmModeSetCursor2 once per frame.
 * Though, testing shows that we need to triple buffer the cursor buffer in
 * order to avoid glitches when animating the cursor, at least when running on
 * Intel. The reason for this might be (but is not confirmed to be) due to
 * the user space gbm_bo cache, making us reuse and overwrite the kernel side
 * buffer content before it was scanned out. To avoid this, we keep a user space
 * reference to each buffer we set until at least one frame after it was drawn.
 * In effect, this means we three active cursor gbm_bo's: one that that just has
 * been set, one that was previously set and may or may not have been scanned
 * out, and one pending that will be replaced if the cursor sprite changes.
 */
#define HW_CURSOR_BUFFER_COUNT 3

66 67
static GQuark quark_cursor_sprite = 0;

68 69 70 71 72
struct _MetaCursorRendererNative
{
  MetaCursorRenderer parent;
};

73 74
struct _MetaCursorRendererNativePrivate
{
75 76
  MetaMonitorManager *monitor_manager;

77
  gboolean hw_state_invalidated;
78 79
  gboolean has_hw_cursor;

80
  MetaCursorSprite *last_cursor;
81
  guint animation_timeout_id;
82 83
};
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
84

85 86 87
typedef struct _MetaCursorRendererNativeGpuData
{
  gboolean hw_cursor_broken;
88 89 90

  uint64_t cursor_width;
  uint64_t cursor_height;
91
} MetaCursorRendererNativeGpuData;
92

93 94 95 96 97 98 99
typedef enum _MetaCursorGbmBoState
{
  META_CURSOR_GBM_BO_STATE_NONE,
  META_CURSOR_GBM_BO_STATE_SET,
  META_CURSOR_GBM_BO_STATE_INVALIDATED,
} MetaCursorGbmBoState;

100
typedef struct _MetaCursorNativeGpuState
101 102 103 104
{
  guint active_bo;
  MetaCursorGbmBoState pending_bo_state;
  struct gbm_bo *bos[HW_CURSOR_BUFFER_COUNT];
105 106 107 108 109
} MetaCursorNativeGpuState;

typedef struct _MetaCursorNativePrivate
{
  GHashTable *gpu_states;
110 111
} MetaCursorNativePrivate;

112 113
static GQuark quark_cursor_renderer_native_gpu_data = 0;

114 115
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);

116 117 118 119 120 121 122 123
static MetaCursorNativeGpuState *
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
                      MetaGpuKms              *gpu_kms);

static MetaCursorNativeGpuState *
ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
                         MetaGpuKms              *gpu_kms);

124 125 126
static MetaCursorNativePrivate *
ensure_cursor_priv (MetaCursorSprite *cursor_sprite);

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
static MetaCursorNativePrivate *
get_cursor_priv (MetaCursorSprite *cursor_sprite);

static MetaCursorRendererNativeGpuData *
meta_cursor_renderer_native_gpu_data_from_gpu (MetaGpuKms *gpu_kms)
{
  return g_object_get_qdata (G_OBJECT (gpu_kms),
                             quark_cursor_renderer_native_gpu_data);
}

static MetaCursorRendererNativeGpuData *
meta_create_cursor_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
{
  MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;

  cursor_renderer_gpu_data = g_new0 (MetaCursorRendererNativeGpuData, 1);
  g_object_set_qdata_full (G_OBJECT (gpu_kms),
                           quark_cursor_renderer_native_gpu_data,
                           cursor_renderer_gpu_data,
                           g_free);

  return cursor_renderer_gpu_data;
}

151 152 153 154 155 156
static void
meta_cursor_renderer_native_finalize (GObject *object)
{
  MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer);

157 158 159
  if (priv->animation_timeout_id)
    g_source_remove (priv->animation_timeout_id);

160 161 162
  G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
}

163
static guint
164
get_pending_cursor_sprite_gbm_bo_index (MetaCursorNativeGpuState *cursor_gpu_state)
165
{
166
  return (cursor_gpu_state->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
167 168
}

169
static struct gbm_bo *
170
get_pending_cursor_sprite_gbm_bo (MetaCursorNativeGpuState *cursor_gpu_state)
171
{
172 173
  guint pending_bo;

174 175
  pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state);
  return cursor_gpu_state->bos[pending_bo];
176 177
}

178
static struct gbm_bo *
179
get_active_cursor_sprite_gbm_bo (MetaCursorNativeGpuState *cursor_gpu_state)
180
{
181
  return cursor_gpu_state->bos[cursor_gpu_state->active_bo];
182 183 184
}

static void
185
set_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
186
                                  MetaGpuKms       *gpu_kms,
187
                                  struct gbm_bo    *bo)
188
{
189
  MetaCursorNativePrivate *cursor_priv;
190
  MetaCursorNativeGpuState *cursor_gpu_state;
191 192 193
  guint pending_bo;

  cursor_priv = ensure_cursor_priv (cursor_sprite);
194
  cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms);
195

196 197 198
  pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state);
  cursor_gpu_state->bos[pending_bo] = bo;
  cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_SET;
199 200
}

201 202
static void
set_crtc_cursor (MetaCursorRendererNative *native,
203
                 MetaCrtc                 *crtc,
204
                 MetaCursorSprite         *cursor_sprite)
205 206
{
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
207 208 209 210 211 212 213 214
  MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
  MetaGpuKms *gpu_kms;
  int kms_fd;

  gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
  cursor_renderer_gpu_data =
    meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
215

216
  if (cursor_sprite)
217
    {
218 219
      MetaCursorNativePrivate *cursor_priv;
      MetaCursorNativeGpuState *cursor_gpu_state;
220 221 222 223
      struct gbm_bo *bo;
      union gbm_bo_handle handle;
      int hot_x, hot_y;

224 225 226 227 228
      cursor_priv = get_cursor_priv (cursor_sprite);
      cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);

      if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
        bo = get_pending_cursor_sprite_gbm_bo (cursor_gpu_state);
229
      else
230
        bo = get_active_cursor_sprite_gbm_bo (cursor_gpu_state);
231

232
      if (!priv->hw_state_invalidated && bo == crtc->cursor_renderer_private)
233 234 235 236
        return;

      crtc->cursor_renderer_private = bo;

237
      handle = gbm_bo_get_handle (bo);
238 239
      meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);

240 241 242
      if (drmModeSetCursor2 (kms_fd, crtc->crtc_id, handle.u32,
                             cursor_renderer_gpu_data->cursor_width,
                             cursor_renderer_gpu_data->cursor_height,
243 244
                             hot_x, hot_y) < 0)
        {
245 246 247 248 249 250
          if (errno != EACCES)
            {
              g_warning ("drmModeSetCursor2 failed with (%s), "
                         "drawing cursor with OpenGL from now on",
                         strerror (errno));
              priv->has_hw_cursor = FALSE;
251
              cursor_renderer_gpu_data->hw_cursor_broken = TRUE;
252
            }
253
        }
254

255
      if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
256
        {
257 258 259
          cursor_gpu_state->active_bo =
            (cursor_gpu_state->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
          cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_NONE;
260
        }
261 262 263
    }
  else
    {
264
      if (priv->hw_state_invalidated || crtc->cursor_renderer_private != NULL)
265
        {
266
          drmModeSetCursor2 (kms_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
267 268
          crtc->cursor_renderer_private = NULL;
        }
269 270 271
    }
}

272 273 274 275
typedef struct
{
  MetaCursorRendererNative *in_cursor_renderer_native;
  MetaLogicalMonitor *in_logical_monitor;
276
  ClutterRect in_local_cursor_rect;
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  MetaCursorSprite *in_cursor_sprite;

  gboolean out_painted;
} UpdateCrtcCursorData;

static gboolean
update_monitor_crtc_cursor (MetaMonitor         *monitor,
                            MetaMonitorMode     *monitor_mode,
                            MetaMonitorCrtcMode *monitor_crtc_mode,
                            gpointer             user_data,
                            GError             **error)
{
  UpdateCrtcCursorData *data = user_data;
  MetaCursorRendererNative *cursor_renderer_native =
    data->in_cursor_renderer_native;
  MetaCursorRendererNativePrivate *priv =
    meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
294
  MetaMonitorTransform transform;
295
  ClutterRect scaled_crtc_rect;
296
  float scale;
297
  int crtc_x, crtc_y;
298
  int crtc_width, crtc_height;
299 300 301 302

  if (meta_is_stage_views_scaled ())
    scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
  else
303
    scale = 1.0;
304

305 306
  meta_monitor_calculate_crtc_pos (monitor, monitor_mode,
                                   monitor_crtc_mode->output,
307
                                   META_MONITOR_TRANSFORM_NORMAL,
308 309
                                   &crtc_x, &crtc_y);

310 311 312 313 314 315 316 317 318 319 320 321
  transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
  if (meta_monitor_transform_is_rotated (transform))
    {
      crtc_width = monitor_crtc_mode->crtc_mode->height;
      crtc_height = monitor_crtc_mode->crtc_mode->width;
    }
  else
    {
      crtc_width = monitor_crtc_mode->crtc_mode->width;
      crtc_height = monitor_crtc_mode->crtc_mode->height;
    }

322 323 324 325 326 327
  scaled_crtc_rect = (ClutterRect) {
    .origin = {
      .x = crtc_x / scale,
      .y = crtc_y / scale
    },
    .size = {
328 329
      .width = crtc_width / scale,
      .height = crtc_height / scale
330
    },
331 332 333
  };

  if (priv->has_hw_cursor &&
334 335 336
      clutter_rect_intersection (&scaled_crtc_rect,
                                 &data->in_local_cursor_rect,
                                 NULL))
337
    {
338 339
      MetaGpuKms *gpu_kms;
      int kms_fd;
340
      float crtc_cursor_x, crtc_cursor_y;
341 342 343 344 345

      set_crtc_cursor (data->in_cursor_renderer_native,
                       monitor_crtc_mode->output->crtc,
                       data->in_cursor_sprite);

346 347
      gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
      kms_fd = meta_gpu_kms_get_fd (gpu_kms);
348 349 350 351
      crtc_cursor_x = (data->in_local_cursor_rect.origin.x -
                       scaled_crtc_rect.origin.x) * scale;
      crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
                       scaled_crtc_rect.origin.y) * scale;
352
      drmModeMoveCursor (kms_fd,
353
                         monitor_crtc_mode->output->crtc->crtc_id,
354 355
                         roundf (crtc_cursor_x),
                         roundf (crtc_cursor_y));
356 357 358 359 360 361 362 363 364 365 366 367

      data->out_painted = data->out_painted || TRUE;
    }
  else
    {
      set_crtc_cursor (data->in_cursor_renderer_native,
                       monitor_crtc_mode->output->crtc, NULL);
    }

  return TRUE;
}

368 369
static void
update_hw_cursor (MetaCursorRendererNative *native,
370
                  MetaCursorSprite         *cursor_sprite)
371 372 373
{
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
374
  MetaMonitorManager *monitor_manager = priv->monitor_manager;
375 376
  GList *logical_monitors;
  GList *l;
377
  ClutterRect rect;
378
  gboolean painted = FALSE;
379

380 381 382
  if (cursor_sprite)
    rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
  else
383
    rect = (ClutterRect) { 0 };
384

385 386 387
  logical_monitors =
    meta_monitor_manager_get_logical_monitors (monitor_manager);
  for (l = logical_monitors; l; l = l->next)
388
    {
389 390 391 392 393 394 395 396
      MetaLogicalMonitor *logical_monitor = l->data;
      UpdateCrtcCursorData data;
      GList *monitors;
      GList *k;

      data = (UpdateCrtcCursorData) {
        .in_cursor_renderer_native = native,
        .in_logical_monitor = logical_monitor,
397 398 399 400 401 402
        .in_local_cursor_rect = (ClutterRect) {
          .origin = {
            .x = rect.origin.x - logical_monitor->rect.x,
            .y = rect.origin.y - logical_monitor->rect.y
          },
          .size = rect.size
403 404 405 406 407 408
        },
        .in_cursor_sprite = cursor_sprite
      };

      monitors = meta_logical_monitor_get_monitors (logical_monitor);
      for (k = monitors; k; k = k->next)
409
        {
410 411 412 413 414 415 416 417
          MetaMonitor *monitor = k->data;
          MetaMonitorMode *monitor_mode;

          monitor_mode = meta_monitor_get_current_mode (monitor);
          meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
                                          update_monitor_crtc_cursor,
                                          &data,
                                          NULL);
418
        }
419 420

      painted = painted || data.out_painted;
421
    }
422

423 424
  priv->hw_state_invalidated = FALSE;

425 426
  if (painted)
    meta_cursor_renderer_emit_painted (renderer, cursor_sprite);
427 428 429
}

static gboolean
430 431
has_valid_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
                                MetaGpuKms       *gpu_kms)
432
{
433 434
  MetaCursorNativePrivate *cursor_priv;
  MetaCursorNativeGpuState *cursor_gpu_state;
435

436
  cursor_priv = get_cursor_priv (cursor_sprite);
437 438 439
  if (!cursor_priv)
    return FALSE;

440 441 442 443 444
  cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
  if (!cursor_gpu_state)
    return FALSE;

  switch (cursor_gpu_state->pending_bo_state)
445 446
    {
    case META_CURSOR_GBM_BO_STATE_NONE:
447
      return get_active_cursor_sprite_gbm_bo (cursor_gpu_state) != NULL;
448 449 450 451 452 453 454 455 456 457 458
    case META_CURSOR_GBM_BO_STATE_SET:
      return TRUE;
    case META_CURSOR_GBM_BO_STATE_INVALIDATED:
      return FALSE;
    }

  g_assert_not_reached ();

  return FALSE;
}

459
static gboolean
460 461
cursor_over_transformed_logical_monitor (MetaCursorRenderer *renderer,
                                         MetaCursorSprite   *cursor_sprite)
462
{
463 464 465 466 467
  MetaCursorRendererNative *cursor_renderer_native =
    META_CURSOR_RENDERER_NATIVE (renderer);
  MetaCursorRendererNativePrivate *priv =
    meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
  MetaMonitorManager *monitor_manager = priv->monitor_manager;
468 469 470
  GList *logical_monitors;
  GList *l;
  ClutterRect cursor_rect;
471

472
  cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
473

474 475 476
  logical_monitors =
    meta_monitor_manager_get_logical_monitors (monitor_manager);
  for (l = logical_monitors; l; l = l->next)
477
    {
478 479 480 481
      MetaLogicalMonitor *logical_monitor = l->data;
      MetaRectangle logical_monitor_layout;
      ClutterRect logical_monitor_rect;
      MetaMonitorTransform transform;
482
      GList *monitors, *l_mon;
483 484 485 486 487

      logical_monitor_layout =
        meta_logical_monitor_get_layout (logical_monitor);
      logical_monitor_rect =
        meta_rectangle_to_clutter_rect (&logical_monitor_layout);
488

489 490
      if (!clutter_rect_intersection (&cursor_rect, &logical_monitor_rect,
                                      NULL))
491 492
        continue;

493 494 495 496 497 498 499 500 501 502 503
      monitors = meta_logical_monitor_get_monitors (logical_monitor);
      for (l_mon = monitors; l_mon; l_mon = l_mon->next)
        {
          MetaMonitor *monitor = l_mon->data;

          transform = meta_logical_monitor_get_transform (logical_monitor);
          /* Get transform corrected for LCD panel-orientation. */
          transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
          if (transform != META_MONITOR_TRANSFORM_NORMAL)
            return TRUE;
        }
504 505 506 507 508
    }

  return FALSE;
}

509 510 511 512 513 514 515 516 517 518 519 520
static float
calculate_cursor_crtc_sprite_scale (MetaCursorSprite   *cursor_sprite,
                                    MetaLogicalMonitor *logical_monitor)
{
  return (meta_logical_monitor_get_scale (logical_monitor) *
          meta_cursor_sprite_get_texture_scale (cursor_sprite));
}

static gboolean
can_draw_cursor_unscaled (MetaCursorRenderer *renderer,
                          MetaCursorSprite   *cursor_sprite)
{
521 522 523 524 525
  MetaCursorRendererNative *cursor_renderer_native =
    META_CURSOR_RENDERER_NATIVE (renderer);
  MetaCursorRendererNativePrivate *priv =
    meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
  MetaMonitorManager *monitor_manager = priv->monitor_manager;
526
  ClutterRect cursor_rect;
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
  GList *logical_monitors;
  GList *l;
  gboolean has_visible_crtc_sprite = FALSE;

  if (!meta_is_stage_views_scaled ())
   return meta_cursor_sprite_get_texture_scale (cursor_sprite) == 1.0;

  logical_monitors =
    meta_monitor_manager_get_logical_monitors (monitor_manager);

  if (!logical_monitors)
    return FALSE;

  cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);

  for (l = logical_monitors; l; l = l->next)
    {
      MetaLogicalMonitor *logical_monitor = l->data;
545 546
      ClutterRect logical_monitor_rect =
        meta_rectangle_to_clutter_rect (&logical_monitor->rect);
547

548 549 550
      if (!clutter_rect_intersection (&cursor_rect,
                                      &logical_monitor_rect,
                                      NULL))
551 552 553 554 555 556 557 558 559 560 561 562
        continue;

      if (calculate_cursor_crtc_sprite_scale (cursor_sprite,
                                              logical_monitor) != 1.0)
        return FALSE;

      has_visible_crtc_sprite = TRUE;
    }

  return has_visible_crtc_sprite;
}

563 564 565 566
static gboolean
should_have_hw_cursor (MetaCursorRenderer *renderer,
                       MetaCursorSprite   *cursor_sprite)
{
567 568
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
569
  GList *gpus;
570
  GList *l;
571 572 573
  CoglTexture *texture;

  if (!cursor_sprite)
574
    return FALSE;
575

576
  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
  for (l = gpus; l; l = l->next)
    {
      MetaGpuKms *gpu_kms = l->data;
      MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;

      cursor_renderer_gpu_data =
        meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
      if (!cursor_renderer_gpu_data)
        return FALSE;

      if (cursor_renderer_gpu_data->hw_cursor_broken)
        return FALSE;

      if (!has_valid_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms))
        return FALSE;
    }
593

594
  if (cursor_over_transformed_logical_monitor (renderer, cursor_sprite))
595 596
    return FALSE;

597 598 599 600
  texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
  if (!texture)
    return FALSE;

601
  if (!can_draw_cursor_unscaled (renderer, cursor_sprite))
602 603 604
    return FALSE;

  return TRUE;
605 606
}

607 608 609 610
static gboolean
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
{
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
611 612
  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
  MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
613 614

  priv->animation_timeout_id = 0;
615
  meta_cursor_sprite_tick_frame (cursor_sprite);
616
  meta_cursor_renderer_force_update (renderer);
617 618 619 620 621

  return G_SOURCE_REMOVE;
}

static void
622 623
meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native,
                                           MetaCursorSprite         *cursor_sprite)
624 625 626 627 628
{
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
  gboolean cursor_change;
  guint delay;

629 630
  cursor_change = cursor_sprite != priv->last_cursor;
  priv->last_cursor = cursor_sprite;
631 632 633 634 635 636 637 638 639 640

  if (!cursor_change && priv->animation_timeout_id)
    return;

  if (priv->animation_timeout_id)
    {
      g_source_remove (priv->animation_timeout_id);
      priv->animation_timeout_id = 0;
    }

641
  if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite))
642
    {
643
      delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite);
644 645 646 647 648 649 650 651 652 653 654 655 656

      if (delay == 0)
        return;

      priv->animation_timeout_id =
        g_timeout_add (delay,
                       (GSourceFunc) meta_cursor_renderer_native_update_animation,
                       native);
      g_source_set_name_by_id (priv->animation_timeout_id,
                               "[mutter] meta_cursor_renderer_native_update_animation");
    }
}

657
static gboolean
658 659
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
                                           MetaCursorSprite   *cursor_sprite)
660 661 662 663
{
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);

664 665 666 667
  if (cursor_sprite)
    meta_cursor_sprite_realize_texture (cursor_sprite);

  meta_cursor_renderer_native_trigger_frame (native, cursor_sprite);
668

669
  priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite);
670
  update_hw_cursor (native, cursor_sprite);
671
  return priv->has_hw_cursor;
672 673
}

674
static void
675
cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state)
676
{
677
  int i;
678

679 680 681
  for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++)
    g_clear_pointer (&cursor_gpu_state->bos[i], (GDestroyNotify) gbm_bo_destroy);
  g_free (cursor_gpu_state);
682 683
}

684 685 686
static MetaCursorNativeGpuState *
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
                      MetaGpuKms              *gpu_kms)
687
{
688 689
  return g_hash_table_lookup (cursor_priv->gpu_states, gpu_kms);
}
690

691 692 693 694 695
static MetaCursorNativeGpuState *
ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
                         MetaGpuKms              *gpu_kms)
{
  MetaCursorNativeGpuState *cursor_gpu_state;
696

697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
  cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
  if (cursor_gpu_state)
    return cursor_gpu_state;

  cursor_gpu_state = g_new0 (MetaCursorNativeGpuState, 1);
  g_hash_table_insert (cursor_priv->gpu_states, gpu_kms, cursor_gpu_state);

  return cursor_gpu_state;
}

static void
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
{
  g_hash_table_destroy (cursor_priv->gpu_states);
}

static MetaCursorNativePrivate *
get_cursor_priv (MetaCursorSprite *cursor_sprite)
{
  return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
717 718 719 720 721
}

static MetaCursorNativePrivate *
ensure_cursor_priv (MetaCursorSprite *cursor_sprite)
{
722
  MetaCursorNativePrivate *cursor_priv;
723

724 725 726 727 728 729 730 731 732 733 734 735 736 737
  cursor_priv = get_cursor_priv (cursor_sprite);
  if (cursor_priv)
    return cursor_priv;

  cursor_priv = g_new0 (MetaCursorNativePrivate, 1);
  cursor_priv->gpu_states =
    g_hash_table_new_full (g_direct_hash,
                           g_direct_equal,
                           NULL,
                           (GDestroyNotify) cursor_gpu_state_free);
  g_object_set_qdata_full (G_OBJECT (cursor_sprite),
                           quark_cursor_sprite,
                           cursor_priv,
                           (GDestroyNotify) cursor_priv_free);
738 739 740 741

  return cursor_priv;
}

742
static void
743 744 745 746 747 748 749 750
load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
                                       MetaGpuKms               *gpu_kms,
                                       MetaCursorSprite         *cursor_sprite,
                                       uint8_t                  *pixels,
                                       uint                      width,
                                       uint                      height,
                                       int                       rowstride,
                                       uint32_t                  gbm_format)
751 752
{
  uint64_t cursor_width, cursor_height;
753 754 755 756 757 758 759
  MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
  struct gbm_device *gbm_device;

  cursor_renderer_gpu_data =
    meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
  if (!cursor_renderer_gpu_data)
    return;
760

761 762
  cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width;
  cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height;
763 764 765 766 767 768 769 770

  if (width > cursor_width || height > cursor_height)
    {
      meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
                    (unsigned int)cursor_width, (unsigned int)cursor_height);
      return;
    }

771 772
  gbm_device = meta_gbm_device_from_gpu (gpu_kms);
  if (gbm_device_is_format_supported (gbm_device, gbm_format,
773 774 775 776 777 778
                                      GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
    {
      struct gbm_bo *bo;
      uint8_t buf[4 * cursor_width * cursor_height];
      uint i;

779
      bo = gbm_bo_create (gbm_device, cursor_width, cursor_height,
780
                          gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
781 782 783 784 785
      if (!bo)
        {
          meta_warning ("Failed to allocate HW cursor buffer\n");
          return;
        }
786 787 788 789

      memset (buf, 0, sizeof(buf));
      for (i = 0; i < height; i++)
        memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
790 791 792 793 794 795 796
      if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0)
        {
          meta_warning ("Failed to write cursors buffer data: %s",
                        g_strerror (errno));
          gbm_bo_destroy (bo);
          return;
        }
797

798
      set_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms, bo);
799 800
    }
  else
801 802 803 804 805 806
    {
      meta_warning ("HW cursor for format %d not supported\n", gbm_format);
    }
}

static void
807 808
invalidate_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
                                         MetaGpuKms       *gpu_kms)
809
{
810 811
  MetaCursorNativePrivate *cursor_priv;
  MetaCursorNativeGpuState *cursor_gpu_state;
812 813
  guint pending_bo;

814
  cursor_priv = get_cursor_priv (cursor_sprite);
815 816 817
  if (!cursor_priv)
    return;

818 819 820 821 822 823
  cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
  if (!cursor_gpu_state)
    return;

  pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state);
  g_clear_pointer (&cursor_gpu_state->bos[pending_bo],
824
                   (GDestroyNotify) gbm_bo_destroy);
825
  cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED;
826 827 828 829
}

#ifdef HAVE_WAYLAND
static void
830 831 832 833
meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
                                                                   MetaGpuKms         *gpu_kms,
                                                                   MetaCursorSprite   *cursor_sprite,
                                                                   struct wl_resource *buffer)
834 835
{
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
836
  MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
837 838
  uint32_t gbm_format;
  uint64_t cursor_width, cursor_height;
839
  CoglTexture *texture;
840 841
  uint width, height;

842 843 844
  cursor_renderer_gpu_data =
    meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
  if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
845 846
    return;

847 848 849
  /* Destroy any previous pending cursor buffer; we'll always either fail (which
   * should unset, or succeed, which will set new buffer.
   */
850
  invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms);
851 852 853 854

  texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
  width = cogl_texture_get_width (texture);
  height = cogl_texture_get_height (texture);
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886

  struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
  if (shm_buffer)
    {
      int rowstride = wl_shm_buffer_get_stride (shm_buffer);
      uint8_t *buffer_data;

      wl_shm_buffer_begin_access (shm_buffer);

      switch (wl_shm_buffer_get_format (shm_buffer))
        {
#if G_BYTE_ORDER == G_BIG_ENDIAN
        case WL_SHM_FORMAT_ARGB8888:
          gbm_format = GBM_FORMAT_ARGB8888;
          break;
        case WL_SHM_FORMAT_XRGB8888:
          gbm_format = GBM_FORMAT_XRGB8888;
          break;
#else
        case WL_SHM_FORMAT_ARGB8888:
          gbm_format = GBM_FORMAT_ARGB8888;
          break;
        case WL_SHM_FORMAT_XRGB8888:
          gbm_format = GBM_FORMAT_XRGB8888;
          break;
#endif
        default:
          g_warn_if_reached ();
          gbm_format = GBM_FORMAT_ARGB8888;
        }

      buffer_data = wl_shm_buffer_get_data (shm_buffer);
887 888 889 890 891 892
      load_cursor_sprite_gbm_buffer_for_gpu (native,
                                             gpu_kms,
                                             cursor_sprite,
                                             buffer_data,
                                             width, height, rowstride,
                                             gbm_format);
893 894 895 896 897

      wl_shm_buffer_end_access (shm_buffer);
    }
  else
    {
898
      struct gbm_device *gbm_device;
899 900 901 902 903 904 905 906
      struct gbm_bo *bo;

      /* HW cursors have a predefined size (at least 64x64), which usually is
       * bigger than cursor theme size, so themed cursors must be padded with
       * transparent pixels to fill the overlay. This is trivial if we have CPU
       * access to the data, but it's not possible if the buffer is in GPU
       * memory (and possibly tiled too), so if we don't get the right size, we
       * fallback to GL. */
907 908
      cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width;
      cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height;
909 910 911 912 913 914 915

      if (width != cursor_width || height != cursor_height)
        {
          meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
          return;
        }

916 917
      gbm_device = meta_gbm_device_from_gpu (gpu_kms);
      bo = gbm_bo_import (gbm_device,
918 919 920 921 922 923 924 925 926
                          GBM_BO_IMPORT_WL_BUFFER,
                          buffer,
                          GBM_BO_USE_CURSOR);
      if (!bo)
        {
          meta_warning ("Importing HW cursor from wl_buffer failed\n");
          return;
        }

927
      set_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms, bo);
928 929 930 931
    }
}

static void
932 933 934
meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
                                                           MetaCursorSprite *cursor_sprite,
                                                           struct wl_resource *buffer)
935 936
{
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
937 938
  MetaCursorRendererNativePrivate *priv =
	  meta_cursor_renderer_native_get_instance_private (native);
939 940
  GList *gpus;
  GList *l;
941

942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
  for (l = gpus; l; l = l->next)
    {
      MetaGpuKms *gpu_kms = l->data;

      meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (
        renderer,
        gpu_kms,
        cursor_sprite,
        buffer);
    }
}
#endif

static void
meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
                                                                 MetaGpuKms         *gpu_kms,
                                                                 MetaCursorSprite   *cursor_sprite,
                                                                 XcursorImage       *xc_image)
{
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
  MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;

  cursor_renderer_gpu_data =
    meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
  if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
968
    return;
969

970
  invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms);
971

972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
  load_cursor_sprite_gbm_buffer_for_gpu (native,
                                         gpu_kms,
                                         cursor_sprite,
                                         (uint8_t *) xc_image->pixels,
                                         xc_image->width,
                                         xc_image->height,
                                         xc_image->width * 4,
                                         GBM_FORMAT_ARGB8888);
}

static void
meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
                                                         MetaCursorSprite   *cursor_sprite,
                                                         XcursorImage       *xc_image)
{
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
  MetaCursorRendererNativePrivate *priv =
	  meta_cursor_renderer_native_get_instance_private (native);
  GList *gpus;
  GList *l;

  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
  for (l = gpus; l; l = l->next)
    {
      MetaGpuKms *gpu_kms = l->data;

      meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (
        renderer,
        gpu_kms,
        cursor_sprite,
        xc_image);
    }
1004 1005
}

1006 1007 1008 1009 1010 1011 1012 1013
static void
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
{
  MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->finalize = meta_cursor_renderer_native_finalize;
  renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
1014 1015 1016 1017 1018 1019 1020 1021
#ifdef HAVE_WAYLAND
  renderer_class->realize_cursor_from_wl_buffer =
    meta_cursor_renderer_native_realize_cursor_from_wl_buffer;
#endif
  renderer_class->realize_cursor_from_xcursor =
    meta_cursor_renderer_native_realize_cursor_from_xcursor;

  quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
1022 1023
  quark_cursor_renderer_native_gpu_data =
    g_quark_from_static_string ("-meta-cursor-renderer-native-gpu-data");
1024 1025
}

1026 1027 1028 1029
static void
force_update_hw_cursor (MetaCursorRendererNative *native)
{
  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
1030 1031
  MetaCursorRendererNativePrivate *priv =
    meta_cursor_renderer_native_get_instance_private (native);
1032

1033 1034
  priv->hw_state_invalidated = TRUE;
  update_hw_cursor (native, meta_cursor_renderer_get_cursor (renderer));
1035 1036
}

1037 1038 1039 1040 1041
static void
on_monitors_changed (MetaMonitorManager       *monitors,
                     MetaCursorRendererNative *native)
{
  /* Our tracking is all messed up, so force an update. */
1042
  force_update_hw_cursor (native);
1043 1044 1045
}

static void
1046
init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native)
1047
{
1048 1049
  MetaCursorRendererNativePrivate *priv =
    meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
1050
  GList *gpus;
1051
  GList *l;
1052

1053
  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
  for (l = gpus; l; l = l->next)
    {
      MetaGpuKms *gpu_kms = l->data;
      MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
      int kms_fd;
      struct gbm_device *gbm_device;
      uint64_t width, height;

      gbm_device = meta_gbm_device_from_gpu (gpu_kms);
      if (!gbm_device)
        continue;
1065

1066 1067
      cursor_renderer_gpu_data =
        meta_create_cursor_renderer_native_gpu_data (gpu_kms);
1068

1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
      kms_fd = meta_gpu_kms_get_fd (gpu_kms);
      if (drmGetCap (kms_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
          drmGetCap (kms_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
        {
          cursor_renderer_gpu_data->cursor_width = width;
          cursor_renderer_gpu_data->cursor_height = height;
        }
      else
        {
          cursor_renderer_gpu_data->cursor_width = 64;
          cursor_renderer_gpu_data->cursor_height = 64;
        }
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
    }
}

MetaCursorRendererNative *
meta_cursor_renderer_native_new (MetaBackend *backend)
{
  MetaMonitorManager *monitor_manager =
    meta_backend_get_monitor_manager (backend);
  MetaCursorRendererNative *cursor_renderer_native;
  MetaCursorRendererNativePrivate *priv;

  cursor_renderer_native =
    g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
  priv =
    meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);

1097
  g_signal_connect_object (monitor_manager, "monitors-changed-internal",
1098 1099 1100 1101 1102 1103
                           G_CALLBACK (on_monitors_changed),
                           cursor_renderer_native, 0);

  priv->monitor_manager = monitor_manager;
  priv->hw_state_invalidated = TRUE;

1104
  init_hw_cursor_support (cursor_renderer_native);
1105 1106 1107 1108 1109 1110 1111

  return cursor_renderer_native;
}

static void
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
{
1112 1113 1114 1115 1116
}

void
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
{
1117
  force_update_hw_cursor (native);
1118
}