1 /*
2  * Copyright (C) 2020 Red Hat
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17  * 02111-1307, USA.
18  */
19 
20 #include "config.h"
21 
22 #include "backends/native/meta-kms-mode-private.h"
23 
24 #include "backends/native/meta-kms-impl-device.h"
25 
26 struct _MetaKmsMode
27 {
28   MetaKmsImplDevice *impl_device;
29   MetaKmsModeFlag flags;
30   drmModeModeInfo drm_mode;
31 };
32 
33 uint32_t
meta_kms_mode_create_blob_id(MetaKmsMode * mode,GError ** error)34 meta_kms_mode_create_blob_id (MetaKmsMode  *mode,
35                               GError      **error)
36 {
37   int fd;
38   int ret;
39   uint32_t blob_id;
40 
41   fd = meta_kms_impl_device_get_fd (mode->impl_device);
42 
43   ret = drmModeCreatePropertyBlob (fd,
44                                    &mode->drm_mode,
45                                    sizeof (mode->drm_mode),
46                                    &blob_id);
47   if (ret < 0)
48     {
49       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
50                    "drmModeCreatePropertyBlob: %s",
51                    g_strerror (-ret));
52       return 0;
53     }
54 
55   return blob_id;
56 }
57 
58 const char *
meta_kms_mode_get_name(MetaKmsMode * mode)59 meta_kms_mode_get_name (MetaKmsMode *mode)
60 {
61   return mode->drm_mode.name;
62 }
63 
64 MetaKmsModeFlag
meta_kms_mode_get_flags(MetaKmsMode * mode)65 meta_kms_mode_get_flags (MetaKmsMode *mode)
66 {
67   return mode->flags;
68 }
69 
70 const drmModeModeInfo *
meta_kms_mode_get_drm_mode(MetaKmsMode * mode)71 meta_kms_mode_get_drm_mode (MetaKmsMode *mode)
72 {
73   return &mode->drm_mode;
74 }
75 
76 gboolean
meta_drm_mode_equal(const drmModeModeInfo * one,const drmModeModeInfo * two)77 meta_drm_mode_equal (const drmModeModeInfo *one,
78                      const drmModeModeInfo *two)
79 {
80   return (one->clock == two->clock &&
81           one->hdisplay == two->hdisplay &&
82           one->hsync_start == two->hsync_start &&
83           one->hsync_end == two->hsync_end &&
84           one->htotal == two->htotal &&
85           one->hskew == two->hskew &&
86           one->vdisplay == two->vdisplay &&
87           one->vsync_start == two->vsync_start &&
88           one->vsync_end == two->vsync_end &&
89           one->vtotal == two->vtotal &&
90           one->vscan == two->vscan &&
91           one->vrefresh == two->vrefresh &&
92           one->flags == two->flags &&
93           one->type == two->type &&
94           strncmp (one->name, two->name, DRM_DISPLAY_MODE_LEN) == 0);
95 }
96 
97 gboolean
meta_kms_mode_equal(MetaKmsMode * mode,MetaKmsMode * other_mode)98 meta_kms_mode_equal (MetaKmsMode *mode,
99                      MetaKmsMode *other_mode)
100 {
101   return meta_drm_mode_equal (&mode->drm_mode, &other_mode->drm_mode);
102 }
103 
104 unsigned int
meta_kms_mode_hash(MetaKmsMode * mode)105 meta_kms_mode_hash (MetaKmsMode *mode)
106 {
107   const drmModeModeInfo *drm_mode = &mode->drm_mode;
108   unsigned int hash = 0;
109 
110   /*
111    * We don't include the name in the hash because it's generally
112    * derived from the other fields (hdisplay, vdisplay and flags)
113    */
114 
115   hash ^= drm_mode->clock;
116   hash ^= drm_mode->hdisplay ^ drm_mode->hsync_start ^ drm_mode->hsync_end;
117   hash ^= drm_mode->vdisplay ^ drm_mode->vsync_start ^ drm_mode->vsync_end;
118   hash ^= drm_mode->vrefresh;
119   hash ^= drm_mode->flags ^ drm_mode->type;
120 
121   return hash;
122 }
123 
124 void
meta_kms_mode_free(MetaKmsMode * mode)125 meta_kms_mode_free (MetaKmsMode *mode)
126 {
127   g_free (mode);
128 }
129 
130 MetaKmsMode *
meta_kms_mode_new(MetaKmsImplDevice * impl_device,const drmModeModeInfo * drm_mode,MetaKmsModeFlag flags)131 meta_kms_mode_new (MetaKmsImplDevice     *impl_device,
132                    const drmModeModeInfo *drm_mode,
133                    MetaKmsModeFlag        flags)
134 {
135   MetaKmsMode *mode;
136 
137   mode = g_new0 (MetaKmsMode, 1);
138   mode->impl_device = impl_device;
139   mode->flags = flags;
140   mode->drm_mode = *drm_mode;
141 
142   return mode;
143 }
144