1 /*
2 * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
3
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <cutils/log.h>
31 #include <fcntl.h>
32 #include <dlfcn.h>
33 #include "gralloc_priv.h"
34 #include "alloc_controller.h"
35 #include "memalloc.h"
36 #include "ionalloc.h"
37 #include "gr.h"
38 #include "comptype.h"
39 #include "mdp_version.h"
40
41 #ifdef VENUS_COLOR_FORMAT
42 #include <media/msm_media_info.h>
43 #else
44 #define VENUS_Y_STRIDE(args...) 0
45 #define VENUS_Y_SCANLINES(args...) 0
46 #define VENUS_BUFFER_SIZE(args...) 0
47 #endif
48
49 #define ASTC_BLOCK_SIZE 16
50
51 using namespace gralloc;
52 using namespace qdutils;
53
54 ANDROID_SINGLETON_STATIC_INSTANCE(AdrenoMemInfo);
55
56 static void getUBwcWidthAndHeight(int, int, int, int&, int&);
57 static unsigned int getUBwcSize(int, int, int, const int, const int);
58
59 //Common functions
canFallback(int usage,bool triedSystem)60 static bool canFallback(int usage, bool triedSystem)
61 {
62 // Fallback to system heap when alloc fails unless
63 // 1. Composition type is MDP
64 // 2. Alloc from system heap was already tried
65 // 3. The heap type is requsted explicitly
66 // 4. The heap type is protected
67 // 5. The buffer is meant for external display only
68
69 if(QCCompositionType::getInstance().getCompositionType() &
70 COMPOSITION_TYPE_MDP)
71 return false;
72 if(triedSystem)
73 return false;
74 if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED))
75 return false;
76 if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY))
77 return false;
78 //Return true by default
79 return true;
80 }
81
82 /* The default policy is to return cached buffers unless the client explicity
83 * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
84 * read or written in software. Any combination with a _RARELY_ flag will be
85 * treated as uncached. */
useUncached(const int & usage)86 static bool useUncached(const int& usage) {
87 if ((usage & GRALLOC_USAGE_PROTECTED) or
88 (usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
89 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY) or
90 ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY))
91 return true;
92
93 return false;
94 }
95
96 //-------------- AdrenoMemInfo-----------------------//
AdrenoMemInfo()97 AdrenoMemInfo::AdrenoMemInfo()
98 {
99 LINK_adreno_compute_aligned_width_and_height = NULL;
100 LINK_adreno_compute_padding = NULL;
101 LINK_adreno_isMacroTilingSupportedByGpu = NULL;
102 LINK_adreno_compute_compressedfmt_aligned_width_and_height = NULL;
103 LINK_adreno_isUBWCSupportedByGpu = NULL;
104
105 libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
106 if (libadreno_utils) {
107 *(void **)&LINK_adreno_compute_aligned_width_and_height =
108 ::dlsym(libadreno_utils, "compute_aligned_width_and_height");
109 *(void **)&LINK_adreno_compute_padding =
110 ::dlsym(libadreno_utils, "compute_surface_padding");
111 *(void **)&LINK_adreno_isMacroTilingSupportedByGpu =
112 ::dlsym(libadreno_utils, "isMacroTilingSupportedByGpu");
113 *(void **)&LINK_adreno_compute_compressedfmt_aligned_width_and_height =
114 ::dlsym(libadreno_utils,
115 "compute_compressedfmt_aligned_width_and_height");
116 *(void **)&LINK_adreno_isUBWCSupportedByGpu =
117 ::dlsym(libadreno_utils, "isUBWCSupportedByGpu");
118 }
119 }
120
~AdrenoMemInfo()121 AdrenoMemInfo::~AdrenoMemInfo()
122 {
123 if (libadreno_utils) {
124 ::dlclose(libadreno_utils);
125 }
126 }
127
isMacroTilingSupportedByGPU()128 int AdrenoMemInfo::isMacroTilingSupportedByGPU()
129 {
130 if ((libadreno_utils)) {
131 if(LINK_adreno_isMacroTilingSupportedByGpu) {
132 return LINK_adreno_isMacroTilingSupportedByGpu();
133 }
134 }
135 return 0;
136 }
137
138
isUncompressedRgbFormat(int format)139 bool isUncompressedRgbFormat(int format)
140 {
141 bool is_rgb_format = false;
142
143 switch (format)
144 {
145 case HAL_PIXEL_FORMAT_RGBA_8888:
146 case HAL_PIXEL_FORMAT_RGBX_8888:
147 case HAL_PIXEL_FORMAT_RGB_888:
148 case HAL_PIXEL_FORMAT_RGB_565:
149 case HAL_PIXEL_FORMAT_BGRA_8888:
150 case HAL_PIXEL_FORMAT_RGBA_1010102:
151 case HAL_PIXEL_FORMAT_RGBA_FP16:
152 case HAL_PIXEL_FORMAT_RGBA_5551:
153 case HAL_PIXEL_FORMAT_RGBA_4444:
154 case HAL_PIXEL_FORMAT_R_8:
155 case HAL_PIXEL_FORMAT_RG_88:
156 case HAL_PIXEL_FORMAT_BGRX_8888: // Intentional fallthrough
157 is_rgb_format = true;
158 break;
159 default:
160 break;
161 }
162
163 return is_rgb_format;
164 }
165
getAlignedWidthAndHeight(int width,int height,int format,int usage,int & aligned_w,int & aligned_h)166 void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
167 int usage, int& aligned_w, int& aligned_h)
168 {
169
170 // Currently surface padding is only computed for RGB* surfaces.
171 if (isUncompressedRgbFormat(format) == true) {
172 int tileEnabled = isMacroTileEnabled(format, usage);
173 AdrenoMemInfo::getInstance().getGpuAlignedWidthHeight(width,
174 height, format, tileEnabled, aligned_w, aligned_h);
175 return;
176 }
177
178 if (isUBwcEnabled(format, usage)) {
179 getUBwcWidthAndHeight(width, height, format, aligned_w, aligned_h);
180 return;
181 }
182
183 aligned_w = width;
184 aligned_h = height;
185 switch (format)
186 {
187 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
188 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
189 aligned_w = ALIGN(width, 32);
190 break;
191 case HAL_PIXEL_FORMAT_RAW16:
192 aligned_w = ALIGN(width, 16);
193 break;
194 case HAL_PIXEL_FORMAT_RAW10:
195 aligned_w = ALIGN(width * 10 /8, 8);
196 break;
197 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
198 aligned_w = ALIGN(width, 128);
199 break;
200 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
201 case HAL_PIXEL_FORMAT_YV12:
202 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
203 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
204 case HAL_PIXEL_FORMAT_YCbCr_422_I:
205 case HAL_PIXEL_FORMAT_YCrCb_422_I:
206 aligned_w = ALIGN(width, 16);
207 break;
208 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
209 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
210 aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
211 aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
212 break;
213 case HAL_PIXEL_FORMAT_BLOB:
214 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
215 break;
216 case HAL_PIXEL_FORMAT_NV21_ZSL:
217 aligned_w = ALIGN(width, 64);
218 aligned_h = ALIGN(height, 64);
219 break;
220 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
221 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
222 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
223 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
224 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
225 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
226 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
227 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
228 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
229 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
230 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
231 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
232 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
233 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
234 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
235 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
236 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
237 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
238 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
239 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
240 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
241 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
242 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
243 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
244 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
245 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
246 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
247 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
248 if(LINK_adreno_compute_compressedfmt_aligned_width_and_height) {
249 int bytesPerPixel = 0;
250 int raster_mode = 0; //Adreno unknown raster mode.
251 int padding_threshold = 512; //Threshold for padding
252 //surfaces.
253
254 LINK_adreno_compute_compressedfmt_aligned_width_and_height(
255 width, height, format, 0,raster_mode, padding_threshold,
256 &aligned_w, &aligned_h, &bytesPerPixel);
257 } else {
258 ALOGW("%s: Warning!! Symbols" \
259 " compute_compressedfmt_aligned_width_and_height" \
260 " not found", __FUNCTION__);
261 }
262 break;
263 default: break;
264 }
265 }
266
getGpuAlignedWidthHeight(int width,int height,int format,int tile_enabled,int & aligned_w,int & aligned_h)267 void AdrenoMemInfo::getGpuAlignedWidthHeight(int width, int height, int format,
268 int tile_enabled, int& aligned_w, int& aligned_h)
269 {
270 aligned_w = ALIGN(width, 32);
271 aligned_h = ALIGN(height, 32);
272
273 // Don't add any additional padding if debug.gralloc.map_fb_memory
274 // is enabled
275 char property[PROPERTY_VALUE_MAX];
276 if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
277 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
278 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
279 return;
280 }
281
282 int bpp = 4;
283 switch(format)
284 {
285 case HAL_PIXEL_FORMAT_RGBA_FP16:
286 bpp = 8;
287 break;
288 case HAL_PIXEL_FORMAT_RGB_888:
289 bpp = 3;
290 break;
291 case HAL_PIXEL_FORMAT_RGB_565:
292 case HAL_PIXEL_FORMAT_RGBA_5551:
293 case HAL_PIXEL_FORMAT_RGBA_4444:
294 bpp = 2;
295 break;
296 default: break;
297 }
298
299 if (libadreno_utils) {
300 int raster_mode = 0; // Adreno unknown raster mode.
301 int padding_threshold = 512; // Threshold for padding surfaces.
302 // the function below computes aligned width and aligned height
303 // based on linear or macro tile mode selected.
304 if(LINK_adreno_compute_aligned_width_and_height) {
305 LINK_adreno_compute_aligned_width_and_height(width,
306 height, bpp, tile_enabled,
307 raster_mode, padding_threshold,
308 &aligned_w, &aligned_h);
309
310 } else if(LINK_adreno_compute_padding) {
311 int surface_tile_height = 1; // Linear surface
312 aligned_w = LINK_adreno_compute_padding(width, bpp,
313 surface_tile_height, raster_mode,
314 padding_threshold);
315 ALOGW("%s: Warning!! Old GFX API is used to calculate stride",
316 __FUNCTION__);
317 } else {
318 ALOGW("%s: Warning!! Symbols compute_surface_padding and " \
319 "compute_aligned_width_and_height not found", __FUNCTION__);
320 }
321 }
322 }
323
isUBWCSupportedByGPU(int format)324 int AdrenoMemInfo::isUBWCSupportedByGPU(int format)
325 {
326 if (libadreno_utils) {
327 if (LINK_adreno_isUBWCSupportedByGpu) {
328 ADRENOPIXELFORMAT gpu_format = getGpuPixelFormat(format);
329 return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
330 }
331 }
332 return 0;
333 }
334
getGpuPixelFormat(int hal_format)335 ADRENOPIXELFORMAT AdrenoMemInfo::getGpuPixelFormat(int hal_format)
336 {
337 switch (hal_format) {
338 case HAL_PIXEL_FORMAT_RGBA_8888:
339 return ADRENO_PIXELFORMAT_R8G8B8A8;
340 case HAL_PIXEL_FORMAT_RGB_565:
341 return ADRENO_PIXELFORMAT_B5G6R5;
342 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
343 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
344 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
345 return ADRENO_PIXELFORMAT_NV12;
346 default:
347 ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
348 break;
349 }
350 return ADRENO_PIXELFORMAT_UNKNOWN;
351 }
352
353 //-------------- IAllocController-----------------------//
354 IAllocController* IAllocController::sController = NULL;
getInstance(void)355 IAllocController* IAllocController::getInstance(void)
356 {
357 if(sController == NULL) {
358 sController = new IonController();
359 }
360 return sController;
361 }
362
363
364 //-------------- IonController-----------------------//
IonController()365 IonController::IonController()
366 {
367 allocateIonMem();
368 }
369
allocateIonMem()370 void IonController::allocateIonMem()
371 {
372 mIonAlloc = new IonAlloc();
373 }
374
allocate(alloc_data & data,int usage)375 int IonController::allocate(alloc_data& data, int usage)
376 {
377 int ionFlags = 0;
378 int ret;
379
380 data.uncached = useUncached(usage);
381 data.allocType = 0;
382
383 if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
384 ionFlags |= ION_HEAP(ION_SYSTEM_HEAP_ID);
385
386 if(usage & GRALLOC_USAGE_PRIVATE_IOMMU_HEAP)
387 ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
388
389 if(usage & GRALLOC_USAGE_PROTECTED) {
390 ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
391 ionFlags |= ION_SECURE;
392 #ifdef ION_FLAG_ALLOW_NON_CONTIG
393 if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
394 ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
395 }
396 #endif
397 } else if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
398 //MM Heap is exclusively a secure heap.
399 //If it is used for non secure cases, fallback to IOMMU heap
400 ALOGW("GRALLOC_USAGE_PRIVATE_MM_HEAP \
401 cannot be used as an insecure heap!\
402 trying to use IOMMU instead !!");
403 ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
404 }
405
406 if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP)
407 ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID);
408
409 if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
410 ionFlags |= ION_HEAP(ION_ADSP_HEAP_ID);
411
412 if(ionFlags & ION_SECURE)
413 data.allocType |= private_handle_t::PRIV_FLAGS_SECURE_BUFFER;
414
415 // if no flags are set, default to
416 // SF + IOMMU heaps, so that bypass can work
417 // we can fall back to system heap if
418 // we run out.
419 if(!ionFlags)
420 ionFlags = ION_HEAP(ION_SF_HEAP_ID) | ION_HEAP(ION_IOMMU_HEAP_ID);
421
422 data.flags = ionFlags;
423 ret = mIonAlloc->alloc_buffer(data);
424
425 // Fallback
426 if(ret < 0 && canFallback(usage,
427 (ionFlags & ION_SYSTEM_HEAP_ID)))
428 {
429 ALOGW("Falling back to system heap");
430 data.flags = ION_HEAP(ION_SYSTEM_HEAP_ID);
431 ret = mIonAlloc->alloc_buffer(data);
432 }
433
434 if(ret >= 0 ) {
435 data.allocType |= private_handle_t::PRIV_FLAGS_USES_ION;
436 }
437
438 return ret;
439 }
440
getAllocator(int flags)441 IMemAlloc* IonController::getAllocator(int flags)
442 {
443 IMemAlloc* memalloc = NULL;
444 if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
445 memalloc = mIonAlloc;
446 } else {
447 ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
448 }
449
450 return memalloc;
451 }
452
isMacroTileEnabled(int format,int usage)453 bool isMacroTileEnabled(int format, int usage)
454 {
455 bool tileEnabled = false;
456
457 // Check whether GPU & MDSS supports MacroTiling feature
458 if(AdrenoMemInfo::getInstance().isMacroTilingSupportedByGPU() &&
459 qdutils::MDPVersion::getInstance().supportsMacroTile())
460 {
461 // check the format
462 switch(format)
463 {
464 case HAL_PIXEL_FORMAT_RGBA_8888:
465 case HAL_PIXEL_FORMAT_RGBX_8888:
466 case HAL_PIXEL_FORMAT_BGRA_8888:
467 case HAL_PIXEL_FORMAT_RGB_565:
468 {
469 tileEnabled = true;
470 // check the usage flags
471 if (usage & (GRALLOC_USAGE_SW_READ_MASK |
472 GRALLOC_USAGE_SW_WRITE_MASK)) {
473 // Application intends to use CPU for rendering
474 tileEnabled = false;
475 }
476 break;
477 }
478 default:
479 break;
480 }
481 }
482 return tileEnabled;
483 }
484
485 // helper function
getSize(int format,int width,int height,int usage,const int alignedw,const int alignedh)486 unsigned int getSize(int format, int width, int height, int usage,
487 const int alignedw, const int alignedh) {
488
489 if (isUBwcEnabled(format, usage)) {
490 return getUBwcSize(width, height, format, alignedw, alignedh);
491 }
492
493 unsigned int size = 0;
494 switch (format) {
495 case HAL_PIXEL_FORMAT_RGBA_FP16:
496 size = alignedw * alignedh * 8;
497 break;
498 case HAL_PIXEL_FORMAT_RGBA_8888:
499 case HAL_PIXEL_FORMAT_RGBX_8888:
500 case HAL_PIXEL_FORMAT_BGRA_8888:
501 case HAL_PIXEL_FORMAT_RGBA_1010102:
502 size = alignedw * alignedh * 4;
503 break;
504 case HAL_PIXEL_FORMAT_RGB_888:
505 size = alignedw * alignedh * 3;
506 break;
507 case HAL_PIXEL_FORMAT_RGB_565:
508 case HAL_PIXEL_FORMAT_RGBA_5551:
509 case HAL_PIXEL_FORMAT_RGBA_4444:
510 case HAL_PIXEL_FORMAT_RAW16:
511 size = alignedw * alignedh * 2;
512 break;
513 case HAL_PIXEL_FORMAT_RAW10:
514 size = ALIGN(alignedw * alignedh, 4096);
515 break;
516 // adreno formats
517 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21
518 size = ALIGN(alignedw*alignedh, 4096);
519 size += ALIGN(2 * ALIGN(width/2, 32) * ALIGN(height/2, 32), 4096);
520 break;
521 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12
522 // The chroma plane is subsampled,
523 // but the pitch in bytes is unchanged
524 // The GPU needs 4K alignment, but the video decoder needs 8K
525 size = ALIGN( alignedw * alignedh, 8192);
526 size += ALIGN( alignedw * ALIGN(height/2, 32), 8192);
527 break;
528 case HAL_PIXEL_FORMAT_YV12:
529 if ((format == HAL_PIXEL_FORMAT_YV12) && ((width&1) || (height&1))) {
530 ALOGE("w or h is odd for the YV12 format");
531 return 0;
532 }
533 size = alignedw*alignedh +
534 (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
535 size = ALIGN(size, (unsigned int)4096);
536 break;
537 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
538 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
539 size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2 + 1, 4096);
540 break;
541 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
542 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
543 case HAL_PIXEL_FORMAT_YCbCr_422_I:
544 case HAL_PIXEL_FORMAT_YCrCb_422_I:
545 if(width & 1) {
546 ALOGE("width is odd for the YUV422_SP format");
547 return 0;
548 }
549 size = ALIGN(alignedw * alignedh * 2, 4096);
550 break;
551 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
552 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
553 size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
554 break;
555 case HAL_PIXEL_FORMAT_BLOB:
556 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
557 if(height != 1) {
558 ALOGE("%s: Buffers with RAW_OPAQUE/blob formats \
559 must have height==1 ", __FUNCTION__);
560 return 0;
561 }
562 size = width;
563 break;
564 case HAL_PIXEL_FORMAT_NV21_ZSL:
565 size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2, 4096);
566 break;
567 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
568 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
569 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
570 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
571 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
572 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
573 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
574 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
575 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
576 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
577 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
578 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
579 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
580 case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
581 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
582 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
583 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
584 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
585 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
586 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
587 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
588 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
589 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
590 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
591 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
592 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
593 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
594 case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
595 size = alignedw * alignedh * ASTC_BLOCK_SIZE;
596 break;
597 default:
598 ALOGE("%s: Unrecognized pixel format: 0x%x", __FUNCTION__, format);
599 return 0;
600 }
601 return size;
602 }
603
getBufferSizeAndDimensions(int width,int height,int format,int & alignedw,int & alignedh)604 unsigned int getBufferSizeAndDimensions(int width, int height, int format,
605 int& alignedw, int &alignedh)
606 {
607 unsigned int size;
608
609 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
610 height,
611 format,
612 0,
613 alignedw,
614 alignedh);
615
616 size = getSize(format, width, height, 0 /* usage */, alignedw, alignedh);
617
618 return size;
619 }
620
621
getBufferSizeAndDimensions(int width,int height,int format,int usage,int & alignedw,int & alignedh)622 unsigned int getBufferSizeAndDimensions(int width, int height, int format,
623 int usage, int& alignedw, int &alignedh)
624 {
625 unsigned int size;
626
627 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
628 height,
629 format,
630 usage,
631 alignedw,
632 alignedh);
633
634 size = getSize(format, width, height, usage, alignedw, alignedh);
635
636 return size;
637 }
638
639
getBufferAttributes(int width,int height,int format,int usage,int & alignedw,int & alignedh,int & tileEnabled,unsigned int & size)640 void getBufferAttributes(int width, int height, int format, int usage,
641 int& alignedw, int &alignedh, int& tileEnabled, unsigned int& size)
642 {
643 tileEnabled = isMacroTileEnabled(format, usage);
644
645 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
646 height,
647 format,
648 usage,
649 alignedw,
650 alignedh);
651 size = getSize(format, width, height, usage, alignedw, alignedh);
652 }
653
getYUVPlaneInfo(private_handle_t * hnd,struct android_ycbcr * ycbcr)654 int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
655 {
656 int err = 0;
657 unsigned int ystride, cstride;
658 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
659
660 // Get the chroma offsets from the handle width/height. We take advantage
661 // of the fact the width _is_ the stride
662 switch (hnd->format) {
663 //Semiplanar
664 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
665 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
666 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
667 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
668 ystride = cstride = hnd->width;
669 ycbcr->y = (void*)hnd->base;
670 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
671 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
672 ycbcr->ystride = ystride;
673 ycbcr->cstride = cstride;
674 ycbcr->chroma_step = 2;
675 break;
676
677 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
678 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
679 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
680 case HAL_PIXEL_FORMAT_NV21_ZSL:
681 case HAL_PIXEL_FORMAT_RAW10:
682 case HAL_PIXEL_FORMAT_RAW16:
683 ystride = cstride = hnd->width;
684 ycbcr->y = (void*)hnd->base;
685 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
686 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
687 ycbcr->ystride = ystride;
688 ycbcr->cstride = cstride;
689 ycbcr->chroma_step = 2;
690 break;
691
692 //Planar
693 case HAL_PIXEL_FORMAT_YV12:
694 ystride = hnd->width;
695 cstride = ALIGN(hnd->width/2, 16);
696 ycbcr->y = (void*)hnd->base;
697 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
698 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
699 cstride * hnd->height/2);
700 ycbcr->ystride = ystride;
701 ycbcr->cstride = cstride;
702 ycbcr->chroma_step = 1;
703
704 break;
705 //Unsupported formats
706 case HAL_PIXEL_FORMAT_YCbCr_422_I:
707 case HAL_PIXEL_FORMAT_YCrCb_422_I:
708 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
709 default:
710 ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
711 hnd->format);
712 err = -EINVAL;
713 }
714 return err;
715
716 }
717
718
719
720 // Allocate buffer from width, height and format into a
721 // private_handle_t. It is the responsibility of the caller
722 // to free the buffer using the free_buffer function
alloc_buffer(private_handle_t ** pHnd,int w,int h,int format,int usage)723 int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage)
724 {
725 alloc_data data;
726 int alignedw, alignedh;
727 gralloc::IAllocController* sAlloc =
728 gralloc::IAllocController::getInstance();
729 data.base = 0;
730 data.fd = -1;
731 data.offset = 0;
732 data.size = getBufferSizeAndDimensions(w, h, format, usage, alignedw,
733 alignedh);
734
735 data.align = getpagesize();
736 data.uncached = useUncached(usage);
737 int allocFlags = usage;
738
739 int err = sAlloc->allocate(data, allocFlags);
740 if (0 != err) {
741 ALOGE("%s: allocate failed", __FUNCTION__);
742 return -ENOMEM;
743 }
744
745 private_handle_t* hnd = new private_handle_t(data.fd, data.size,
746 data.allocType, 0, format,
747 alignedw, alignedh);
748 hnd->base = (uint64_t) data.base;
749 hnd->offset = data.offset;
750 hnd->gpuaddr = 0;
751 *pHnd = hnd;
752 return 0;
753 }
754
free_buffer(private_handle_t * hnd)755 void free_buffer(private_handle_t *hnd)
756 {
757 gralloc::IAllocController* sAlloc =
758 gralloc::IAllocController::getInstance();
759 if (hnd && hnd->fd > 0) {
760 IMemAlloc* memalloc = sAlloc->getAllocator(hnd->flags);
761 memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
762 }
763 if(hnd)
764 delete hnd;
765
766 }
767
768 // UBWC helper functions
isUBwcFormat(int format)769 static bool isUBwcFormat(int format)
770 {
771 // Explicitly defined UBWC formats
772 switch(format)
773 {
774 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
775 return true;
776 default:
777 return false;
778 }
779 }
780
isUBwcSupported(int format)781 static bool isUBwcSupported(int format)
782 {
783 // Existing HAL formats with UBWC support
784 switch(format)
785 {
786 case HAL_PIXEL_FORMAT_RGB_565:
787 case HAL_PIXEL_FORMAT_RGBA_8888:
788 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
789 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
790 return true;
791 default:
792 return false;
793 }
794 }
795
isUBwcEnabled(int format,int usage)796 bool isUBwcEnabled(int format, int usage)
797 {
798 if (isUBwcFormat(format) ||
799 ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)))
800 {
801 // Allow UBWC, only if GPU supports it and CPU usage flags are not set
802 if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
803 !(usage & (GRALLOC_USAGE_SW_READ_MASK |
804 GRALLOC_USAGE_SW_WRITE_MASK))) {
805 return true;
806 }
807 }
808 return false;
809 }
810
getUBwcWidthAndHeight(int width,int height,int format,int & aligned_w,int & aligned_h)811 static void getUBwcWidthAndHeight(int width, int height, int format,
812 int& aligned_w, int& aligned_h)
813 {
814 switch (format)
815 {
816 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
817 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
818 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
819 aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
820 aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height);
821 break;
822 default:
823 ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
824 aligned_w = 0;
825 aligned_h = 0;
826 break;
827 }
828 }
829
getUBwcBlockSize(int bpp,int & block_width,int & block_height)830 static void getUBwcBlockSize(int bpp, int& block_width, int& block_height)
831 {
832 block_width = 0;
833 block_height = 0;
834
835 switch(bpp)
836 {
837 case 2:
838 case 4:
839 block_width = 16;
840 block_height = 4;
841 break;
842 case 8:
843 block_width = 8;
844 block_height = 4;
845 break;
846 case 16:
847 block_width = 4;
848 block_height = 4;
849 break;
850 default:
851 ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
852 break;
853 }
854 }
855
getUBwcMetaBufferSize(int width,int height,int bpp)856 static unsigned int getUBwcMetaBufferSize(int width, int height, int bpp)
857 {
858 unsigned int size = 0;
859 int meta_width, meta_height;
860 int block_width, block_height;
861
862 getUBwcBlockSize(bpp, block_width, block_height);
863
864 if (!block_width || !block_height) {
865 ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
866 return size;
867 }
868
869 // Align meta buffer height to 16 blocks
870 meta_height = ALIGN(((height + block_height - 1) / block_height), 16);
871
872 // Align meta buffer width to 64 blocks
873 meta_width = ALIGN(((width + block_width - 1) / block_width), 64);
874
875 // Align meta buffer size to 4K
876 size = ((meta_width * meta_height), 4096);
877 return size;
878 }
879
getUBwcSize(int width,int height,int format,const int alignedw,const int alignedh)880 static unsigned int getUBwcSize(int width, int height, int format,
881 const int alignedw, const int alignedh) {
882
883 unsigned int size = 0;
884 switch (format) {
885 case HAL_PIXEL_FORMAT_RGB_565:
886 size = alignedw * alignedh * 2;
887 size += getUBwcMetaBufferSize(width, height, 2);
888 break;
889 case HAL_PIXEL_FORMAT_RGBA_8888:
890 size = alignedw * alignedh * 4;
891 size += getUBwcMetaBufferSize(width, height, 4);
892 break;
893 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
894 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
895 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
896 size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
897 break;
898 default:
899 ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
900 break;
901 }
902 return size;
903 }
904