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                         &regs[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                         &regs[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