blob: e6da3e632a7ec0593f6699d0daccb9579f4301a9
1 | /* |
2 | * Copyright (C) 2014 ARM Limited. All rights reserved. |
3 | * |
4 | * Copyright (C) 2008 The Android Open Source Project |
5 | * |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | */ |
18 | #include <hardware/hardware.h> |
19 | #include <cutils/log.h> |
20 | #include <hardware/gralloc.h> |
21 | #include "format_chooser.h" |
22 | |
23 | #ifndef GRALLOC_DISP_W |
24 | #define GRALLOC_DISP_W 0 |
25 | #endif |
26 | #ifndef GRALLOC_DISP_H |
27 | #define GRALLOC_DISP_H 0 |
28 | #endif |
29 | |
30 | /* Minimum size of buffer for AFBC to be enabled. Defined as percentage of total |
31 | * display size */ |
32 | #define GRALLOC_AFBC_MIN_SIZE 75 |
33 | |
34 | static inline int find_format_index(int format) |
35 | { |
36 | int index=-1; |
37 | |
38 | switch ( format ) |
39 | { |
40 | case HAL_PIXEL_FORMAT_RGBA_8888: |
41 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888; |
42 | break; |
43 | case HAL_PIXEL_FORMAT_RGBX_8888: |
44 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888; |
45 | break; |
46 | case HAL_PIXEL_FORMAT_RGB_888: |
47 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888; |
48 | break; |
49 | case HAL_PIXEL_FORMAT_RGB_565: |
50 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565; |
51 | break; |
52 | case HAL_PIXEL_FORMAT_BGRA_8888: |
53 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888; |
54 | break; |
55 | #if PLATFORM_SDK_VERSION >= 19 && PLATFORM_SDK_VERSION <= 22 |
56 | case HAL_PIXEL_FORMAT_sRGB_A_8888: |
57 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_A_8888; |
58 | break; |
59 | case HAL_PIXEL_FORMAT_sRGB_X_8888: |
60 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_X_8888; |
61 | break; |
62 | #endif |
63 | case HAL_PIXEL_FORMAT_YV12: |
64 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12; |
65 | break; |
66 | #if PLATFORM_SDK_VERSION >= 18 |
67 | case HAL_PIXEL_FORMAT_Y8: |
68 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_Y8; |
69 | break; |
70 | case HAL_PIXEL_FORMAT_Y16: |
71 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_Y16; |
72 | break; |
73 | #endif |
74 | case HAL_PIXEL_FORMAT_YCbCr_420_888: |
75 | index = GRALLOC_ARM_HAL_FORMAT_INDEXED_YCbCr_420_888; |
76 | break; |
77 | } |
78 | |
79 | return index; |
80 | } |
81 | |
82 | static bool is_afbc_allowed(int buffer_size) |
83 | { |
84 | bool afbc_allowed = false; |
85 | |
86 | #if !defined(GRALLOC_ARM_NO_EXTERNAL_AFBC) |
87 | if ((GRALLOC_DISP_W*GRALLOC_DISP_H) != 0) |
88 | { |
89 | afbc_allowed = ((buffer_size*100) / (GRALLOC_DISP_W*GRALLOC_DISP_H)) >= GRALLOC_AFBC_MIN_SIZE; |
90 | } |
91 | /* If display size is not valid then always allow AFBC */ |
92 | else |
93 | { |
94 | afbc_allowed = true; |
95 | } |
96 | #endif /* defined(GRALLOC_ARM_NO_EXTERNAL_AFBC) */ |
97 | |
98 | return afbc_allowed; |
99 | } |
100 | |
101 | /* |
102 | * Define GRALLOC_ARM_FORMAT_SELECTION_DISABLE to disable the format selection completely |
103 | * or GRALLOC_ARM_NO_EXTERNAL_AFBC to disable selection of AFBC formats for external buffers. |
104 | */ |
105 | uint64_t gralloc_select_format(int req_format, int usage, int buffer_size) |
106 | { |
107 | #if defined(GRALLOC_ARM_FORMAT_SELECTION_DISABLE) |
108 | (void) usage; |
109 | return (uint64_t) req_format; |
110 | |
111 | #else |
112 | uint64_t new_format = req_format; |
113 | int intformat_ind; |
114 | int n=0; |
115 | int largest_weight_ind=-1; |
116 | int16_t accum_weights[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST] = {0}; |
117 | int afbc_split_mode = 0; |
118 | bool afbc_allowed; |
119 | |
120 | ALOGV("gralloc_select_format: req_format=0x%x usage=0x%x\n",req_format,usage); |
121 | |
122 | /* The GRALLOC_USAGE_PRIVATE_3 set in the usage field indicates the req_format is |
123 | * to be treated as encoded private format instead of trying to find closest match. |
124 | * At the time being, the flag is used for testing AFBC and 10bit YUV that are not |
125 | * yet supported by Android HAL */ |
126 | /* Decode the passed in private format and get the gralloc indexed formats */ |
127 | if (usage & GRALLOC_USAGE_PRIVATE_3) |
128 | { |
129 | uint64_t result = 0; |
130 | /* req_format is within the range for normal AFBC formats */ |
131 | if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC(req_format)) |
132 | { |
133 | req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC; |
134 | result = req_format | GRALLOC_ARM_INTFMT_AFBC; |
135 | switch (req_format & GRALLOC_ARM_INTFMT_FMT_MASK) |
136 | { |
137 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC: |
138 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC: |
139 | result |= GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; |
140 | break; |
141 | } |
142 | return result; |
143 | } |
144 | else if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC_SPLITBLK(req_format)) |
145 | { |
146 | req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK; |
147 | result = req_format | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK; |
148 | /* We don't support yuv 4:2:2 afbc split mode */ |
149 | if (req_format == GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC) |
150 | { |
151 | result |= GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; |
152 | } |
153 | return result; |
154 | } |
155 | else if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_BASE_YUVEXT(req_format)) |
156 | { |
157 | req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_YUVEXT; |
158 | switch (req_format & GRALLOC_ARM_INTFMT_FMT_MASK) |
159 | { |
160 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC: |
161 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC: |
162 | result = (GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV); |
163 | /* pass through */ |
164 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y0L2: |
165 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_P010: |
166 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_P210: |
167 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y210: |
168 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y410: |
169 | /* preserve the format + possible AFBC flag, and add extended-yuv flag */ |
170 | result |= GRALLOC_ARM_INTFMT_EXTENDED_YUV; |
171 | result |= (req_format & (GRALLOC_ARM_INTFMT_FMT_MASK | GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV)); |
172 | break; |
173 | } |
174 | return result; |
175 | } |
176 | else if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC_WIDEBLK(req_format)) |
177 | { |
178 | req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK; |
179 | switch (req_format & GRALLOC_ARM_INTFMT_FMT_MASK) |
180 | { |
181 | case HAL_PIXEL_FORMAT_RGBA_8888: |
182 | case HAL_PIXEL_FORMAT_RGBX_8888: |
183 | case HAL_PIXEL_FORMAT_BGRA_8888: |
184 | case HAL_PIXEL_FORMAT_RGB_888: |
185 | result = req_format | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK; |
186 | break; |
187 | case HAL_PIXEL_FORMAT_RGB_565: |
188 | case HAL_PIXEL_FORMAT_YV12: |
189 | result = req_format | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK; |
190 | break; |
191 | #if 1 == MALI_USE_YUV_AFBC_WIDEBLK |
192 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC: |
193 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC: |
194 | result = req_format | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; |
195 | break; |
196 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC: |
197 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC: |
198 | result = GRALLOC_ARM_INTFMT_EXTENDED_YUV | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; |
199 | result |= (req_format & ( GRALLOC_ARM_INTFMT_FMT_MASK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK )); |
200 | break; |
201 | #else |
202 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC: |
203 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC: |
204 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC: |
205 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC: |
206 | /* invalid format value */ |
207 | return -EINVAL; |
208 | #endif |
209 | default: |
210 | ALOGV("Gralloc gets internal HAL pixel format: 0x%llX", (req_format & GRALLOC_ARM_INTFMT_FMT_MASK)); |
211 | result = req_format | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK; |
212 | break; |
213 | } |
214 | return result; |
215 | } |
216 | else |
217 | { |
218 | /* invalid format value */ |
219 | return -EINVAL; |
220 | } |
221 | } |
222 | |
223 | if (req_format == 0) |
224 | { |
225 | return 0; |
226 | } |
227 | |
228 | if ((usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) != 0 || |
229 | usage == 0) |
230 | { |
231 | return new_format; |
232 | } |
233 | |
234 | #if DISABLE_FRAMEBUFFER_HAL != 1 |
235 | /* This is currently a limitation with the display and will be removed eventually |
236 | * We can't allocate fbdev framebuffer buffers in AFBC format */ |
237 | if (!osd_afbcd_enable()) { |
238 | if (usage & GRALLOC_USAGE_HW_FB) { |
239 | return new_format; |
240 | } |
241 | } |
242 | if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { |
243 | return new_format; |
244 | } |
245 | #endif |
246 | |
247 | /* Implementation defined format set to YCbCr_420_888 interpreted as NV12. */ |
248 | if((req_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) || (req_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) |
249 | { |
250 | return HAL_PIXEL_FORMAT_YCbCr_420_888; |
251 | } |
252 | if (0 == (usage & GRALLOC_USAGE_HW_FB)) { |
253 | return new_format; |
254 | } |
255 | /* if this format can't be classified in one of the groups we |
256 | * have pre-defined, ignore it. |
257 | */ |
258 | intformat_ind = find_format_index( req_format ); |
259 | if (intformat_ind < 0) |
260 | { |
261 | return new_format; |
262 | } |
263 | |
264 | afbc_allowed = is_afbc_allowed(buffer_size); |
265 | while (blklist[n].blk_init != 0) |
266 | { |
267 | if ( (blklist[n].hwblkconf.usage & usage) != 0 ) |
268 | { |
269 | uint32_t m; |
270 | |
271 | for (m=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_FIRST; m<GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST; m++) |
272 | { |
273 | uint64_t internal_format = translate_internal_indexed[m].internal_extended_format; |
274 | bool is_afbc = internal_format & (GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | |
275 | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV); |
276 | |
277 | if ((blklist[n].hwblkconf.weights[intformat_ind][m] != DEFAULT_WEIGHT_UNSUPPORTED) && (!is_afbc || afbc_allowed)) |
278 | { |
279 | accum_weights[m] += blklist[n].hwblkconf.weights[intformat_ind][m]; |
280 | |
281 | if( largest_weight_ind < 0 || |
282 | accum_weights[m] > accum_weights[largest_weight_ind]) |
283 | { |
284 | largest_weight_ind = m; |
285 | } |
286 | } |
287 | else |
288 | { |
289 | /* Format not supported by this hwblk */ |
290 | accum_weights[m] = DEFAULT_WEIGHT_UNSUPPORTED; |
291 | } |
292 | } |
293 | } |
294 | n++; |
295 | } |
296 | |
297 | if ( largest_weight_ind < 0 ) |
298 | { |
299 | new_format = 0; |
300 | } |
301 | else |
302 | { |
303 | new_format = translate_internal_indexed[largest_weight_ind].internal_extended_format; |
304 | } |
305 | |
306 | ALOGV("Returned iterated format: 0x%llX", new_format); |
307 | |
308 | return new_format; |
309 | #endif |
310 | } |
311 | |
312 | extern "C" |
313 | { |
314 | void *gralloc_get_internal_info(int *blkconf_size, int *gpu_conf) |
315 | { |
316 | void *blkinit_address = NULL; |
317 | |
318 | #if !defined(GRALLOC_ARM_FORMAT_SELECTION_DISABLE) |
319 | |
320 | if (blkconf_size != NULL && gpu_conf != NULL) |
321 | { |
322 | blkinit_address = (void*) blklist; |
323 | *blkconf_size = blklist_array_size; |
324 | |
325 | /* |
326 | * Tests intended to verify gralloc format selection behavior are GPU version aware in runtime. |
327 | * They need to know what configuration we built for. For now this is simply AFBC on or off. This |
328 | * will likely change in the future to mean something else. |
329 | */ |
330 | #if MALI_AFBC_GRALLOC == 1 |
331 | *gpu_conf = 1; |
332 | #else |
333 | *gpu_conf = 0; |
334 | #endif /* MALI_AFBC_GRALLOC */ |
335 | } |
336 | |
337 | #endif /* GRALLOC_ARM_FORMAT_SELECTION_DISABLE */ |
338 | |
339 | return blkinit_address; |
340 | } |
341 | |
342 | int gralloc_get_internal_format(int hal_format) |
343 | { |
344 | return find_format_index(hal_format); |
345 | } |
346 | } |
347 |