| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/ozone/platform/drm/gpu/drm_device.h" | 5 #include "ui/ozone/platform/drm/gpu/drm_device.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <sys/mman.h> | 8 #include <sys/mman.h> |
| 9 #include <unistd.h> | 9 #include <unistd.h> |
| 10 #include <xf86drm.h> | 10 #include <xf86drm.h> |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy); | 178 ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy); |
| 179 return ret < 0 ? -errno : ret; | 179 return ret < 0 ? -errno : ret; |
| 180 } | 180 } |
| 181 | 181 |
| 182 using ScopedDrmColorLutPtr = std::unique_ptr<DrmColorLut, base::FreeDeleter>; | 182 using ScopedDrmColorLutPtr = std::unique_ptr<DrmColorLut, base::FreeDeleter>; |
| 183 using ScopedDrmColorCtmPtr = std::unique_ptr<DrmColorCtm, base::FreeDeleter>; | 183 using ScopedDrmColorCtmPtr = std::unique_ptr<DrmColorCtm, base::FreeDeleter>; |
| 184 | 184 |
| 185 ScopedDrmColorLutPtr CreateLutBlob( | 185 ScopedDrmColorLutPtr CreateLutBlob( |
| 186 const std::vector<GammaRampRGBEntry>& source) { | 186 const std::vector<GammaRampRGBEntry>& source) { |
| 187 TRACE_EVENT0("drm", "CreateLutBlob"); | 187 TRACE_EVENT0("drm", "CreateLutBlob"); |
| 188 if (source.empty()) |
| 189 return nullptr; |
| 190 |
| 188 ScopedDrmColorLutPtr lut( | 191 ScopedDrmColorLutPtr lut( |
| 189 static_cast<DrmColorLut*>(malloc(sizeof(DrmColorLut) * source.size()))); | 192 static_cast<DrmColorLut*>(malloc(sizeof(DrmColorLut) * source.size()))); |
| 190 DrmColorLut* p = lut.get(); | 193 DrmColorLut* p = lut.get(); |
| 191 for (size_t i = 0; i < source.size(); ++i) { | 194 for (size_t i = 0; i < source.size(); ++i) { |
| 192 p[i].red = source[i].r; | 195 p[i].red = source[i].r; |
| 193 p[i].green = source[i].g; | 196 p[i].green = source[i].g; |
| 194 p[i].blue = source[i].b; | 197 p[i].blue = source[i].b; |
| 195 } | 198 } |
| 196 return lut; | 199 return lut; |
| 197 } | 200 } |
| 198 | 201 |
| 199 ScopedDrmColorCtmPtr CreateCTMBlob( | 202 ScopedDrmColorCtmPtr CreateCTMBlob( |
| 200 const std::vector<float>& correction_matrix) { | 203 const std::vector<float>& correction_matrix) { |
| 204 if (correction_matrix.empty()) |
| 205 return nullptr; |
| 206 |
| 201 ScopedDrmColorCtmPtr ctm( | 207 ScopedDrmColorCtmPtr ctm( |
| 202 static_cast<DrmColorCtm*>(malloc(sizeof(DrmColorCtm)))); | 208 static_cast<DrmColorCtm*>(malloc(sizeof(DrmColorCtm)))); |
| 203 for (size_t i = 0; i < arraysize(ctm->ctm_coeff); ++i) { | 209 for (size_t i = 0; i < arraysize(ctm->ctm_coeff); ++i) { |
| 204 if (correction_matrix[i] < 0) { | 210 if (correction_matrix[i] < 0) { |
| 205 ctm->ctm_coeff[i] = static_cast<uint64_t>( | 211 ctm->ctm_coeff[i] = static_cast<uint64_t>( |
| 206 -correction_matrix[i] * (static_cast<uint64_t>(1) << 32)); | 212 -correction_matrix[i] * (static_cast<uint64_t>(1) << 32)); |
| 207 ctm->ctm_coeff[i] |= static_cast<uint64_t>(1) << 63; | 213 ctm->ctm_coeff[i] |= static_cast<uint64_t>(1) << 63; |
| 208 } else { | 214 } else { |
| 209 ctm->ctm_coeff[i] = static_cast<uint64_t>( | 215 ctm->ctm_coeff[i] = static_cast<uint64_t>( |
| 210 correction_matrix[i] * (static_cast<uint64_t>(1) << 32)); | 216 correction_matrix[i] * (static_cast<uint64_t>(1) << 32)); |
| 211 } | 217 } |
| 212 } | 218 } |
| 213 return ctm; | 219 return ctm; |
| 214 } | 220 } |
| 215 | 221 |
| 216 bool SetBlobProperty(int fd, | 222 bool SetBlobProperty(int fd, |
| 217 uint32_t object_id, | 223 uint32_t object_id, |
| 218 uint32_t object_type, | 224 uint32_t object_type, |
| 219 uint32_t prop_id, | 225 uint32_t prop_id, |
| 220 const char* property_name, | 226 const char* property_name, |
| 221 unsigned char* data, | 227 unsigned char* data, |
| 222 size_t length) { | 228 size_t length) { |
| 223 uint32_t blob_id; | 229 uint32_t blob_id = 0; |
| 224 int res; | 230 int res; |
| 225 res = CreatePropertyBlob(fd, data, length, &blob_id); | 231 |
| 226 if (res != 0) { | 232 if (data) { |
| 227 LOG(ERROR) << "Error creating property blob: " << base::safe_strerror(res) | 233 res = CreatePropertyBlob(fd, data, length, &blob_id); |
| 228 << " for property " << property_name; | 234 if (res != 0) { |
| 229 return false; | 235 LOG(ERROR) << "Error creating property blob: " << base::safe_strerror(res) |
| 236 << " for property " << property_name; |
| 237 return false; |
| 238 } |
| 230 } | 239 } |
| 240 |
| 241 bool success = false; |
| 231 res = drmModeObjectSetProperty(fd, object_id, object_type, prop_id, blob_id); | 242 res = drmModeObjectSetProperty(fd, object_id, object_type, prop_id, blob_id); |
| 232 if (res != 0) { | 243 if (res != 0) { |
| 233 LOG(ERROR) << "Error updating property: " << base::safe_strerror(res) | 244 LOG(ERROR) << "Error updating property: " << base::safe_strerror(res) |
| 234 << " for property " << property_name; | 245 << " for property " << property_name; |
| 246 } else { |
| 247 success = true; |
| 248 } |
| 249 if (blob_id != 0) |
| 235 DestroyPropertyBlob(fd, blob_id); | 250 DestroyPropertyBlob(fd, blob_id); |
| 236 return false; | 251 return success; |
| 237 } | |
| 238 DestroyPropertyBlob(fd, blob_id); | |
| 239 return true; | |
| 240 } | 252 } |
| 241 | 253 |
| 242 std::vector<GammaRampRGBEntry> ResampleLut( | 254 std::vector<GammaRampRGBEntry> ResampleLut( |
| 243 const std::vector<GammaRampRGBEntry>& lut_in, | 255 const std::vector<GammaRampRGBEntry>& lut_in, |
| 244 size_t desired_size) { | 256 size_t desired_size) { |
| 245 TRACE_EVENT1("drm", "ResampleLut", "desired_size", desired_size); | 257 TRACE_EVENT1("drm", "ResampleLut", "desired_size", desired_size); |
| 258 if (lut_in.empty()) |
| 259 return std::vector<GammaRampRGBEntry>(); |
| 260 |
| 246 if (lut_in.size() == desired_size) | 261 if (lut_in.size() == desired_size) |
| 247 return lut_in; | 262 return lut_in; |
| 248 | 263 |
| 249 std::vector<GammaRampRGBEntry> result; | 264 std::vector<GammaRampRGBEntry> result; |
| 250 result.resize(desired_size); | 265 result.resize(desired_size); |
| 251 | 266 |
| 252 for (size_t i = 0; i < desired_size; ++i) { | 267 for (size_t i = 0; i < desired_size; ++i) { |
| 253 size_t base_index = lut_in.size() * i / desired_size; | 268 size_t base_index = lut_in.size() * i / desired_size; |
| 254 size_t remaining = lut_in.size() * i % desired_size; | 269 size_t remaining = lut_in.size() * i % desired_size; |
| 255 if (base_index < lut_in.size() - 1) { | 270 if (base_index < lut_in.size() - 1) { |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 | 682 |
| 668 bool DrmDevice::DropMaster() { | 683 bool DrmDevice::DropMaster() { |
| 669 TRACE_EVENT1("drm", "DrmDevice::DropMaster", "path", device_path_.value()); | 684 TRACE_EVENT1("drm", "DrmDevice::DropMaster", "path", device_path_.value()); |
| 670 DCHECK(file_.IsValid()); | 685 DCHECK(file_.IsValid()); |
| 671 return (drmDropMaster(file_.GetPlatformFile()) == 0); | 686 return (drmDropMaster(file_.GetPlatformFile()) == 0); |
| 672 } | 687 } |
| 673 | 688 |
| 674 bool DrmDevice::SetGammaRamp(uint32_t crtc_id, | 689 bool DrmDevice::SetGammaRamp(uint32_t crtc_id, |
| 675 const std::vector<GammaRampRGBEntry>& lut) { | 690 const std::vector<GammaRampRGBEntry>& lut) { |
| 676 ScopedDrmCrtcPtr crtc = GetCrtc(crtc_id); | 691 ScopedDrmCrtcPtr crtc = GetCrtc(crtc_id); |
| 692 size_t gamma_size = static_cast<size_t>(crtc->gamma_size); |
| 693 |
| 694 if (gamma_size == 0 && lut.empty()) |
| 695 return true; |
| 696 |
| 697 if (gamma_size == 0) { |
| 698 LOG(ERROR) << "Gamma table not supported"; |
| 699 return false; |
| 700 } |
| 677 | 701 |
| 678 // TODO(robert.bradford) resample the incoming ramp to match what the kernel | 702 // TODO(robert.bradford) resample the incoming ramp to match what the kernel |
| 679 // expects. | 703 // expects. |
| 680 if (static_cast<size_t>(crtc->gamma_size) != lut.size()) { | 704 if (!lut.empty() && gamma_size != lut.size()) { |
| 681 LOG(ERROR) << "Gamma table size mismatch: supplied " << lut.size() | 705 LOG(ERROR) << "Gamma table size mismatch: supplied " << lut.size() |
| 682 << " expected " << crtc->gamma_size; | 706 << " expected " << gamma_size; |
| 707 return false; |
| 683 } | 708 } |
| 684 | 709 |
| 685 std::vector<uint16_t> r, g, b; | 710 std::vector<uint16_t> r, g, b; |
| 686 r.reserve(lut.size()); | 711 r.reserve(gamma_size); |
| 687 g.reserve(lut.size()); | 712 g.reserve(gamma_size); |
| 688 b.reserve(lut.size()); | 713 b.reserve(gamma_size); |
| 689 | 714 |
| 690 for (size_t i = 0; i < lut.size(); ++i) { | 715 if (lut.empty()) { |
| 691 r.push_back(lut[i].r); | 716 // Create a linear gamma ramp table to deactivate the feature. |
| 692 g.push_back(lut[i].g); | 717 for (size_t i = 0; i < gamma_size; ++i) { |
| 693 b.push_back(lut[i].b); | 718 uint16_t value = (i * ((1 << 16) - 1)) / (gamma_size - 1); |
| 719 r.push_back(value); |
| 720 g.push_back(value); |
| 721 b.push_back(value); |
| 722 } |
| 723 } else { |
| 724 for (size_t i = 0; i < gamma_size; ++i) { |
| 725 r.push_back(lut[i].r); |
| 726 g.push_back(lut[i].g); |
| 727 b.push_back(lut[i].b); |
| 728 } |
| 694 } | 729 } |
| 695 | 730 |
| 696 DCHECK(file_.IsValid()); | 731 DCHECK(file_.IsValid()); |
| 697 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); | 732 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); |
| 698 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], | 733 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], |
| 699 &g[0], &b[0]) == 0); | 734 &g[0], &b[0]) == 0); |
| 700 } | 735 } |
| 701 | 736 |
| 702 bool DrmDevice::SetColorCorrection( | 737 bool DrmDevice::SetColorCorrection( |
| 703 uint32_t crtc_id, | 738 uint32_t crtc_id, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 716 degamma_lut_size = crtc_props->prop_values[i]; | 751 degamma_lut_size = crtc_props->prop_values[i]; |
| 717 } | 752 } |
| 718 if (property && !strcmp(property->name, "GAMMA_LUT_SIZE")) { | 753 if (property && !strcmp(property->name, "GAMMA_LUT_SIZE")) { |
| 719 gamma_lut_size = crtc_props->prop_values[i]; | 754 gamma_lut_size = crtc_props->prop_values[i]; |
| 720 } | 755 } |
| 721 | 756 |
| 722 if (degamma_lut_size && gamma_lut_size) | 757 if (degamma_lut_size && gamma_lut_size) |
| 723 break; | 758 break; |
| 724 } | 759 } |
| 725 | 760 |
| 761 // If we can't find the degamma & gamma lut size, it means the properties |
| 762 // aren't available. We should then use the legacy gamma ramp ioctl. |
| 726 if (degamma_lut_size == 0 || gamma_lut_size == 0) { | 763 if (degamma_lut_size == 0 || gamma_lut_size == 0) { |
| 727 LOG(WARNING) << "No available (de)gamma tables."; | 764 return SetGammaRamp(crtc_id, gamma_lut); |
| 728 return false; | |
| 729 } | 765 } |
| 730 | 766 |
| 731 ScopedDrmColorLutPtr degamma_blob_data = | 767 ScopedDrmColorLutPtr degamma_blob_data = |
| 732 CreateLutBlob(ResampleLut(degamma_lut, degamma_lut_size)); | 768 CreateLutBlob(ResampleLut(degamma_lut, degamma_lut_size)); |
| 733 ScopedDrmColorLutPtr gamma_blob_data = | 769 ScopedDrmColorLutPtr gamma_blob_data = |
| 734 CreateLutBlob(ResampleLut(gamma_lut, gamma_lut_size)); | 770 CreateLutBlob(ResampleLut(gamma_lut, gamma_lut_size)); |
| 735 ScopedDrmColorCtmPtr ctm_blob_data = CreateCTMBlob(correction_matrix); | 771 ScopedDrmColorCtmPtr ctm_blob_data = CreateCTMBlob(correction_matrix); |
| 736 | 772 |
| 737 for (uint32_t i = 0; i < crtc_props->count_props; ++i) { | 773 for (uint32_t i = 0; i < crtc_props->count_props; ++i) { |
| 738 ScopedDrmPropertyPtr property( | 774 ScopedDrmPropertyPtr property( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 763 reinterpret_cast<unsigned char*>(ctm_blob_data.get()), | 799 reinterpret_cast<unsigned char*>(ctm_blob_data.get()), |
| 764 sizeof(DrmColorCtm))) | 800 sizeof(DrmColorCtm))) |
| 765 return false; | 801 return false; |
| 766 } | 802 } |
| 767 } | 803 } |
| 768 | 804 |
| 769 return true; | 805 return true; |
| 770 } | 806 } |
| 771 | 807 |
| 772 } // namespace ui | 808 } // namespace ui |
| OLD | NEW |