1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #pragma once
17
18 #include <android-base/unique_fd.h>
19 #include <binder/Parcel.h>
20 #include <binder/Parcelable.h>
21 #include <cutils/ashmem.h>
22 #include <sys/mman.h>
23 #include <algorithm>
24 #include <ostream>
25 #include <vector>
26
27 namespace android::gui {
28
29 struct DisplayLuts : public Parcelable {
30 public:
31 struct Entry : public Parcelable {
EntryDisplayLuts::Entry32 Entry() {};
EntryDisplayLuts::Entry33 Entry(int32_t lutDimension, int32_t lutSize, int32_t lutSamplingKey)
34 : dimension(lutDimension), size(lutSize), samplingKey(lutSamplingKey) {}
35 int32_t dimension;
36 int32_t size;
37 int32_t samplingKey;
38
39 status_t writeToParcel(android::Parcel* parcel) const override;
40 status_t readFromParcel(const android::Parcel* parcel) override;
41 };
42
DisplayLutsDisplayLuts43 DisplayLuts() {}
44
DisplayLutsDisplayLuts45 DisplayLuts(base::unique_fd lutfd, std::vector<int32_t> lutoffsets,
46 std::vector<int32_t> lutdimensions, std::vector<int32_t> lutsizes,
47 std::vector<int32_t> lutsamplingKeys) {
48 fd = std::move(lutfd);
49 offsets = lutoffsets;
50 lutProperties.reserve(offsets.size());
51 for (size_t i = 0; i < lutoffsets.size(); i++) {
52 Entry entry{lutdimensions[i], lutsizes[i], lutsamplingKeys[i]};
53 lutProperties.emplace_back(entry);
54 }
55 }
56
57 status_t writeToParcel(android::Parcel* parcel) const override;
58 status_t readFromParcel(const android::Parcel* parcel) override;
59
getLutFileDescriptorDisplayLuts60 const base::unique_fd& getLutFileDescriptor() const { return fd; }
61
62 std::vector<Entry> lutProperties;
63 std::vector<int32_t> offsets;
64
65 private:
66 base::unique_fd fd;
67 }; // struct DisplayLuts
68
PrintTo(const std::vector<int32_t> & offsets,::std::ostream * os)69 static inline void PrintTo(const std::vector<int32_t>& offsets, ::std::ostream* os) {
70 *os << "\n .offsets = {";
71 for (size_t i = 0; i < offsets.size(); i++) {
72 *os << offsets[i];
73 if (i != offsets.size() - 1) {
74 *os << ", ";
75 }
76 }
77 *os << "}";
78 }
79
PrintTo(const std::vector<DisplayLuts::Entry> & entries,::std::ostream * os)80 static inline void PrintTo(const std::vector<DisplayLuts::Entry>& entries, ::std::ostream* os) {
81 *os << "\n .lutProperties = {\n";
82 for (auto& [dimension, size, samplingKey] : entries) {
83 *os << " Entry{"
84 << "dimension: " << dimension << ", size: " << size << ", samplingKey: " << samplingKey
85 << "}\n";
86 }
87 *os << " }";
88 }
89
90 static constexpr size_t kMaxPrintCount = 100;
91
PrintTo(const std::vector<float> & buffer,size_t offset,int32_t dimension,size_t size,::std::ostream * os)92 static inline void PrintTo(const std::vector<float>& buffer, size_t offset, int32_t dimension,
93 size_t size, ::std::ostream* os) {
94 size_t range = std::min(size, kMaxPrintCount);
95 *os << "{";
96 if (dimension == 1) {
97 for (size_t i = 0; i < range; i++) {
98 *os << buffer[offset + i];
99 if (i != range - 1) {
100 *os << ", ";
101 }
102 }
103 } else {
104 *os << "\n {R channel:";
105 for (size_t i = 0; i < range; i++) {
106 *os << buffer[offset + i];
107 if (i != range - 1) {
108 *os << ", ";
109 }
110 }
111 *os << "}\n {G channel:";
112 for (size_t i = 0; i < range; i++) {
113 *os << buffer[offset + size + i];
114 if (i != range - 1) {
115 *os << ", ";
116 }
117 }
118 *os << "}\n {B channel:";
119 for (size_t i = 0; i < range; i++) {
120 *os << buffer[offset + 2 * size + i];
121 if (i != range - 1) {
122 *os << ", ";
123 }
124 }
125 }
126 *os << "}";
127 }
128
PrintTo(const std::shared_ptr<DisplayLuts> luts,::std::ostream * os)129 static inline void PrintTo(const std::shared_ptr<DisplayLuts> luts, ::std::ostream* os) {
130 *os << "gui::DisplayLuts {";
131 auto& fd = luts->getLutFileDescriptor();
132 *os << "\n .pfd = " << fd.get();
133 if (fd.ok()) {
134 PrintTo(luts->offsets, os);
135 PrintTo(luts->lutProperties, os);
136 // decode luts
137 int32_t fullLength = luts->offsets[luts->offsets.size() - 1];
138 if (luts->lutProperties[luts->offsets.size() - 1].dimension == 1) {
139 fullLength += luts->lutProperties[luts->offsets.size() - 1].size;
140 } else {
141 fullLength += (luts->lutProperties[luts->offsets.size() - 1].size *
142 luts->lutProperties[luts->offsets.size() - 1].size *
143 luts->lutProperties[luts->offsets.size() - 1].size * 3);
144 }
145 size_t bufferSize = static_cast<size_t>(fullLength) * sizeof(float);
146 float* ptr = (float*)mmap(NULL, bufferSize, PROT_READ, MAP_SHARED, fd.get(), 0);
147 if (ptr == MAP_FAILED) {
148 *os << "\n .bufferdata cannot mmap!";
149 return;
150 }
151 std::vector<float> buffers(ptr, ptr + fullLength);
152 munmap(ptr, bufferSize);
153
154 *os << "\n .bufferdata = ";
155 for (size_t i = 0; i < luts->offsets.size(); i++) {
156 PrintTo(buffers, static_cast<size_t>(luts->offsets[i]),
157 luts->lutProperties[i].dimension,
158 static_cast<size_t>(luts->lutProperties[i].size), os);
159 }
160 }
161 *os << "\n }";
162 }
163
164 } // namespace android::gui