1 /*
2 * Copyright Samsung Electronics Co.,LTD.
3 * Copyright (C) 2017 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
19
20 #include "acrylic_g2d.h"
21
22 #include <alloca.h>
23 #include <exynos_format.h> // hardware/smasung_slsi/exynos/include
24 #include <hardware/hwcomposer2.h>
25 #include <log/log.h>
26 #include <mali_gralloc_formats.h>
27 #include <sys/ioctl.h>
28 #include <system/graphics.h>
29 #include <utils/Trace.h>
30
31 #include <algorithm>
32 #include <cstring>
33
34 enum {
35 G2D_CSC_STD_UNDEFINED = -1,
36 G2D_CSC_STD_601 = 0,
37 G2D_CSC_STD_709 = 1,
38 G2D_CSC_STD_2020 = 2,
39 G2D_CSC_STD_P3 = 3,
40
41 G2D_CSC_STD_COUNT = 4,
42 };
43
44 enum {
45 G2D_CSC_RANGE_LIMITED,
46 G2D_CSC_RANGE_FULL,
47
48 G2D_CSC_RANGE_COUNT,
49 };
50
51 static char csc_std_to_matrix_index[] = {
52 G2D_CSC_STD_709, // HAL_DATASPACE_STANDARD_UNSPECIFIED
53 G2D_CSC_STD_709, // HAL_DATASPACE_STANDARD_BT709
54 G2D_CSC_STD_601, // HAL_DATASPACE_STANDARD_BT601_625
55 G2D_CSC_STD_601, // HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED
56 G2D_CSC_STD_601, // HAL_DATASPACE_STANDARD_BT601_525
57 G2D_CSC_STD_601, // HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED
58 G2D_CSC_STD_2020, // HAL_DATASPACE_STANDARD_BT2020
59 G2D_CSC_STD_2020, // HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE
60 static_cast<char>(G2D_CSC_STD_UNDEFINED), // HAL_DATASPACE_STANDARD_BT470M
61 G2D_CSC_STD_709, // HAL_DATASPACE_STANDARD_FILM
62 G2D_CSC_STD_P3, // HAL_DATASPACE_STANDARD_DCI_P3
63 static_cast<char>(G2D_CSC_STD_UNDEFINED), // HAL_DATASPACE_STANDARD_ADOBE_RGB
64 };
65
66 static uint16_t YCbCr2sRGBCoefficients[G2D_CSC_STD_COUNT * G2D_CSC_RANGE_COUNT][9] = {
67 {0x0254, 0x0000, 0x0331, 0x0254, 0xFF37, 0xFE60, 0x0254, 0x0409, 0x0000}, // 601 limited
68 {0x0200, 0x0000, 0x02BE, 0x0200, 0xFF54, 0xFE9B, 0x0200, 0x0377, 0x0000}, // 601 full
69 {0x0254, 0x0000, 0x0396, 0x0254, 0xFF93, 0xFEEF, 0x0254, 0x043A, 0x0000}, // 709 limited
70 {0x0200, 0x0000, 0x0314, 0x0200, 0xFFA2, 0xFF16, 0x0200, 0x03A1, 0x0000}, // 709 full
71 {0x0254, 0x0000, 0x035B, 0x0254, 0xFFA0, 0xFEB3, 0x0254, 0x0449, 0x0000}, // 2020 limited
72 {0x0200, 0x0000, 0x02E2, 0x0200, 0xFFAE, 0xFEE2, 0x0200, 0x03AE, 0x0000}, // 2020 full
73 {0x0254, 0x0000, 0x03AE, 0x0254, 0xFF96, 0xFEEE, 0x0254, 0x0456, 0x0000}, // DCI-P3 limited
74 {0x0200, 0x0000, 0x0329, 0x0200, 0xFFA5, 0xFF15, 0x0200, 0x03B9, 0x0000}, // DCI-P3 full
75 };
76
77 static uint16_t sRGB2YCbCrCoefficients[G2D_CSC_STD_COUNT * G2D_CSC_RANGE_COUNT][9] = {
78 {0x0083, 0x0102, 0x0032, 0xFFB4, 0xFF6B, 0x00E1, 0x00E1, 0xFF44, 0xFFDB}, // 601 limited
79 {0x0099, 0x012D, 0x003A, 0xFFA8, 0xFF53, 0x0106, 0x0106, 0xFF25, 0xFFD5}, // 601 full
80 {0x005D, 0x013A, 0x0020, 0xFFCC, 0xFF53, 0x00E1, 0x00E1, 0xFF34, 0xFFEB}, // 709 limited
81 {0x006D, 0x016E, 0x0025, 0xFFC4, 0xFF36, 0x0106, 0x0106, 0xFF12, 0xFFE8}, // 709 full
82 {0x0074, 0x012A, 0x001A, 0xFFC1, 0xFF5A, 0x00E1, 0x00E1, 0xFF31, 0xFFEE}, // 2020 limited
83 {0x0087, 0x015B, 0x001E, 0xFFB7, 0xFF43, 0x0106, 0x0106, 0xFF0F, 0xFFEB}, // 2020 full
84 {0x006B, 0x0171, 0x0023, 0xFFC6, 0xFF3A, 0x0100, 0x0100, 0xFF16, 0xFFEA}, // DCI-P3 limited(full)
85 {0x006B, 0x0171, 0x0023, 0xFFC6, 0xFF3A, 0x0100, 0x0100, 0xFF16, 0xFFEA}, // DCI-P3 full
86 };
87
88 #define CSC_MATRIX_REGISTER_COUNT 9
89 #define CSC_MATRIX_REGISTER_SIZE (CSC_MATRIX_REGISTER_COUNT * sizeof(uint32_t))
90
g2dfmt_is_ycbcr(unsigned int g2dfmt)91 static inline bool g2dfmt_is_ycbcr(unsigned int g2dfmt)
92 {
93 g2dfmt &= G2D_DATAFMT_MASK;
94 return (G2D_DATAFMT_YUV_MIN <= g2dfmt) && (g2dfmt <= G2D_DATAFMT_YUV_MAX);
95 }
96
97 class CSCMatrixWriter {
98 enum { CSC_MATRIX_MAX_COUNT = 4, CSC_MATRIX_INVALID_INDEX = 200 };
99 enum { CSC_MATRIX_SRC_BASE = 0x2000, CSC_MATRIX_DST_BASE = 0x2100 };
100 public:
CSCMatrixWriter(unsigned int g2dfmt,unsigned int dataspace,uint32_t * command)101 CSCMatrixWriter(unsigned int g2dfmt, unsigned int dataspace, uint32_t *command)
102 : mMatrixCount(0), mMatrixTargetIndex(CSC_MATRIX_INVALID_INDEX) {
103 // Ignore if unsupported dataspace is specified.
104 // G2D also works for the case.
105 // But the correctness of the result is not guaranteed.
106 if (g2dfmt_is_ycbcr(g2dfmt)) {
107 mMatrixTargetIndex = findMatrixIndex(dataspace);
108 if ((dataspace & HAL_DATASPACE_RANGE_FULL) != 0)
109 *command = G2D_LAYER_YCBCRMODE_WIDE;
110 }
111 }
112
configure(unsigned int g2dfmt,unsigned int dataspace,uint32_t * command)113 bool configure(unsigned int g2dfmt, unsigned int dataspace, uint32_t *command) {
114 if (!g2dfmt_is_ycbcr(g2dfmt))
115 return true;
116
117 unsigned int spcidx = findMatrixIndex(dataspace);
118
119 if (spcidx == CSC_MATRIX_INVALID_INDEX)
120 return false;
121
122 if ((dataspace & HAL_DATASPACE_RANGE_FULL) != 0)
123 *command = G2D_LAYER_YCBCRMODE_WIDE;
124
125 for (int i = 0; i < mMatrixCount; i++) {
126 if (mMatrixIndex[i] == spcidx) {
127 *command |= i;
128 return true;
129 }
130 }
131
132 if (mMatrixCount == CSC_MATRIX_MAX_COUNT) {
133 ALOGE("Too many CSC requirements");
134 return false;
135 }
136
137 mMatrixIndex[mMatrixCount] = spcidx;
138
139 *command |= mMatrixCount++;
140
141 return true;
142 }
143
getRegisterCount()144 unsigned int getRegisterCount() {
145 unsigned int count = CSC_MATRIX_REGISTER_COUNT * mMatrixCount;
146 if (mMatrixTargetIndex != CSC_MATRIX_INVALID_INDEX)
147 count += CSC_MATRIX_REGISTER_COUNT;
148 return count;
149 }
150
write(g2d_reg regs[])151 unsigned int write(g2d_reg regs[]) {
152 unsigned int count = 0;
153
154 if (mMatrixTargetIndex != CSC_MATRIX_INVALID_INDEX) {
155 writeSingle(CSC_MATRIX_DST_BASE,
156 ®s[count], sRGB2YCbCrCoefficients[mMatrixTargetIndex]);
157 count += CSC_MATRIX_REGISTER_COUNT;
158 }
159
160 for (int m = 0; m < mMatrixCount; m++) {
161 writeSingle(CSC_MATRIX_SRC_BASE + m * CSC_MATRIX_REGISTER_SIZE,
162 ®s[count], YCbCr2sRGBCoefficients[mMatrixIndex[m]]);
163 count += CSC_MATRIX_REGISTER_COUNT;
164 }
165
166 return count;
167 }
168
169 private:
writeSingle(unsigned int base,g2d_reg regs[],uint16_t matrix[9])170 void writeSingle(unsigned int base, g2d_reg regs[], uint16_t matrix[9]) {
171 for (unsigned int idx = 0; idx < CSC_MATRIX_REGISTER_COUNT; idx++) {
172 regs[idx].offset = base;
173 regs[idx].value = matrix[idx];
174 base += sizeof(uint32_t);
175 }
176 }
177
findMatrixIndex(unsigned int dataspace)178 unsigned int findMatrixIndex(unsigned int dataspace) {
179 unsigned int index, colorspace;
180
181 colorspace = (dataspace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
182 if (colorspace >= ARRSIZE(csc_std_to_matrix_index)) {
183 ALOGE("Data space %d is not supported by G2D", dataspace);
184 return CSC_MATRIX_INVALID_INDEX;
185 }
186
187 index = csc_std_to_matrix_index[colorspace] * G2D_CSC_RANGE_COUNT;
188 if ((dataspace & HAL_DATASPACE_RANGE_FULL) != 0)
189 index++;
190
191 return index;
192 }
193
194 unsigned int mMatrixIndex[CSC_MATRIX_MAX_COUNT];
195 int mMatrixCount;
196 unsigned int mMatrixTargetIndex;
197 };
198
199 #define G2D_FILTER_COEF_BASE 0x6000
200 #define G2D_FILTER_COEF_REG(idx) (0x6000 + (idx) * 0x400)
201 #define G2D_FILTER_C_OFFSET 0x200
202 #define G2D_SCALE_FACTOR(from, to) ((static_cast<uint32_t>(from) << G2D_SCALEFACTOR_FRACBITS) / (to))
203
204 #define SI11(v) static_cast<uint32_t>((v) & 0x7FF)
205 #define FILTER_HCOEF(a, b, c, d, e, f, g, h) {SI11(a), SI11(b), SI11(c), SI11(d), SI11(e), SI11(f), SI11(g), SI11(h)}
206 #define FILTER_VCOEF(a, b, c, d) {SI11(a), SI11(b), SI11(c), SI11(d)}
207
208 #define NUM_HORI_COEFFICIENTS 8
209 #define NUM_VERT_COEFFICIENTS 4
210 #define NUM_FILTER_PHASE 9
211 #define NUM_FILTER_COEF_SETS 7
212
213 #define NUM_VERT_COEF_REGS (NUM_FILTER_PHASE * NUM_VERT_COEFFICIENTS)
214 #define NUM_HORI_COEF_REGS (NUM_FILTER_PHASE * NUM_HORI_COEFFICIENTS)
215
216 static uint32_t g2dHoriFilterCoef[NUM_FILTER_COEF_SETS][NUM_FILTER_PHASE][NUM_HORI_COEFFICIENTS] = {
217 { // Upsampling
218 FILTER_HCOEF( 0, 0, 0, 512, 0, 0, 0, 0), FILTER_HCOEF( -2, 8, -25, 509, 30, -9, 2, -1), FILTER_HCOEF( -4, 14, -46, 499, 64, -19, 5, -1),
219 FILTER_HCOEF( -5, 20, -62, 482, 101, -30, 8, -2), FILTER_HCOEF( -5, 23, -73, 458, 142, -41, 12, -3), FILTER_HCOEF( -6, 25, -80, 429, 185, -53, 15, -3),
220 FILTER_HCOEF( -6, 26, -83, 395, 228, -63, 19, -4), FILTER_HCOEF( -6, 25, -82, 357, 273, -71, 21, -5), FILTER_HCOEF( -5, 23, -78, 316, 316, -78, 23, -5),
221 }, { // x7/8 Downsampling
222 FILTER_HCOEF( 12, -32, 56, 444, 52, -32, 12, 0), FILTER_HCOEF( 9, -24, 29, 445, 82, -39, 13, -3), FILTER_HCOEF( 7, -16, 6, 438, 112, -46, 14, -3),
223 FILTER_HCOEF( 5, -9, -14, 426, 144, -52, 15, -3), FILTER_HCOEF( 3, -3, -30, 410, 177, -58, 16, -3), FILTER_HCOEF( 2, 2, -43, 390, 211, -63, 16, -3),
224 FILTER_HCOEF( 1, 7, -53, 365, 244, -66, 16, -2), FILTER_HCOEF( 0, 10, -60, 338, 277, -66, 15, -2), FILTER_HCOEF( -1, 13, -65, 309, 309, -65, 13, -1),
225 }, { // x6/8 Downsampling
226 FILTER_HCOEF( 8, -44, 100, 384, 100, -44, 8, 0), FILTER_HCOEF( 9, -40, 77, 382, 123, -47, 8, 0), FILTER_HCOEF( 8, -36, 57, 377, 147, -49, 7, 1),
227 FILTER_HCOEF( 8, -32, 38, 369, 171, -49, 5, 2), FILTER_HCOEF( 8, -27, 20, 358, 196, -48, 3, 2), FILTER_HCOEF( 7, -22, 5, 344, 221, -47, 1, 3),
228 FILTER_HCOEF( 7, -18, -9, 329, 245, -43, -2, 3), FILTER_HCOEF( 5, -13, -20, 310, 268, -37, -5, 4), FILTER_HCOEF( 5, -9, -30, 290, 290, -30, -9, 5),
229 }, { // x5/8 Downsampling
230 FILTER_HCOEF( -3, -31, 130, 320, 130, -31, -3, 0), FILTER_HCOEF( -3, -32, 113, 319, 147, -29, -6, 3), FILTER_HCOEF( -1, -33, 97, 315, 165, -26, -8, 3),
231 FILTER_HCOEF( 0, -32, 81, 311, 182, -22, -11, 3), FILTER_HCOEF( 1, -31, 66, 304, 199, -17, -13, 3), FILTER_HCOEF( 2, -30, 52, 296, 216, -11, -16, 3),
232 FILTER_HCOEF( 2, -28, 38, 286, 232, -3, -18, 3), FILTER_HCOEF( 3, -25, 26, 274, 247, 5, -21, 3), FILTER_HCOEF( 3, -23, 15, 261, 261, 15, -23, 3),
233 }, { // x4/8 Downsampling
234 FILTER_HCOEF( -11, 0, 140, 255, 140, 0, -12, 0), FILTER_HCOEF( -10, -4, 129, 254, 151, 5, -13, 0), FILTER_HCOEF( -9, -7, 117, 253, 163, 10, -14, -1),
235 FILTER_HCOEF( -8, -10, 106, 250, 174, 16, -15, -1), FILTER_HCOEF( -7, -12, 95, 246, 185, 22, -16, -1), FILTER_HCOEF( -6, -14, 85, 241, 195, 29, -16, -2),
236 FILTER_HCOEF( -5, -15, 74, 236, 204, 37, -17, -2), FILTER_HCOEF( -5, -16, 64, 229, 214, 46, -17, -3), FILTER_HCOEF( -4, -17, 55, 222, 222, 55, -17, -4),
237 }, { // x3/8 Downsampling
238 FILTER_HCOEF( -5, 31, 133, 195, 133, 31, -6, 0), FILTER_HCOEF( -5, 27, 126, 195, 139, 37, -4, -3), FILTER_HCOEF( -5, 23, 119, 194, 146, 41, -3, -3),
239 FILTER_HCOEF( -5, 19, 112, 193, 152, 47, -2, -4), FILTER_HCOEF( -5, 16, 105, 191, 158, 53, -2, -4), FILTER_HCOEF( -5, 12, 98, 189, 163, 59, 0, -4),
240 FILTER_HCOEF( -5, 10, 91, 185, 169, 65, 1, -4), FILTER_HCOEF( -5, 7, 84, 182, 174, 71, 3, -4), FILTER_HCOEF( -5, 5, 78, 178, 178, 78, 5, -5),
241 }, { // x2/8 Downsampling
242 FILTER_HCOEF( 10, 52, 118, 152, 118, 52, 10, 0), FILTER_HCOEF( 9, 48, 114, 152, 122, 56, 11, 0), FILTER_HCOEF( 7, 45, 110, 151, 125, 60, 13, 1),
243 FILTER_HCOEF( 6, 41, 106, 150, 129, 64, 15, 1), FILTER_HCOEF( 5, 38, 102, 149, 132, 68, 17, 1), FILTER_HCOEF( 4, 35, 98, 148, 135, 72, 19, 1),
244 FILTER_HCOEF( 4, 31, 94, 146, 138, 77, 21, 1), FILTER_HCOEF( 3, 29, 89, 145, 140, 81, 23, 2), FILTER_HCOEF( 2, 26, 85, 143, 143, 85, 26, 2),
245 }
246 };
247
248 static uint32_t g2dVertFilterCoef[NUM_FILTER_COEF_SETS][NUM_FILTER_PHASE][NUM_VERT_COEFFICIENTS] = {
249 { // Upsampling
250 FILTER_VCOEF( 0, 512, 0, 0), FILTER_VCOEF( -15, 508, 20, -1), FILTER_VCOEF( -25, 495, 45, -3),
251 FILTER_VCOEF( -31, 473, 75, -5), FILTER_VCOEF( -33, 443, 110, -8), FILTER_VCOEF( -33, 408, 148, -11),
252 FILTER_VCOEF( -31, 367, 190, -14), FILTER_VCOEF( -27, 324, 234, -19), FILTER_VCOEF( -23, 279, 279, -23),
253 }, { // x7/8 Downsampling
254 FILTER_VCOEF( 32, 448, 32, 0), FILTER_VCOEF( 17, 446, 55, -6), FILTER_VCOEF( 3, 437, 79, -7),
255 FILTER_VCOEF( -7, 421, 107, -9), FILTER_VCOEF( -14, 399, 138, -11), FILTER_VCOEF( -18, 373, 170, -13),
256 FILTER_VCOEF( -20, 343, 204, -15), FILTER_VCOEF( -20, 310, 240, -18), FILTER_VCOEF( -19, 275, 275, -19),
257 }, { // x6/8 Downsampling
258 FILTER_VCOEF( 61, 390, 61, 0), FILTER_VCOEF( 46, 390, 83, -7), FILTER_VCOEF( 31, 383, 106, -8),
259 FILTER_VCOEF( 19, 371, 130, -8), FILTER_VCOEF( 9, 356, 156, -9), FILTER_VCOEF( 2, 337, 183, -10),
260 FILTER_VCOEF( -3, 315, 210, -10), FILTER_VCOEF( -7, 291, 238, -10), FILTER_VCOEF( -9, 265, 265, -9),
261 }, { // x5/8 Downsampling
262 FILTER_VCOEF( 85, 341, 86, 0), FILTER_VCOEF( 71, 341, 105, -5), FILTER_VCOEF( 56, 336, 124, -4),
263 FILTER_VCOEF( 43, 328, 145, -4), FILTER_VCOEF( 32, 317, 166, -3), FILTER_VCOEF( 23, 304, 187, -2),
264 FILTER_VCOEF( 16, 288, 209, -1), FILTER_VCOEF( 9, 271, 231, 1), FILTER_VCOEF( 5, 251, 251, 5),
265 }, { // x4/8 Downsampling
266 FILTER_VCOEF( 104, 304, 104, 0), FILTER_VCOEF( 89, 302, 120, 1), FILTER_VCOEF( 76, 298, 136, 2),
267 FILTER_VCOEF( 63, 293, 153, 3), FILTER_VCOEF( 52, 285, 170, 5), FILTER_VCOEF( 42, 275, 188, 7),
268 FILTER_VCOEF( 33, 264, 205, 10), FILTER_VCOEF( 26, 251, 221, 14), FILTER_VCOEF( 20, 236, 236, 20),
269 }, { // x3/8 Downsampling
270 FILTER_VCOEF( 118, 276, 118, 0), FILTER_VCOEF( 103, 273, 129, 7), FILTER_VCOEF( 90, 270, 143, 9),
271 FILTER_VCOEF( 78, 266, 157, 11), FILTER_VCOEF( 67, 260, 171, 14), FILTER_VCOEF( 57, 253, 185, 17),
272 FILTER_VCOEF( 48, 244, 199, 21), FILTER_VCOEF( 40, 234, 211, 27), FILTER_VCOEF( 33, 223, 223, 33),
273 }, { // x2/8 Downsampling
274 FILTER_VCOEF( 127, 258, 127, 0), FILTER_VCOEF( 111, 252, 135, 14), FILTER_VCOEF( 100, 250, 147, 15),
275 FILTER_VCOEF( 88, 247, 159, 18), FILTER_VCOEF( 78, 242, 171, 21), FILTER_VCOEF( 68, 237, 182, 25),
276 FILTER_VCOEF( 59, 230, 193, 30), FILTER_VCOEF( 50, 222, 204, 36), FILTER_VCOEF( 43, 213, 213, 43),
277 }
278 };
279
findFilterCoefficientsIndex(uint32_t factor)280 static unsigned int findFilterCoefficientsIndex(uint32_t factor)
281 {
282 static uint32_t choicetable[NUM_FILTER_COEF_SETS] = {
283 G2D_SCALE_FACTOR(8, 8), G2D_SCALE_FACTOR(8, 7), G2D_SCALE_FACTOR(8, 6), G2D_SCALE_FACTOR(8, 5),
284 G2D_SCALE_FACTOR(8, 4), G2D_SCALE_FACTOR(8, 3), G2D_SCALE_FACTOR(8, 2),
285 };
286
287 for (unsigned int i = 0; i < NUM_FILTER_COEF_SETS; i++)
288 if (factor <= choicetable[i])
289 return i;
290 // if i == NUM_FILTER_COEF_SETS, the downsampling factor is larger than 4.0 which is not supported by the filter.
291 return NUM_FILTER_COEF_SETS - 1;
292 }
293
294 template<typename CoefT>
__writeFilterCoefficients(CoefT & coef_set,unsigned int index,uint32_t base,g2d_reg regs[])295 static unsigned int __writeFilterCoefficients(CoefT &coef_set, unsigned int index, uint32_t base, g2d_reg regs[])
296 {
297 // The default value of filter coefficients are values of 8:8/zoom-in
298 // So, do not update redundantly.
299 if (index == 0)
300 return 0;
301
302 unsigned int cnt = 0;
303
304 for (auto &coef_table: coef_set[index]) {
305 uint32_t coef_base = base;
306 // register offsets of filter coeffcients are ordered by phase number then tab index
307 // while values are ordered by tab index then phase number in the above coefficients array.
308 // So register offset is increased by the number of tabs instead of 1.
309 // The coefficients array is specified in the order of tab index due to readability
310 // because the coefficient values are also specified in the same order in UM.
311 for (auto coef: coef_table) {
312 regs[cnt].offset = coef_base;
313 regs[cnt].value = coef;
314 coef_base += (sizeof(coef_set[index]) / sizeof(coef_table)) * sizeof(coef_table[0]);
315 cnt++;
316 }
317 base += sizeof(uint32_t);
318 }
319
320 return cnt;
321 }
322
getChromaScaleFactor(uint32_t colormode,unsigned int * hfactor,unsigned int * vfactor)323 void getChromaScaleFactor(uint32_t colormode, unsigned int *hfactor, unsigned int *vfactor)
324 {
325 switch (colormode & G2D_DATAFMT_MASK) {
326 case G2D_DATAFMT_YUV420SP:
327 case G2D_DATAFMT_YUV420P:
328 *hfactor /= 2;
329 [[fallthrough]];
330 case G2D_DATAFMT_YUV422SP:
331 case G2D_DATAFMT_YUV422I:
332 *vfactor /= 2;
333 break;
334 default:
335 break;
336 }
337 }
338
writeFilterCoefficients(uint32_t hfactor,uint32_t vfactor,uint32_t colormode,unsigned layer_index,g2d_reg regs[])339 static unsigned int writeFilterCoefficients(uint32_t hfactor, uint32_t vfactor, uint32_t colormode,
340 unsigned layer_index, g2d_reg regs[])
341 {
342 unsigned int hindex = findFilterCoefficientsIndex(hfactor);
343 unsigned int vindex = findFilterCoefficientsIndex(vfactor);
344 // Filter coefficients of 1:1 and upsampling are configured to the filter by default (reset value)
345 if ((hindex == 0) && (vindex == 0))
346 return 0;
347
348 unsigned int base = G2D_FILTER_COEF_REG(layer_index);
349 unsigned int cnt = 0;
350 // Y Coefficients
351 cnt += __writeFilterCoefficients(g2dVertFilterCoef, vindex, base, regs);
352 cnt += __writeFilterCoefficients(g2dHoriFilterCoef, hindex, base + sizeof(g2dVertFilterCoef[0]), regs + cnt);
353 if (IS_YUV(colormode)) {
354 // C Coefficients
355 getChromaScaleFactor(colormode, &hfactor, &vfactor);
356
357 hindex = findFilterCoefficientsIndex(hfactor);
358 vindex = findFilterCoefficientsIndex(vfactor);
359 base += G2D_FILTER_C_OFFSET;
360 cnt += __writeFilterCoefficients(g2dVertFilterCoef, vindex, base, regs + cnt);
361 cnt += __writeFilterCoefficients(g2dHoriFilterCoef, hindex, base + sizeof(g2dVertFilterCoef[0]), regs + cnt);
362 }
363
364 return cnt;
365 }
366
getFilterCoefficientCount(uint32_t * src_cmds[],unsigned int layer_count)367 static unsigned int getFilterCoefficientCount(uint32_t *src_cmds[], unsigned int layer_count)
368 {
369 unsigned int count = 0;
370
371
372 for (unsigned int i = 0; i < layer_count; i++) {
373 unsigned int layer_coef_cnt = 0;
374 unsigned int hfactor = src_cmds[i][G2DSFR_SRC_XSCALE];
375 unsigned int vfactor = src_cmds[i][G2DSFR_SRC_YSCALE];
376
377 if (hfactor > G2D_SCALE_FACTOR(8, 8))
378 layer_coef_cnt += NUM_HORI_COEF_REGS;
379 if (vfactor > G2D_SCALE_FACTOR(8, 8))
380 layer_coef_cnt += NUM_VERT_COEF_REGS;
381 if (IS_YUV(src_cmds[i][G2DSFR_IMG_COLORMODE])) {
382 getChromaScaleFactor(src_cmds[i][G2DSFR_IMG_COLORMODE], &hfactor, &vfactor);
383 if (hfactor > G2D_SCALE_FACTOR(8, 8))
384 layer_coef_cnt += NUM_HORI_COEF_REGS;
385 if (vfactor > G2D_SCALE_FACTOR(8, 8))
386 layer_coef_cnt += NUM_VERT_COEF_REGS;
387 }
388
389 count += layer_coef_cnt;
390 }
391
392 return count;
393 }
394
show_g2d_layer(const char * title,int idx,const g2d_layer & layer)395 static void show_g2d_layer(const char *title, int idx, const g2d_layer &layer)
396 {
397 ALOGD("%s%d: flags %#x, fence %d, buffer_type %d, num_buffers %d", title, idx,
398 layer.flags, layer.fence, layer.buffer_type, layer.num_buffers);
399 for (unsigned int i = 0; i < layer.num_buffers; i++) {
400 ALOGD(" buf[%d] ptr %p, fd %d, offset %u, length %u",
401 i, layer.buffer[i].userptr,
402 layer.buffer[i].dmabuf.fd, layer.buffer[i].dmabuf.offset,
403 layer.buffer[i].length);
404 }
405 }
406
show_g2d_commands(const g2d_commands & cmds)407 static void show_g2d_commands(const g2d_commands &cmds)
408 {
409 for (unsigned int i = 0; i < G2DSFR_DST_FIELD_COUNT; i++)
410 ALOGD("DST[%02d]: %#010x", i, cmds.target[i]);
411
412 for (unsigned int idx = 0; idx < G2D_MAX_IMAGES; idx++) {
413 if (cmds.source[idx]) {
414 for (unsigned int i = 0; i < G2DSFR_SRC_FIELD_COUNT; i++)
415 ALOGD("SRC[%02d][%02d]: %#010x", idx, i, cmds.source[idx][i]);
416 }
417 }
418
419 if (cmds.extra) {
420 for (unsigned int i = 0; i < cmds.num_extra_regs; i++)
421 ALOGD("EXTRA: offset %#010x, value %#010x",
422 cmds.extra[i].offset, cmds.extra[i].value);
423 }
424 }
425
show_g2d_task(const g2d_task & task)426 static void show_g2d_task(const g2d_task &task)
427 {
428 ALOGD("Showing the content of G2D task descriptor ver %#010x", task.version);
429 ALOGD("source count %d, flags %#x, priority %d, num_release_fences %d",
430 task.num_source, task.flags, task.priority, task.num_release_fences);
431 show_g2d_layer("Target", 0, task.target);
432 for (unsigned int i = 0; i < task.num_source; i++)
433 show_g2d_layer("Source", i, task.source[i]);
434 show_g2d_commands(task.commands);
435 }
436
437 #ifdef LIBACRYL_DEBUG
debug_show_g2d_task(const g2d_task & task)438 static void debug_show_g2d_task(const g2d_task &task)
439 {
440 ALOGD("Showing the content of G2D task descriptor ver %#010x", task.version);
441 ALOGD("source count %d, flags %#x, priority %d, num_release_fences %d",
442 task.num_source, task.flags, task.priority, task.num_release_fences);
443 show_g2d_layer("Target", 0, task.target);
444 for (unsigned int i = 0; i < task.num_source; i++)
445 show_g2d_layer("Source", i, task.source[i]);
446 show_g2d_commands(task.commands);
447 }
448 #else
449 #define debug_show_g2d_task(task) do { } while (0)
450 #endif
451
452 struct g2d_fmt {
453 uint32_t halfmt;
454 uint32_t g2dfmt;
455 uint32_t num_bufs;
456 uint32_t rgb_bpp;
457 };
458
459 static g2d_fmt __halfmt_to_g2dfmt_legacy[] = {
460 // {halfmt, g2dfmt, num_buffers, rgbbpp}
461 {HAL_PIXEL_FORMAT_RGBA_8888, G2D_FMT_ABGR8888, 1, 4},
462 {HAL_PIXEL_FORMAT_BGRA_8888, G2D_FMT_ARGB8888, 1, 4},
463 {HAL_PIXEL_FORMAT_RGBX_8888, G2D_FMT_XBGR8888, 1, 4},
464 {HAL_PIXEL_FORMAT_RGBA_1010102, G2D_FMT_ABGR2101010, 1, 4},
465 {HAL_PIXEL_FORMAT_RGB_888, G2D_FMT_RGB888, 1, 3},
466 {HAL_PIXEL_FORMAT_RGB_565, G2D_FMT_RGB565, 1, 2},
467 // {HAL_PIXEL_FORMAT_YV12, G2D_FMT_YV12, 1, 0},
468 // {HAL_PIXEL_FORMAT_EXYNOS_YV12_M, G2D_FMT_YV12, 3, 0},
469 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P, G2D_FMT_YV12, 1, 0},
470 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN, G2D_FMT_YV12, 1, 0},
471 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M, G2D_FMT_YV12, 3, 0},
472 {HAL_PIXEL_FORMAT_YCrCb_420_SP, G2D_FMT_NV21, 1, 0},
473 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, G2D_FMT_NV21, 2, 0},
474 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, G2D_FMT_NV21, 2, 0},
475 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP, G2D_FMT_NV12, 1, 0},
476 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, G2D_FMT_NV12, 2, 0},
477 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, G2D_FMT_NV12, 1, 0},
478 {HAL_PIXEL_FORMAT_YCBCR_P010, G2D_FMT_NV12_P010_LGCY, 1, 0},
479 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, G2D_FMT_NV12_P010_LGCY, 2, 0},
480 {HAL_PIXEL_FORMAT_YCbCr_422_I, G2D_FMT_YUYV, 1, 0},
481 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I, G2D_FMT_YVYU, 1, 0},
482 {HAL_PIXEL_FORMAT_YCbCr_422_SP, G2D_FMT_NV16, 1, 0},
483 // TODO: add p010
484 };
485
486 static g2d_fmt __halfmt_to_g2dfmt[] = {
487 // {halfmt, g2dfmt, num_buffers, rgbbpp}
488 {HAL_PIXEL_FORMAT_RGBA_8888, G2D_FMT_ABGR8888, 1, 4},
489 {HAL_PIXEL_FORMAT_BGRA_8888, G2D_FMT_ARGB8888, 1, 4},
490 {HAL_PIXEL_FORMAT_RGBX_8888, G2D_FMT_XBGR8888, 1, 4},
491 {HAL_PIXEL_FORMAT_RGBA_1010102, G2D_FMT_ABGR2101010, 1, 4},
492 {HAL_PIXEL_FORMAT_RGB_888, G2D_FMT_RGB888, 1, 3},
493 {HAL_PIXEL_FORMAT_RGB_565, G2D_FMT_RGB565, 1, 2},
494 {HAL_PIXEL_FORMAT_YV12, G2D_FMT_YV12, 1, 0},
495 {HAL_PIXEL_FORMAT_EXYNOS_YV12_M, G2D_FMT_YV12, 3, 0},
496 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P, G2D_FMT_YUV420P, 1, 0},
497 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN, G2D_FMT_YUV420P, 1, 0},
498 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M, G2D_FMT_YUV420P, 3, 0},
499 {HAL_PIXEL_FORMAT_YCrCb_420_SP, G2D_FMT_NV21, 1, 0},
500 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, G2D_FMT_NV21, 2, 0},
501 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, G2D_FMT_NV21, 2, 0},
502 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP, G2D_FMT_NV12, 1, 0},
503 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, G2D_FMT_NV12, 2, 0},
504 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, G2D_FMT_NV12, 1, 0},
505 {HAL_PIXEL_FORMAT_GOOGLE_NV12_SP, G2D_FMT_NV12, 1, 0},
506 {MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I, G2D_FMT_NV12, 1, 0},
507 {HAL_PIXEL_FORMAT_YCBCR_P010, G2D_FMT_NV12_P010, 1, 0},
508 {HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B, G2D_FMT_NV12_P010, 1, 0},
509 {MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I, G2D_FMT_NV12_P010, 1, 0},
510 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, G2D_FMT_NV12_P010, 2, 0},
511 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, G2D_FMT_NV12_P010, 1, 0},
512 {MALI_GRALLOC_FORMAT_INTERNAL_P010, G2D_FMT_NV12_P010, 1, 0},
513 {HAL_PIXEL_FORMAT_YCbCr_422_I, G2D_FMT_YUYV, 1, 0},
514 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I, G2D_FMT_YVYU, 1, 0},
515 {HAL_PIXEL_FORMAT_YCbCr_422_SP, G2D_FMT_NV16, 1, 0},
516 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, G2D_FMT_NV12_SBWC, 2, 0},
517 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, G2D_FMT_NV12_SBWC, 1, 0},
518 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC, G2D_FMT_NV12_SBWC_10B, 2, 0},
519 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC, G2D_FMT_NV12_SBWC_10B, 1, 0},
520 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC, G2D_FMT_NV21_SBWC, 2, 0},
521 {HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC, G2D_FMT_NV21_SBWC_10B, 2, 0},
522 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, G2D_FMT_NV12_SBWC, 2, 0},
523 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, G2D_FMT_NV12_SBWC_10B, 2, 0},
524 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, G2D_FMT_NV12_SBWC_10B, 2, 0},
525 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, G2D_FMT_NV12_SBWC, 2, 0},
526 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, G2D_FMT_NV12_SBWC, 1, 0},
527 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, G2D_FMT_NV12_SBWC, 2,0},
528 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, G2D_FMT_NV12_SBWC, 1,0},
529 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, G2D_FMT_NV12_SBWC_10B, 2, 0},
530 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, G2D_FMT_NV12_SBWC_10B, 1, 0},
531 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, G2D_FMT_NV12_SBWC_10B, 2,0},
532 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, G2D_FMT_NV12_SBWC_10B, 1,0},
533 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, G2D_FMT_NV12_SBWC_10B, 2,0},
534 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, G2D_FMT_NV12_SBWC_10B, 1,0},
535 };
536
halfmt_to_g2dfmt(struct g2d_fmt * tbl,size_t tbl_len,uint32_t halfmt)537 static g2d_fmt *halfmt_to_g2dfmt(struct g2d_fmt *tbl, size_t tbl_len, uint32_t halfmt)
538 {
539 for (size_t i = 0 ; i < tbl_len; i++) {
540 if (tbl[i].halfmt == halfmt)
541 return &tbl[i];
542 }
543
544 ALOGE("Unable to find the proper G2D format for HAL format %#x", halfmt);
545
546 return NULL;
547 }
548
AcrylicCompositorG2D(const HW2DCapability & capability,bool newcolormode)549 AcrylicCompositorG2D::AcrylicCompositorG2D(const HW2DCapability &capability, bool newcolormode)
550 : Acrylic(capability), mDev((capability.maxLayerCount() > 2) ? "/dev/g2d" : "/dev/fimg2d"),
551 mMaxSourceCount(0), mPriority(-1)
552 {
553 memset(&mTask, 0, sizeof(mTask));
554
555 mVersion = 0;
556 if (mDev.ioctl(G2D_IOC_VERSION, &mVersion) < 0)
557 ALOGERR("Failed to get G2D command version");
558 ALOGI("G2D API Version %d", mVersion);
559
560 halfmt_to_g2dfmt_tbl = newcolormode ? __halfmt_to_g2dfmt : __halfmt_to_g2dfmt_legacy;
561 len_halfmt_to_g2dfmt_tbl = newcolormode ? ARRSIZE(__halfmt_to_g2dfmt) : ARRSIZE(__halfmt_to_g2dfmt_legacy);
562
563 mUsePolyPhaseFilter = getCapabilities().supportedMinDecimation() == hw2d_coord_t{4, 4};
564
565 ALOGD_TEST("Created a new Acrylic for G2D on %p", this);
566 }
567
~AcrylicCompositorG2D()568 AcrylicCompositorG2D::~AcrylicCompositorG2D()
569 {
570 delete [] mTask.source;
571 delete [] mTask.commands.target;
572 for (unsigned int i = 0; i < mMaxSourceCount; i++)
573 delete [] mTask.commands.source[i];
574
575 ALOGD_TEST("Deleting Acrylic for G2D on %p", this);
576 }
577
updateFilterCoefficients(unsigned int layercount,g2d_reg regs[])578 unsigned int AcrylicCompositorG2D::updateFilterCoefficients(unsigned int layercount, g2d_reg regs[])
579 {
580 if (!mUsePolyPhaseFilter)
581 return 0;
582
583 unsigned int cnt = 0;
584
585 for (unsigned int i = 0; i < layercount; i++)
586 cnt += writeFilterCoefficients(mTask.commands.source[i][G2DSFR_SRC_XSCALE],
587 mTask.commands.source[i][G2DSFR_SRC_YSCALE],
588 mTask.commands.source[i][G2DSFR_IMG_COLORMODE],
589 i, regs + cnt);
590
591 return cnt;
592 }
593
594 #define SBWC_BLOCK_WIDTH 32
595 #define SBWC_BLOCK_HEIGHT 4
596 #define SBWC_BLOCK_SIZE(bit) (SBWC_BLOCK_WIDTH * SBWC_BLOCK_HEIGHT * (bit) / 8)
597
598 #define SBWC_HEADER_ALIGN 16
599 #define SBWC_PAYLOAD_ALIGN 32
600
601 #define SBWC_HEADER_STRIDE(w) \
602 ALIGN(((w) / SBWC_BLOCK_WIDTH / 2), SBWC_HEADER_ALIGN)
603 #define SBWC_PAYLOAD_STRIDE(w, dep)\
604 ALIGN(((w) / SBWC_BLOCK_WIDTH) * SBWC_BLOCK_SIZE(dep), \
605 SBWC_PAYLOAD_ALIGN)
606
607 #define SBWC_LOSSY_PAYLOAD_STRIDE(w, block_byte) \
608 ALIGN(((w) / SBWC_BLOCK_WIDTH) * (block_byte), \
609 SBWC_PAYLOAD_ALIGN)
610
611 static uint32_t mfc_stride_formats[] = {
612 HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN,
613 HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC,
614 HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC,
615 HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC,
616 HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC,
617 HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC,
618 HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC,
619 };
620
621 struct lossy_formats {
622 unsigned int halfmt;
623 unsigned int blocksize;
624 };
625
626 static lossy_formats sbwc_lossy_formats[] {
627 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, 64},
628 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, 64},
629 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, 64},
630 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, 64},
631 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, 96},
632 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, 96},
633 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, 96},
634 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, 96},
635 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, 128},
636 {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, 128},
637 };
638
639
prepareImage(AcrylicCanvas & layer,struct g2d_layer & image,uint32_t cmd[],int index)640 bool AcrylicCompositorG2D::prepareImage(AcrylicCanvas &layer, struct g2d_layer &image, uint32_t cmd[], int index)
641 {
642 image.flags = 0;
643
644 if (layer.getFence() >= 0) {
645 image.flags |= G2D_LAYERFLAG_ACQUIRE_FENCE;
646 image.fence = layer.getFence();
647 }
648
649 if (layer.isProtected())
650 image.flags |= G2D_LAYERFLAG_SECURE;
651
652 g2d_fmt *g2dfmt = halfmt_to_g2dfmt(halfmt_to_g2dfmt_tbl, len_halfmt_to_g2dfmt_tbl, layer.getFormat());
653 if (!g2dfmt)
654 return false;
655
656 image.flags &= ~G2D_LAYERFLAG_MFC_STRIDE;
657 for (size_t i = 0; i < ARRSIZE(mfc_stride_formats); i++) {
658 if (layer.getFormat() == mfc_stride_formats[i]) {
659 image.flags |= G2D_LAYERFLAG_MFC_STRIDE;
660 break;
661 }
662 }
663
664 if (layer.getBufferType() == AcrylicCanvas::MT_EMPTY) {
665 image.buffer_type = G2D_BUFTYPE_EMPTY;
666 } else {
667 if (layer.getBufferCount() < g2dfmt->num_bufs) {
668 ALOGE("HAL Format %#x requires %d buffers but %d buffers are given",
669 layer.getFormat(), g2dfmt->num_bufs, layer.getBufferCount());
670 return false;
671 }
672
673 if (layer.getBufferType() == AcrylicCanvas::MT_DMABUF) {
674 image.buffer_type = G2D_BUFTYPE_DMABUF;
675 for (unsigned int i = 0; i < g2dfmt->num_bufs; i++) {
676 image.buffer[i].dmabuf.fd = layer.getDmabuf(i);
677 image.buffer[i].dmabuf.offset = layer.getOffset(i);
678 image.buffer[i].length = layer.getBufferLength(i);
679 }
680 } else {
681 LOGASSERT(layer.getBufferType() == AcrylicCanvas::MT_USERPTR,
682 "Unknown buffer type %d", layer.getBufferType());
683 image.buffer_type = G2D_BUFTYPE_USERPTR;
684 for (unsigned int i = 0; i < g2dfmt->num_bufs; i++) {
685 image.buffer[i].userptr = layer.getUserptr(i);
686 image.buffer[i].length = layer.getBufferLength(i);
687 }
688 }
689 }
690
691 image.num_buffers = g2dfmt->num_bufs;
692
693 hw2d_coord_t xy = layer.getImageDimension();
694
695 cmd[G2DSFR_IMG_COLORMODE] = g2dfmt->g2dfmt;
696 if (layer.isUOrder())
697 cmd[G2DSFR_IMG_COLORMODE] |= G2D_DATAFORMAT_UORDER;
698
699 if (layer.isCompressed()) {
700 // AFBC forces RGB swizzling order to BGR for RGB565
701 if (g2dfmt->g2dfmt == G2D_FMT_RGB565)
702 cmd[G2DSFR_IMG_COLORMODE] = G2D_FMT_BGR565;
703 cmd[G2DSFR_IMG_COLORMODE] |= G2D_DATAFORMAT_AFBC;
704 cmd[G2DSFR_IMG_STRIDE] = 0;
705 } else if (layer.isCompressedWideblk()) {
706 if (g2dfmt->g2dfmt == G2D_FMT_RGB565) cmd[G2DSFR_IMG_COLORMODE] = G2D_FMT_BGR565;
707 cmd[G2DSFR_IMG_COLORMODE] |= G2D_DATAFORMAT_AFBC;
708 cmd[G2DSFR_IMG_STRIDE] = 0;
709
710 /*Add AFBC image flags for 32x8 block size*/
711 image.flags |= G2D_LAYERFLAG_AFBC_WIDEBLK;
712 } else if (g2dfmt->g2dfmt & G2D_DATAFORMAT_SBWC) {
713 cmd[G2DSFR_IMG_STRIDE] = 0;
714 } else {
715 cmd[G2DSFR_IMG_STRIDE] = g2dfmt->rgb_bpp * xy.hori;
716 }
717
718 unsigned int payload = 0, header = 0, lossyByteNum = 0;
719
720 if (g2dfmt->g2dfmt & G2D_DATAFORMAT_SBWC) {
721 unsigned int blocksize;
722 unsigned int isLossy = 0;
723 unsigned int format = layer.getFormat();
724
725 for (unsigned int i = 0; i < ARRSIZE(sbwc_lossy_formats); i++) {
726 if (format == sbwc_lossy_formats[i].halfmt) {
727 isLossy = 1;
728 blocksize = sbwc_lossy_formats[i].blocksize;
729 break;
730 }
731 }
732
733 if (isLossy) {
734 lossyByteNum = (blocksize >> 1) | isLossy;
735 payload = SBWC_LOSSY_PAYLOAD_STRIDE(xy.hori, blocksize);
736 } else {
737 payload = SBWC_PAYLOAD_STRIDE(xy.hori, (g2dfmt->g2dfmt & G2D_FMT_YCBCR_10BIT) ? 10 : 8);
738 header = SBWC_HEADER_STRIDE(xy.hori);
739 }
740 }
741
742 if (index < 0) {
743 cmd[G2DSFR_DST_Y_HEADER_STRIDE] = header;
744 cmd[G2DSFR_DST_C_HEADER_STRIDE] = header;
745 cmd[G2DSFR_DST_Y_PAYLOAD_STRIDE] = payload;
746 cmd[G2DSFR_DST_C_PAYLOAD_STRIDE] = payload;
747 cmd[G2DSFR_DST_SBWCINFO] = lossyByteNum;
748 } else {
749 cmd[G2DSFR_SRC_Y_HEADER_STRIDE] = header;
750 cmd[G2DSFR_SRC_C_HEADER_STRIDE] = header;
751 cmd[G2DSFR_SRC_Y_PAYLOAD_STRIDE] = payload;
752 cmd[G2DSFR_SRC_C_PAYLOAD_STRIDE] = payload;
753 cmd[G2DSFR_SRC_SBWCINFO] = lossyByteNum;
754 }
755
756 cmd[G2DSFR_IMG_LEFT] = 0;
757 cmd[G2DSFR_IMG_TOP] = 0;
758 cmd[G2DSFR_IMG_RIGHT] = xy.hori;
759 cmd[G2DSFR_IMG_BOTTOM] = xy.vert;
760 cmd[G2DSFR_IMG_WIDTH] = xy.hori;
761 cmd[G2DSFR_IMG_HEIGHT] = xy.vert;
762
763 return true;
764 }
765
setSolidLayer(struct g2d_layer & image,uint32_t cmd[],hw2d_coord_t xy)766 static void setSolidLayer(struct g2d_layer &image, uint32_t cmd[], hw2d_coord_t xy)
767 {
768 image.flags = G2D_LAYERFLAG_COLORFILL;
769 image.buffer_type = G2D_BUFTYPE_EMPTY;
770 image.num_buffers = 0;
771
772 cmd[G2DSFR_IMG_COLORMODE] = G2D_FMT_ARGB8888;
773 cmd[G2DSFR_IMG_STRIDE] = 4 * xy.hori;
774
775 cmd[G2DSFR_IMG_WIDTH] = xy.hori;
776 cmd[G2DSFR_IMG_HEIGHT] = xy.vert;
777
778 cmd[G2DSFR_SRC_SELECT] = G2D_LAYERSEL_COLORFILL;
779 cmd[G2DSFR_SRC_COMMAND] = G2D_LAYERCMD_VALID;
780
781 cmd[G2DSFR_SRC_ROTATE] = 0;
782 cmd[G2DSFR_SRC_SCALECONTROL] = 0;
783 cmd[G2DSFR_SRC_XSCALE] = G2D_SCALE_FACTOR(1, 1);
784 cmd[G2DSFR_SRC_YSCALE] = G2D_SCALE_FACTOR(1, 1);
785 cmd[G2DSFR_SRC_XPHASE] = 0;
786 cmd[G2DSFR_SRC_YPHASE] = 0;
787 cmd[G2DSFR_SRC_YCBCRMODE] = 0;
788 cmd[G2DSFR_SRC_HDRMODE] = 0;
789 cmd[G2DSFR_SRC_Y_HEADER_STRIDE] = 0;
790 cmd[G2DSFR_SRC_C_HEADER_STRIDE] = 0;
791 cmd[G2DSFR_SRC_Y_PAYLOAD_STRIDE] = 0;
792 cmd[G2DSFR_SRC_C_PAYLOAD_STRIDE] = 0;
793 cmd[G2DSFR_SRC_SBWCINFO] = 0;
794 }
795
prepareSolidLayer(AcrylicCanvas & canvas,struct g2d_layer & image,uint32_t cmd[])796 bool AcrylicCompositorG2D::prepareSolidLayer(AcrylicCanvas &canvas, struct g2d_layer &image, uint32_t cmd[])
797 {
798 hw2d_coord_t xy = canvas.getImageDimension();
799
800 setSolidLayer(image, cmd, xy);
801
802 uint16_t a, r, g, b;
803 getBackgroundColor(&r, &g, &b, &a);
804
805 cmd[G2DSFR_SRC_COLOR] = (a & 0xFF00) << 16;
806 cmd[G2DSFR_SRC_COLOR] |= (r & 0xFF00) << 8;
807 cmd[G2DSFR_SRC_COLOR] |= (g & 0xFF00) << 0;
808 cmd[G2DSFR_SRC_COLOR] |= (b & 0xFF00) >> 8;
809
810 cmd[G2DSFR_IMG_LEFT] = 0;
811 cmd[G2DSFR_IMG_TOP] = 0;
812 cmd[G2DSFR_IMG_RIGHT] = xy.hori;
813 cmd[G2DSFR_IMG_BOTTOM] = xy.vert;
814
815 cmd[G2DSFR_SRC_DSTLEFT] = 0;
816 cmd[G2DSFR_SRC_DSTTOP] = 0;
817 cmd[G2DSFR_SRC_DSTRIGHT] = xy.hori;
818 cmd[G2DSFR_SRC_DSTBOTTOM] = xy.vert;
819
820 cmd[G2DSFR_SRC_ALPHA] = 0;
821 cmd[G2DSFR_SRC_BLEND] = 0;
822
823 return true;
824 }
825
prepareSolidLayer(AcrylicLayer & layer,struct g2d_layer & image,uint32_t cmd[],hw2d_coord_t target_size,unsigned int index)826 bool AcrylicCompositorG2D::prepareSolidLayer(AcrylicLayer &layer, struct g2d_layer &image, uint32_t cmd[], hw2d_coord_t target_size, unsigned int index)
827 {
828 hw2d_coord_t xy = layer.getImageDimension();
829
830 setSolidLayer(image, cmd, xy);
831
832 cmd[G2DSFR_SRC_COLOR] = layer.getSolidColor();
833
834 hw2d_rect_t crop = layer.getImageRect();
835 cmd[G2DSFR_IMG_LEFT] = crop.pos.hori;
836 cmd[G2DSFR_IMG_TOP] = crop.pos.vert;
837 cmd[G2DSFR_IMG_RIGHT] = crop.size.hori + crop.pos.hori;
838 cmd[G2DSFR_IMG_BOTTOM] = crop.size.vert + crop.pos.vert;
839
840 hw2d_rect_t window = layer.getTargetRect();
841 if (area_is_zero(window))
842 window.size = target_size;
843 cmd[G2DSFR_SRC_DSTLEFT] = window.pos.hori;
844 cmd[G2DSFR_SRC_DSTTOP] = window.pos.vert;
845 cmd[G2DSFR_SRC_DSTRIGHT] = window.size.hori + window.pos.hori;
846 cmd[G2DSFR_SRC_DSTBOTTOM] = window.size.vert + window.pos.vert;
847
848 uint8_t alpha = layer.getPlaneAlpha();
849 cmd[G2DSFR_SRC_ALPHA] = (alpha << 24) | (alpha << 16) | (alpha << 8) | alpha;
850 if ((layer.getCompositingMode() == HWC_BLENDING_PREMULT) ||
851 (layer.getCompositingMode() == HWC2_BLEND_MODE_PREMULTIPLIED)) {
852 cmd[G2DSFR_SRC_BLEND] = G2D_BLEND_SRCOVER;
853 } else if ((layer.getCompositingMode() == HWC_BLENDING_COVERAGE) ||
854 (layer.getCompositingMode() == HWC2_BLEND_MODE_COVERAGE)) {
855 cmd[G2DSFR_SRC_BLEND] = G2D_BLEND_NONE;
856 } else {
857 cmd[G2DSFR_SRC_BLEND] = G2D_BLEND_SRCCOPY;
858 }
859
860 /* bottom layer always is opaque */
861 if (index == 0) {
862 cmd[G2DSFR_SRC_COMMAND] |= G2D_LAYERCMD_OPAQUE;
863 if (alpha < 255)
864 cmd[G2DSFR_SRC_COMMAND] |= G2D_LAYERCMD_PREMULT_GLOBALALPHA;
865 } else {
866 cmd[G2DSFR_SRC_COMMAND] |= G2D_LAYERCMD_ALPHABLEND;
867 }
868
869 return true;
870 }
871
prepareSource(AcrylicLayer & layer,struct g2d_layer & image,uint32_t cmd[],hw2d_coord_t target_size,unsigned int index,unsigned int image_index)872 bool AcrylicCompositorG2D::prepareSource(AcrylicLayer &layer, struct g2d_layer &image, uint32_t cmd[],
873 hw2d_coord_t target_size, unsigned int index, unsigned int image_index)
874 {
875 if (layer.isSolidColor()) {
876 prepareSolidLayer(layer, image, cmd, target_size, image_index);
877
878 return true;
879 }
880
881 if (!prepareImage(layer, image, cmd, index))
882 return false;
883
884 cmd[G2DSFR_SRC_SELECT] = 0;
885
886 hw2d_rect_t crop = layer.getImageRect();
887 cmd[G2DSFR_IMG_LEFT] = crop.pos.hori;
888 cmd[G2DSFR_IMG_TOP] = crop.pos.vert;
889 cmd[G2DSFR_IMG_RIGHT] = crop.size.hori + crop.pos.hori;
890 cmd[G2DSFR_IMG_BOTTOM] = crop.size.vert + crop.pos.vert;
891
892 hw2d_rect_t window = layer.getTargetRect();
893 if (area_is_zero(window))
894 window.size = target_size;
895 cmd[G2DSFR_SRC_DSTLEFT] = window.pos.hori;
896 cmd[G2DSFR_SRC_DSTTOP] = window.pos.vert;
897 cmd[G2DSFR_SRC_DSTRIGHT] = window.size.hori + window.pos.hori;
898 cmd[G2DSFR_SRC_DSTBOTTOM] = window.size.vert + window.pos.vert;
899
900 if (layer.isCompressed() || layer.isCompressedWideblk()) {
901 cmd[G2DSFR_IMG_WIDTH]--;
902 cmd[G2DSFR_IMG_HEIGHT]--;
903 }
904
905 cmd[G2DSFR_SRC_ROTATE] = 0;
906 // HAL FLIP value: FLIP_H=0x01, FLIP_V=0x02
907 // G2D FLIP value: FLIP_Y=0x05, FLIP_X=0x04
908 unsigned int flip = layer.getTransform() & (HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V);
909 if (!!(layer.getTransform() & HAL_TRANSFORM_ROT_90)) {
910 window.size.swap();
911
912 cmd[G2DSFR_SRC_ROTATE] |= G2D_ROTATEDIR_ROT90CCW;
913 if (!flip || (flip == (HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V)))
914 flip = ~flip & (HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V);
915 }
916
917 cmd[G2DSFR_SRC_ROTATE] |= flip << G2D_ROTATEDIR_FLIP_SHIFT;
918
919 cmd[G2DSFR_SRC_XSCALE] = G2D_SCALE_FACTOR(crop.size.hori, window.size.hori);
920 cmd[G2DSFR_SRC_YSCALE] = G2D_SCALE_FACTOR(crop.size.vert, window.size.vert);
921 // Configure interpolation only if it is required.
922 // Otherwise, G2D needs more bandwidth because it interpolates pixels
923 // even though it is not required.
924 if ((cmd[G2DSFR_SRC_XSCALE] | cmd[G2DSFR_SRC_YSCALE]) == G2D_SCALE_FACTOR(1, 1))
925 cmd[G2DSFR_SRC_SCALECONTROL] = 0;
926 else if (mUsePolyPhaseFilter)
927 cmd[G2DSFR_SRC_SCALECONTROL] = (index << G2D_SCALECONTROL_FILTERCOEF_SHIFT) | G2D_SCALECONTROL_POLYPHASE;
928 else
929 cmd[G2DSFR_SRC_SCALECONTROL] = G2D_SCALECONTROL_BILINEAR;
930
931 // TODO: Configure initial phases according to the scale factors
932 cmd[G2DSFR_SRC_XPHASE] = 0;
933 cmd[G2DSFR_SRC_YPHASE] = 0;
934
935 uint8_t alpha = layer.getPlaneAlpha();
936 cmd[G2DSFR_SRC_ALPHA] = (alpha << 24) | (alpha << 16) | (alpha << 8) | alpha;
937 if ((layer.getCompositingMode() == HWC_BLENDING_PREMULT) ||
938 (layer.getCompositingMode() == HWC2_BLEND_MODE_PREMULTIPLIED)) {
939 cmd[G2DSFR_SRC_BLEND] = G2D_BLEND_SRCOVER;
940 } else if ((layer.getCompositingMode() == HWC_BLENDING_COVERAGE) ||
941 (layer.getCompositingMode() == HWC2_BLEND_MODE_COVERAGE)) {
942 cmd[G2DSFR_SRC_BLEND] = G2D_BLEND_NONE;
943 } else {
944 cmd[G2DSFR_SRC_BLEND] = G2D_BLEND_SRCCOPY;
945
946 // HWC_BLEND_NONE is used not to appear its lower layer to target layer.
947 // But, when G2D output is reused by DPU, lower layer could appear to target layer.
948 // To prevent this, when blend mode is HWC_BLEND_NONE, make alpha channel max.
949 // Example case is as follow.
950 // If G2D composites several layers and topmost layer is HWC_BLEND_NONE
951 // and has alpha lower than max, that alpha value remains in target buffer.
952 // And if this result layer is recomposited with lower layer by DPU
953 // lower layer color appears to final result layer.
954 if ((cmd[G2DSFR_IMG_COLORMODE] == G2D_FMT_ABGR8888) ||
955 (cmd[G2DSFR_IMG_COLORMODE] == G2D_FMT_ARGB8888) ||
956 (cmd[G2DSFR_IMG_COLORMODE] == G2D_FMT_ABGR2101010)) {
957 cmd[G2DSFR_IMG_COLORMODE] &= ~G2D_SWZ_ALPHA_MASK;
958 cmd[G2DSFR_IMG_COLORMODE] |= G2D_SWZ_ALPHA_ONE;
959 }
960 }
961
962 cmd[G2DSFR_SRC_COMMAND] = G2D_LAYERCMD_VALID;
963
964 /* bottom layer always is opaque */
965 if (image_index == 0) {
966 cmd[G2DSFR_SRC_COMMAND] |= G2D_LAYERCMD_OPAQUE;
967 if (alpha < 255)
968 cmd[G2DSFR_SRC_COMMAND] |= G2D_LAYERCMD_PREMULT_GLOBALALPHA;
969 } else {
970 cmd[G2DSFR_SRC_COMMAND] |= G2D_LAYERCMD_ALPHABLEND;
971 }
972
973 cmd[G2DSFR_SRC_YCBCRMODE] = 0;
974 cmd[G2DSFR_SRC_HDRMODE] = 0;
975
976 return true;
977 }
978
reallocLayer(unsigned int layercount)979 bool AcrylicCompositorG2D::reallocLayer(unsigned int layercount)
980 {
981 if (mMaxSourceCount >= layercount)
982 return true;
983
984 if (!mTask.commands.target) {
985 mTask.commands.target = new uint32_t[G2DSFR_DST_FIELD_COUNT];
986 if (!mTask.commands.target) {
987 ALOGE("Failed to allocate command buffer for target image");
988 return false;
989 }
990
991 memset(mTask.commands.target, 0, sizeof(uint32_t) * G2DSFR_DST_FIELD_COUNT);
992 }
993
994 delete [] mTask.source;
995 for (unsigned int i = 0; i < mMaxSourceCount; i++)
996 delete [] mTask.commands.source[i];
997
998 mMaxSourceCount = 0;
999
1000 mTask.source = new g2d_layer[layercount];
1001 if (!mTask.source) {
1002 ALOGE("Failed to allocate %u source image descriptors", layercount);
1003 return false;
1004 }
1005
1006 for (unsigned int i = 0; i < layercount; i++) {
1007 mTask.commands.source[i] = new uint32_t[G2DSFR_SRC_FIELD_COUNT];
1008 if (mTask.commands.source[i] == NULL) {
1009 ALOGE("Failed to allocate command buffer for source image");
1010 while (i-- > 0)
1011 delete [] mTask.commands.source[i];
1012
1013 delete [] mTask.source;
1014 mTask.source = NULL;
1015
1016 return false;
1017 }
1018
1019 memset(mTask.commands.source[i], 0, sizeof(uint32_t) * G2DSFR_SRC_FIELD_COUNT);
1020 }
1021
1022 mMaxSourceCount = layercount;
1023
1024 return true;
1025 }
1026
ioctlG2D(void)1027 int AcrylicCompositorG2D::ioctlG2D(void)
1028 {
1029 if (mVersion == 1) {
1030 if (mDev.ioctl(G2D_IOC_PROCESS, &mTask) < 0)
1031 return -errno;
1032 } else {
1033 struct g2d_compat_task task;
1034
1035 memcpy(&task, &mTask, sizeof(mTask) - sizeof(mTask.commands));
1036 memcpy(task.commands.target, mTask.commands.target, sizeof(task.commands.target));
1037
1038 for (unsigned int i = 0; i < mMaxSourceCount; i++)
1039 task.commands.source[i] = mTask.commands.source[i];
1040
1041 task.commands.extra = mTask.commands.extra;
1042 task.commands.num_extra_regs = mTask.commands.num_extra_regs;
1043
1044 if (mDev.ioctl(G2D_IOC_COMPAT_PROCESS, &task) < 0)
1045 return -errno;
1046
1047 mTask.flags = task.flags;
1048 mTask.laptime_in_usec = task.laptime_in_usec;
1049
1050 for (unsigned int i = 0; i < mTask.num_release_fences; i++)
1051 mTask.release_fence[i] = task.release_fence[i];
1052 }
1053
1054 return 0;
1055 }
1056
executeG2D(int fence[],unsigned int num_fences,bool nonblocking)1057 bool AcrylicCompositorG2D::executeG2D(int fence[], unsigned int num_fences, bool nonblocking)
1058 {
1059 ATRACE_CALL();
1060 if (!validateAllLayers())
1061 return false;
1062
1063 unsigned int layercount = layerCount();
1064
1065 // Set invalid fence fd to the entries exceeds the number of source and destination images
1066 for (unsigned int i = layercount; i < num_fences; i++)
1067 fence[i] = -1;
1068
1069 if (num_fences > layercount + 1)
1070 num_fences = layercount + 1;
1071
1072 bool hasBackground = hasBackgroundColor();
1073
1074 g2d_fmt *g2dfmt = halfmt_to_g2dfmt(halfmt_to_g2dfmt_tbl, len_halfmt_to_g2dfmt_tbl, getCanvas().getFormat());
1075 if (g2dfmt && (g2dfmt->g2dfmt & G2D_DATAFORMAT_SBWC))
1076 hasBackground = true;
1077
1078 if (hasBackground) {
1079 layercount++;
1080
1081 if (layercount > getCapabilities().maxLayerCount()) {
1082 ALOGE("Too many layers %d with the default background color configured", layerCount());
1083 return false;
1084 }
1085 }
1086
1087 if (!reallocLayer(layercount))
1088 return false;
1089
1090 sortLayers();
1091
1092 mTask.flags = 0;
1093
1094 if (!prepareImage(getCanvas(), mTask.target, mTask.commands.target, -1)) {
1095 ALOGE("Failed to configure the target image");
1096 return false;
1097 }
1098
1099 if (getCanvas().isOTF())
1100 mTask.flags |= G2D_FLAG_HWFC;
1101
1102 unsigned int baseidx = 0;
1103
1104 if (hasBackground) {
1105 baseidx++;
1106 prepareSolidLayer(getCanvas(), mTask.source[0], mTask.commands.source[0]);
1107 }
1108
1109 mTask.commands.target[G2DSFR_DST_YCBCRMODE] = 0;
1110
1111 CSCMatrixWriter cscMatrixWriter(mTask.commands.target[G2DSFR_IMG_COLORMODE],
1112 getCanvas().getDataspace(),
1113 &mTask.commands.target[G2DSFR_DST_YCBCRMODE]);
1114
1115 mTask.commands.target[G2DSFR_DST_YCBCRMODE] |= (G2D_LAYER_YCBCRMODE_OFFX | G2D_LAYER_YCBCRMODE_OFFY);
1116
1117 for (unsigned int i = baseidx; i < layercount; i++) {
1118 AcrylicLayer &layer = *getLayer(i - baseidx);
1119
1120 if (!prepareSource(layer, mTask.source[i],
1121 mTask.commands.source[i], getCanvas().getImageDimension(),
1122 i, i - baseidx)) {
1123 ALOGE("Failed to configure source layer %u", i - baseidx);
1124 return false;
1125 }
1126
1127 if (!cscMatrixWriter.configure(mTask.commands.source[i][G2DSFR_IMG_COLORMODE],
1128 layer.getDataspace(),
1129 &mTask.commands.source[i][G2DSFR_SRC_YCBCRMODE])) {
1130 ALOGE("Failed to configure CSC coefficient of layer %d for dataspace %u",
1131 i, layer.getDataspace());
1132 return false;
1133 }
1134
1135 if (layer.getLayerHDR()) {
1136 mHdrWriter.setLayerStaticMetadata(i, layer.getDataspace(),
1137 layer.getMinMasteringLuminance(),
1138 layer.getMaxMasteringLuminance());
1139
1140 bool alpha_premult = (layer.getCompositingMode() == HWC_BLENDING_PREMULT)
1141 || (layer.getCompositingMode() == HWC2_BLEND_MODE_PREMULTIPLIED);
1142 mHdrWriter.setLayerImageInfo(i, layer.getFormat(), alpha_premult);
1143 mHdrWriter.setLayerOpaqueData(i, layer.getLayerData(), layer.getLayerDataLength());
1144 }
1145 }
1146
1147 mHdrWriter.setTargetInfo(getCanvas().getDataspace(), getTargetDisplayInfo());
1148 mHdrWriter.setTargetDisplayLuminance(getMinTargetDisplayLuminance(), getMaxTargetDisplayLuminance());
1149
1150 mHdrWriter.getCommands();
1151 mHdrWriter.getLayerHdrMode(mTask);
1152
1153 mTask.num_source = layercount;
1154
1155 if (nonblocking)
1156 mTask.flags |= G2D_FLAG_NONBLOCK;
1157
1158 mTask.num_release_fences = num_fences;
1159 mTask.release_fence = reinterpret_cast<int *>(alloca(sizeof(int) * num_fences));
1160
1161 mTask.commands.num_extra_regs = cscMatrixWriter.getRegisterCount() +
1162 mHdrWriter.getCommandCount();
1163 if (mUsePolyPhaseFilter)
1164 mTask.commands.num_extra_regs += getFilterCoefficientCount(mTask.commands.source, layercount);
1165
1166 mTask.commands.extra = reinterpret_cast<g2d_reg *>(alloca(sizeof(g2d_reg) * mTask.commands.num_extra_regs));
1167
1168 g2d_reg *regs = mTask.commands.extra;
1169
1170 regs += cscMatrixWriter.write(regs);
1171
1172 regs += updateFilterCoefficients(layercount, regs);
1173
1174 mHdrWriter.write(regs);
1175
1176 debug_show_g2d_task(mTask);
1177
1178 if (ioctlG2D() < 0) {
1179 ALOGERR("Failed to process a task");
1180 show_g2d_task(mTask);
1181 return false;
1182 }
1183
1184 mHdrWriter.putCommands();
1185
1186 if (!!(mTask.flags & G2D_FLAG_ERROR)) {
1187 ALOGE("Error occurred during processing a task to G2D");
1188 show_g2d_task(mTask);
1189 return false;
1190 }
1191
1192 getCanvas().clearSettingModified();
1193 getCanvas().setFence(-1);
1194
1195 for (unsigned int i = 0; i < layerCount(); i++) {
1196 getLayer(i)->clearSettingModified();
1197 getLayer(i)->setFence(-1);
1198 }
1199
1200 for (unsigned int i = 0; i < num_fences; i++)
1201 fence[i] = mTask.release_fence[i];
1202
1203 return true;
1204 }
1205
execute(int fence[],unsigned int num_fences)1206 bool AcrylicCompositorG2D::execute(int fence[], unsigned int num_fences)
1207 {
1208 if (!executeG2D(fence, num_fences, true)) {
1209 // Clearing all acquire fences because their buffers are expired.
1210 // The clients should configure everything again to start new execution
1211 for (unsigned int i = 0; i < layerCount(); i++)
1212 getLayer(i)->setFence(-1);
1213 getCanvas().setFence(-1);
1214
1215 return false;
1216 }
1217
1218 return true;
1219 }
1220
execute(int * handle)1221 bool AcrylicCompositorG2D::execute(int *handle)
1222 {
1223 if (!executeG2D(NULL, 0, handle ? true : false)) {
1224 // Clearing all acquire fences because their buffers are expired.
1225 // The clients should configure everything again to start new execution
1226 for (unsigned int i = 0; i < layerCount(); i++)
1227 getLayer(i)->setFence(-1);
1228 getCanvas().setFence(-1);
1229
1230 return false;
1231 }
1232
1233 if (handle != NULL)
1234 *handle = 1; /* dummy handle */
1235
1236 return true;
1237 }
1238
waitExecution(int __unused handle)1239 bool AcrylicCompositorG2D::waitExecution(int __unused handle)
1240 {
1241 ALOGD_TEST("Waiting for execution of m2m1shot2 G2D completed by handle %d", handle);
1242
1243 return true;
1244 }
1245
requestPerformanceQoS(AcrylicPerformanceRequest * request)1246 bool AcrylicCompositorG2D::requestPerformanceQoS(AcrylicPerformanceRequest *request)
1247 {
1248 g2d_performance data;
1249
1250 memset(&data, 0, sizeof(data));
1251
1252 if (!request || (request->getFrameCount() == 0)) {
1253 if (mDev.ioctl(G2D_IOC_PERFORMANCE, &data) < 0) {
1254 ALOGERR("Failed to cancel performance request");
1255 return false;
1256 }
1257
1258 ALOGD_TEST("Canceled performance request");
1259 return true;
1260 }
1261
1262 ALOGD_TEST("Requesting performance: frame count %d:", request->getFrameCount());
1263 for (int i = 0; i < request->getFrameCount(); i++) {
1264 AcrylicPerformanceRequestFrame *frame = request->getFrame(i);
1265 uint64_t bandwidth = 0;
1266 bool src_yuv420_8b;
1267 bool src_rotate;
1268
1269 src_rotate = false;
1270 src_yuv420_8b = false;
1271
1272 unsigned int bpp;
1273 uint8_t planecount;
1274 uint32_t equiv_fmt;
1275 for (int idx = 0; idx < frame->getLayerCount(); idx++) {
1276 AcrylicPerformanceRequestLayer *layer = &(frame->mLayers[idx]);
1277 uint64_t layer_bw, pixelcount;
1278 int32_t is_scaling;
1279 uint32_t src_hori = layer->mSourceRect.size.hori;
1280 uint32_t src_vert = layer->mSourceRect.size.vert;
1281 uint32_t dst_hori = layer->mTargetRect.size.hori;
1282 uint32_t dst_vert = layer->mTargetRect.size.vert;
1283 data.frame[i].layer[idx].crop_width = src_hori;
1284 data.frame[i].layer[idx].crop_height = src_vert;
1285 data.frame[i].layer[idx].window_width = dst_hori;
1286 data.frame[i].layer[idx].window_height = dst_vert;
1287
1288 // Src layer crop size is used when calculating read bandwidth.
1289 // Crop coordinates should be aligned in multiples of 16.
1290 pixelcount = (ALIGN(layer->mSourceRect.pos.hori + src_hori, 16) -
1291 ALIGN_DOWN(layer->mSourceRect.pos.hori, 16)) *
1292 (ALIGN(layer->mSourceRect.pos.vert + src_vert, 16) -
1293 ALIGN_DOWN(layer->mSourceRect.pos.vert, 16));
1294
1295 bpp = halfmt_bpp(layer->mPixFormat);
1296 planecount = halfmt_plane_count(layer->mPixFormat);
1297 equiv_fmt = find_format_equivalent(layer->mPixFormat);
1298
1299 if (equiv_fmt == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC ||
1300 equiv_fmt == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC)
1301 data.frame[i].layer[idx].layer_attr |= G2D_PERF_LAYER_SBWC;
1302 else if (layer->mAttribute & AcrylicCanvas::ATTR_COMPRESSED) {
1303 if (planecount == 1)
1304 data.frame[i].layer[idx].layer_attr |= G2D_PERF_LAYER_RGB_AFBC;
1305 else
1306 data.frame[i].layer[idx].layer_attr |= G2D_PERF_LAYER_YUV_AFBC;
1307 } else if (planecount == 2)
1308 data.frame[i].layer[idx].layer_attr |= G2D_PERF_LAYER_YUV2P;
1309
1310 // src_yuv420_8b is used when calculating write bandwidth
1311 if (bpp == 12) src_yuv420_8b = true;
1312
1313 layer_bw = pixelcount * bpp;
1314 // Below is checking if scaling is involved.
1315 // Comparisons are replaced by additions to avoid branches.
1316 if (!!(layer->mTransform & HAL_TRANSFORM_ROT_90)) {
1317 src_rotate = true;
1318 data.frame[i].layer[idx].layer_attr |= G2D_PERF_LAYER_ROTATE;
1319
1320 is_scaling = src_hori - dst_vert;
1321 is_scaling += src_vert - dst_hori;
1322 } else {
1323 is_scaling = src_hori - dst_hori;
1324 is_scaling += src_vert - dst_vert;
1325 }
1326 // Weight to the bandwidth when scaling is involved is 1.125.
1327 // It is multiplied by 16 to avoid multiplication with a real number.
1328 // We also get benefit from shift instead of multiplication.
1329 if (is_scaling == 0) {
1330 layer_bw <<= 4; // layer_bw * 16
1331 } else {
1332 layer_bw = (layer_bw << 4) + (layer_bw << 1); // layer_bw * 18
1333 }
1334
1335 bandwidth += layer_bw;
1336 ALOGD_TEST(" LAYER[%d]: BW %llu FMT %#x(%u) (%dx%d)@(%dx%d)on(%dx%d) --> (%dx%d)@(%dx%d) TRFM %#x",
1337 idx, static_cast<unsigned long long>(layer_bw), layer->mPixFormat, bpp,
1338 layer->mSourceRect.size.hori, layer->mSourceRect.size.vert,
1339 layer->mSourceRect.pos.hori, layer->mSourceRect.pos.vert,
1340 layer->mSourceDimension.hori, layer->mSourceDimension.vert,
1341 layer->mTargetRect.size.hori, layer->mTargetRect.size.vert,
1342 layer->mTargetRect.pos.hori, layer->mTargetRect.pos.vert, layer->mTransform);
1343 }
1344
1345 bandwidth *= frame->mFrameRate;
1346 bandwidth >>= 17; // divide by 16(weight), 8(bpp) and 1024(kilobyte)
1347
1348 data.frame[i].bandwidth_read = static_cast<uint32_t>(bandwidth);
1349
1350 bpp = halfmt_bpp(frame->mTargetPixFormat);
1351 bandwidth = frame->mTargetDimension.hori * frame->mTargetDimension.vert;
1352 bandwidth *= frame->mFrameRate * bpp;
1353
1354 // When src rotation is involved, src format includes yuv420(8bit-depth)
1355 // and dst format is yuv420(8bit-depth), weight to the write bandwidth is 2.
1356 // RSH 12 : bw * 2 / (bits_per_byte * kilobyte)
1357 // RHS 13 : bw * 1 / (bits_per_byte * kilobyte)
1358 bandwidth >>= ((bpp == 12) && src_yuv420_8b && src_rotate) ? 12 : 13;
1359 data.frame[i].bandwidth_write = static_cast<uint32_t>(bandwidth);
1360
1361 if (frame->mHasBackgroundLayer)
1362 data.frame[i].frame_attr |= G2D_PERF_FRAME_SOLIDCOLORFILL;
1363
1364 data.frame[i].num_layers = frame->getLayerCount();
1365 data.frame[i].target_pixelcount = frame->mTargetDimension.vert * frame->mTargetDimension.hori;
1366 data.frame[i].frame_rate = frame->mFrameRate;
1367
1368 ALOGD_TEST(" FRAME[%d]: BW:(%u, %u) Layercount %d, Framerate %d, Target %dx%d, FMT %#x Background? %d",
1369 i, data.frame[i].bandwidth_read, data.frame[i].bandwidth_write, data.frame[i].num_layers, frame->mFrameRate,
1370 frame->mTargetDimension.hori, frame->mTargetDimension.vert, frame->mTargetPixFormat,
1371 frame->mHasBackgroundLayer);
1372 }
1373
1374 data.num_frame = request->getFrameCount();
1375
1376 if (mDev.ioctl(G2D_IOC_PERFORMANCE, &data) < 0) {
1377 ALOGERR("Failed to request performance");
1378 return false;
1379 }
1380
1381 return true;
1382 }
1383
prioritize(int priority)1384 int AcrylicCompositorG2D::prioritize(int priority)
1385 {
1386 static int32_t g2d_priorities[] = {
1387 G2D_LOW_PRIORITY, // 0
1388 G2D_MEDIUM_PRIORITY, // 1
1389 G2D_HIGH_PRIORITY, // 2
1390 };
1391
1392 if (priority == mPriority)
1393 return 0;
1394
1395 if (Acrylic::prioritize(priority) < 0)
1396 return -1;
1397
1398 int32_t arg;
1399
1400 if (priority > 2)
1401 arg = G2D_HIGHEST_PRIORITY;
1402 else if (priority < 0)
1403 arg = G2D_DEFAULT_PRIORITY;
1404 else
1405 arg = g2d_priorities[priority];
1406
1407 if (mDev.ioctl(G2D_IOC_PRIORITY, &arg) < 0) {
1408 if (errno != EBUSY) {
1409 ALOGERR("Failed to set priority on a context of G2D");
1410 return -1;
1411 }
1412
1413 ALOGD("G2D Driver returned EBUSY but the priority of %d(%d) is successfully applied", priority, arg);
1414 return 1;
1415 }
1416
1417 ALOGD_TEST("Applied the priority of %d(%d) successfully", priority, arg);
1418
1419 mPriority = priority;
1420
1421 return 0;
1422 }
1423