1/*
2* Copyright (c) 2015-2017, 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 <gralloc_priv.h>
31
32#include <core/buffer_allocator.h>
33#include <utils/constants.h>
34#include <utils/debug.h>
35
36#include "hwc_buffer_allocator.h"
37#include "hwc_debugger.h"
38
39#define __CLASS__ "HWCBufferAllocator"
40namespace sdm {
41
42HWCBufferAllocator::HWCBufferAllocator() {
43  int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module_);
44  if (err != 0) {
45    DLOGE("FATAL: can not open GRALLOC module");
46  } else {
47    gralloc1_open(module_, &gralloc_device_);
48  }
49  ReleaseBuffer_ = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
50      gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_RELEASE));
51  Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
52      gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
53}
54
55HWCBufferAllocator::~HWCBufferAllocator() {
56  if (gralloc_device_ != nullptr) {
57    gralloc1_close(gralloc_device_);
58  }
59}
60
61DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
62  const BufferConfig &buffer_config = buffer_info->buffer_config;
63  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
64  uint32_t width = buffer_config.width;
65  uint32_t height = buffer_config.height;
66  int format;
67  int alloc_flags = 0;
68  int error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
69  if (error != 0) {
70    return kErrorParameters;
71  }
72
73  if (buffer_config.secure) {
74    alloc_flags |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
75  }
76
77  if (!buffer_config.cache) {
78    // Allocate uncached buffers
79    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
80  }
81
82  if (buffer_config.gfx_client) {
83    alloc_flags |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
84  }
85
86  uint64_t producer_usage = UINT64(alloc_flags);
87  uint64_t consumer_usage = UINT64(alloc_flags);
88
89  // CreateBuffer
90  private_handle_t *hnd = nullptr;
91  Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER, width, height, format,
92           producer_usage, consumer_usage, &hnd);
93
94  if (hnd) {
95    alloc_buffer_info->fd = hnd->fd;
96    alloc_buffer_info->stride = UINT32(hnd->width);
97    alloc_buffer_info->size = hnd->size;
98  } else {
99    DLOGE("Failed to allocate memory");
100    return kErrorMemory;
101  }
102
103  buffer_info->private_data = reinterpret_cast<void *>(hnd);
104  return kErrorNone;
105}
106
107DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
108  DisplayError err = kErrorNone;
109  buffer_handle_t hnd = static_cast<private_handle_t *>(buffer_info->private_data);
110  ReleaseBuffer_(gralloc_device_, hnd);
111  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
112  alloc_buffer_info->fd = -1;
113  alloc_buffer_info->stride = 0;
114  alloc_buffer_info->size = 0;
115  buffer_info->private_data = NULL;
116  return err;
117}
118
119void HWCBufferAllocator::GetCustomWidthAndHeight(const private_handle_t *handle, int *width,
120                                                 int *height) {
121  Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE, handle,
122           width, height);
123}
124
125void HWCBufferAllocator::GetAlignedWidthAndHeight(int width, int height, int format,
126                                                  uint32_t alloc_type, int *aligned_width,
127                                                  int *aligned_height) {
128  int tile_enabled;
129  gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
130  gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
131  if (alloc_type & GRALLOC_USAGE_HW_FB) {
132    consumer_usage = GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
133  }
134
135  Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES, width, height, format,
136           producer_usage, consumer_usage, aligned_width, aligned_height, &tile_enabled);
137}
138
139uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
140  const BufferConfig &buffer_config = buffer_info->buffer_config;
141  int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
142
143  int width = INT(buffer_config.width);
144  int height = INT(buffer_config.height);
145  int format;
146
147  if (buffer_config.secure) {
148    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
149  }
150
151  if (!buffer_config.cache) {
152    // Allocate uncached buffers
153    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
154  }
155
156  if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
157    return 0;
158  }
159
160  uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
161  uint64_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
162  uint64_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
163  // TODO(user): Currently both flags are treated similarly in gralloc
164  producer_usage = UINT64(alloc_flags);
165  consumer_usage = producer_usage;
166  Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS, width, height,
167           format, producer_usage, consumer_usage, &aligned_width, &aligned_height, &buffer_size);
168  return buffer_size;
169}
170
171int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int *flags) {
172  switch (format) {
173    case kFormatRGBA8888:
174      *target = HAL_PIXEL_FORMAT_RGBA_8888;
175      break;
176    case kFormatRGBX8888:
177      *target = HAL_PIXEL_FORMAT_RGBX_8888;
178      break;
179    case kFormatRGB888:
180      *target = HAL_PIXEL_FORMAT_RGB_888;
181      break;
182    case kFormatRGB565:
183      *target = HAL_PIXEL_FORMAT_RGB_565;
184      break;
185    case kFormatBGR565:
186      *target = HAL_PIXEL_FORMAT_BGR_565;
187      break;
188    case kFormatBGRA8888:
189      *target = HAL_PIXEL_FORMAT_BGRA_8888;
190      break;
191    case kFormatYCrCb420PlanarStride16:
192      *target = HAL_PIXEL_FORMAT_YV12;
193      break;
194    case kFormatYCrCb420SemiPlanar:
195      *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;
196      break;
197    case kFormatYCbCr420SemiPlanar:
198      *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;
199      break;
200    case kFormatYCbCr422H2V1Packed:
201      *target = HAL_PIXEL_FORMAT_YCbCr_422_I;
202      break;
203    case kFormatYCbCr422H2V1SemiPlanar:
204      *target = HAL_PIXEL_FORMAT_YCbCr_422_SP;
205      break;
206    case kFormatYCbCr420SemiPlanarVenus:
207      *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
208      break;
209    case kFormatYCrCb420SemiPlanarVenus:
210      *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;
211      break;
212    case kFormatYCbCr420SPVenusUbwc:
213      *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
214      break;
215    case kFormatRGBA5551:
216      *target = HAL_PIXEL_FORMAT_RGBA_5551;
217      break;
218    case kFormatRGBA4444:
219      *target = HAL_PIXEL_FORMAT_RGBA_4444;
220      break;
221    case kFormatRGBA1010102:
222      *target = HAL_PIXEL_FORMAT_RGBA_1010102;
223      break;
224    case kFormatARGB2101010:
225      *target = HAL_PIXEL_FORMAT_ARGB_2101010;
226      break;
227    case kFormatRGBX1010102:
228      *target = HAL_PIXEL_FORMAT_RGBX_1010102;
229      break;
230    case kFormatXRGB2101010:
231      *target = HAL_PIXEL_FORMAT_XRGB_2101010;
232      break;
233    case kFormatBGRA1010102:
234      *target = HAL_PIXEL_FORMAT_BGRA_1010102;
235      break;
236    case kFormatABGR2101010:
237      *target = HAL_PIXEL_FORMAT_ABGR_2101010;
238      break;
239    case kFormatBGRX1010102:
240      *target = HAL_PIXEL_FORMAT_BGRX_1010102;
241      break;
242    case kFormatXBGR2101010:
243      *target = HAL_PIXEL_FORMAT_XBGR_2101010;
244      break;
245    case kFormatYCbCr420P010:
246      *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;
247      break;
248    case kFormatYCbCr420TP10Ubwc:
249      *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
250      break;
251    case kFormatRGBA8888Ubwc:
252      *target = HAL_PIXEL_FORMAT_RGBA_8888;
253      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
254      break;
255    case kFormatRGBX8888Ubwc:
256      *target = HAL_PIXEL_FORMAT_RGBX_8888;
257      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
258      break;
259    case kFormatBGR565Ubwc:
260      *target = HAL_PIXEL_FORMAT_BGR_565;
261      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
262      break;
263    case kFormatRGBA1010102Ubwc:
264      *target = HAL_PIXEL_FORMAT_RGBA_1010102;
265      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
266      break;
267    case kFormatRGBX1010102Ubwc:
268      *target = HAL_PIXEL_FORMAT_RGBX_1010102;
269      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
270      break;
271    default:
272      DLOGE("Unsupported format = 0x%x", format);
273      return -EINVAL;
274  }
275  return 0;
276}
277
278DisplayError HWCBufferAllocator::GetAllocatedBufferInfo(
279    const BufferConfig &buffer_config, AllocatedBufferInfo *allocated_buffer_info) {
280  // TODO(user): This API should pass the buffer_info of the already allocated buffer
281  // The private_data can then be typecast to the private_handle and used directly.
282  int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
283
284  int width = INT(buffer_config.width);
285  int height = INT(buffer_config.height);
286  int format;
287
288  if (buffer_config.secure) {
289    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
290  }
291
292  if (!buffer_config.cache) {
293    // Allocate uncached buffers
294    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
295  }
296
297  if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
298    return kErrorParameters;
299  }
300
301  uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
302  uint64_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
303  uint64_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
304  // TODO(user): Currently both flags are treated similarly in gralloc
305  producer_usage = UINT64(alloc_flags);
306  consumer_usage = producer_usage;
307  Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS, width, height,
308           format, producer_usage, consumer_usage, &aligned_width, &aligned_height, &buffer_size);
309  allocated_buffer_info->stride = UINT32(aligned_width);
310  allocated_buffer_info->aligned_width = UINT32(aligned_width);
311  allocated_buffer_info->aligned_height = UINT32(aligned_height);
312  allocated_buffer_info->size = UINT32(buffer_size);
313
314  return kErrorNone;
315}
316
317}  // namespace sdm
318