summaryrefslogtreecommitdiff
path: root/format_chooser.cpp (plain)
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
34static 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
82static 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 */
105uint64_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
312extern "C"
313{
314void *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
342int gralloc_get_internal_format(int hal_format)
343{
344 return find_format_index(hal_format);
345}
346}
347