1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/ozone/platform/drm/gpu/drm_gpu_util.h"
6 
7 #include <fcntl.h>
8 #include <xf86drm.h>
9 #include <xf86drmMode.h>
10 
11 #include "base/files/scoped_file.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "ui/display/types/gamma_ramp_rgb_entry.h"
15 #include "ui/ozone/platform/drm/gpu/drm_device.h"
16 
17 namespace ui {
18 
GetDrmPropertyForName(DrmDevice * drm,drmModeObjectProperties * properties,const std::string & name,DrmDevice::Property * property)19 bool GetDrmPropertyForName(DrmDevice* drm,
20                            drmModeObjectProperties* properties,
21                            const std::string& name,
22                            DrmDevice::Property* property) {
23   for (uint32_t i = 0; i < properties->count_props; ++i) {
24     ScopedDrmPropertyPtr drm_property(drm->GetProperty(properties->props[i]));
25     if (name != drm_property->name)
26       continue;
27 
28     property->id = drm_property->prop_id;
29     property->value = properties->prop_values[i];
30     if (property->id)
31       return true;
32   }
33 
34   return false;
35 }
36 
AddPropertyIfValid(drmModeAtomicReq * property_set,uint32_t object_id,const DrmDevice::Property & property)37 bool AddPropertyIfValid(drmModeAtomicReq* property_set,
38                         uint32_t object_id,
39                         const DrmDevice::Property& property) {
40   if (!property.id)
41     return true;
42 
43   int ret = drmModeAtomicAddProperty(property_set, object_id, property.id,
44                                      property.value);
45   if (ret < 0) {
46     LOG(ERROR) << "Failed to set property object_id=" << object_id
47                << " property_id=" << property.id
48                << " property_value=" << property.value << " error=" << -ret;
49     return false;
50   }
51 
52   return true;
53 }
54 
CreateLutBlob(const std::vector<display::GammaRampRGBEntry> & source)55 ScopedDrmColorLutPtr CreateLutBlob(
56     const std::vector<display::GammaRampRGBEntry>& source) {
57   TRACE_EVENT0("drm", "CreateLutBlob");
58   if (source.empty())
59     return nullptr;
60 
61   ScopedDrmColorLutPtr lut(static_cast<drm_color_lut*>(
62       malloc(sizeof(drm_color_lut) * source.size())));
63   drm_color_lut* p = lut.get();
64   for (size_t i = 0; i < source.size(); ++i) {
65     p[i].red = source[i].r;
66     p[i].green = source[i].g;
67     p[i].blue = source[i].b;
68   }
69   return lut;
70 }
71 
CreateCTMBlob(const std::vector<float> & color_matrix)72 ScopedDrmColorCtmPtr CreateCTMBlob(const std::vector<float>& color_matrix) {
73   if (color_matrix.empty())
74     return nullptr;
75 
76   ScopedDrmColorCtmPtr ctm(
77       static_cast<drm_color_ctm*>(malloc(sizeof(drm_color_ctm))));
78   DCHECK_EQ(color_matrix.size(), base::size(ctm->matrix));
79   for (size_t i = 0; i < base::size(ctm->matrix); ++i) {
80     if (color_matrix[i] < 0) {
81       ctm->matrix[i] = static_cast<uint64_t>(-color_matrix[i] * (1ull << 32));
82       ctm->matrix[i] |= static_cast<uint64_t>(1) << 63;
83     } else {
84       ctm->matrix[i] = static_cast<uint64_t>(color_matrix[i] * (1ull << 32));
85     }
86   }
87   return ctm;
88 }
89 
ResampleLut(const std::vector<display::GammaRampRGBEntry> & lut_in,size_t desired_size)90 std::vector<display::GammaRampRGBEntry> ResampleLut(
91     const std::vector<display::GammaRampRGBEntry>& lut_in,
92     size_t desired_size) {
93   TRACE_EVENT1("drm", "ResampleLut", "desired_size", desired_size);
94   if (lut_in.empty())
95     return std::vector<display::GammaRampRGBEntry>();
96 
97   if (lut_in.size() == desired_size)
98     return lut_in;
99 
100   std::vector<display::GammaRampRGBEntry> result;
101   result.resize(desired_size);
102 
103   for (size_t i = 0; i < desired_size; ++i) {
104     size_t base_index = lut_in.size() * i / desired_size;
105     size_t remaining = lut_in.size() * i % desired_size;
106     if (base_index < lut_in.size() - 1) {
107       result[i].r = lut_in[base_index].r +
108                     (lut_in[base_index + 1].r - lut_in[base_index].r) *
109                         remaining / desired_size;
110       result[i].g = lut_in[base_index].g +
111                     (lut_in[base_index + 1].g - lut_in[base_index].g) *
112                         remaining / desired_size;
113       result[i].b = lut_in[base_index].b +
114                     (lut_in[base_index + 1].b - lut_in[base_index].b) *
115                         remaining / desired_size;
116     } else {
117       result[i] = lut_in.back();
118     }
119   }
120 
121   return result;
122 }
123 
IsDriverName(const char * device_file_name,const char * driver)124 bool IsDriverName(const char* device_file_name, const char* driver) {
125   base::ScopedFD fd(open(device_file_name, O_RDWR));
126   if (!fd.is_valid()) {
127     LOG(ERROR) << "Failed to open DRM device " << device_file_name;
128     return false;
129   }
130 
131   ScopedDrmVersionPtr version(drmGetVersion(fd.get()));
132   if (!version) {
133     LOG(ERROR) << "Failed to query DRM version " << device_file_name;
134     return false;
135   }
136 
137   if (strncmp(driver, version->name, version->name_len) == 0)
138     return true;
139 
140   return false;
141 }
142 
143 }  // namespace ui
144