external/gbm_gralloc
Revision | 9a78d4f87eafcb1ab950ab3b4a07f45f10bbc16e (tree) |
---|---|
Time | 2019-01-02 11:43:54 |
Author | Mauro Rossi <issor.oruam@gmai...> |
Commiter | Chih-Wei Huang |
android: add gralloctest
gralloctest executable is added for Android based on minigbm/cros_gralloc commits:
b57dffc ("minigbm: move gralloctest to this repo")
2eeaf5a ("minigbm: cros_gralloc: fix -Wimplicit-function-declaration warnings in gralloctest")
Signed-off-by: Mauro Rossi <issor.oruam@gmail.com>
@@ -41,3 +41,4 @@ LOCAL_MODULE_RELATIVE_PATH := hw | ||
41 | 41 | LOCAL_PROPRIETARY_MODULE := true |
42 | 42 | |
43 | 43 | include $(BUILD_SHARED_LIBRARY) |
44 | +include $(LOCAL_PATH)/tests/Android.mk |
@@ -0,0 +1,36 @@ | ||
1 | +# Copyright 2016 The Chromium OS Authors | |
2 | +# Copyright 2018 Mauro Rossi <issor.oruam@gmailc.com> | |
3 | +# | |
4 | +# Permission is hereby granted, free of charge, to any person obtaining a | |
5 | +# copy of this software and associated documentation files (the "Software"), | |
6 | +# to deal in the Software without restriction, including without limitation | |
7 | +# the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | +# and/or sell copies of the Software, and to permit persons to whom the | |
9 | +# Software is furnished to do so, subject to the following conditions: | |
10 | +# | |
11 | +# The above copyright notice and this permission notice shall be included | |
12 | +# in all copies or substantial portions of the Software. | |
13 | +# | |
14 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
19 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
20 | +# DEALINGS IN THE SOFTWARE. | |
21 | + | |
22 | +LOCAL_PATH := $(call my-dir) | |
23 | + | |
24 | +include $(CLEAR_VARS) | |
25 | +include $(LOCAL_PATH)/Makefile.sources | |
26 | + | |
27 | +LOCAL_SRC_FILES := $(GRALLOCTEST_FILES) | |
28 | + | |
29 | +LOCAL_MODULE := gralloctest | |
30 | + | |
31 | +LOCAL_SHARED_LIBRARIES := \ | |
32 | + libhardware \ | |
33 | + libsync \ | |
34 | + libcutils | |
35 | + | |
36 | +include $(BUILD_EXECUTABLE) |
@@ -0,0 +1,30 @@ | ||
1 | +# Copyright 2016 The Chromium OS Authors. All rights reserved. | |
2 | +# Use of this source code is governed by a BSD-style license that can be | |
3 | +# found in the LICENSE file. | |
4 | + | |
5 | +GRALLOCTEST = gralloctest | |
6 | +SOURCES += gralloctest.c | |
7 | + | |
8 | +CCFLAGS += -g -O2 -Wall -fPIE | |
9 | +LIBS += -lhardware -lsync -lcutils -pie | |
10 | + | |
11 | +OBJS = $(foreach source, $(SOURCES), $(addsuffix .o, $(basename $(source)))) | |
12 | + | |
13 | +OBJECTS = $(addprefix $(TARGET_DIR), $(notdir $(OBJS))) | |
14 | +BINARY = $(addprefix $(TARGET_DIR), $(GRALLOCTEST)) | |
15 | + | |
16 | +.PHONY: all clean | |
17 | + | |
18 | +all: $(BINARY) | |
19 | + | |
20 | +$(BINARY): $(OBJECTS) | |
21 | + | |
22 | +clean: | |
23 | + $(RM) $(BINARY) | |
24 | + $(RM) $(OBJECTS) | |
25 | + | |
26 | +$(BINARY): | |
27 | + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) | |
28 | + | |
29 | +$(TARGET_DIR)%.o: %.c | |
30 | + $(CC) $(CFLAGS) -c $^ -o $@ -MMD |
@@ -0,0 +1,2 @@ | ||
1 | +GRALLOCTEST_FILES := \ | |
2 | + gralloctest.c |
@@ -0,0 +1,705 @@ | ||
1 | +/* | |
2 | + * Copyright 2016 The Chromium OS Authors. All rights reserved. | |
3 | + * Use of this source code is governed by a BSD-style license that can be | |
4 | + * found in the LICENSE file. | |
5 | + */ | |
6 | + | |
7 | +/* | |
8 | + * Please run clang-format on this file after making changes: | |
9 | + * | |
10 | + * clang-format -style=file -i gralloctest.c | |
11 | + * | |
12 | + */ | |
13 | + | |
14 | +#define _GNU_SOURCE | |
15 | +#include <stdio.h> | |
16 | +#include <stdlib.h> | |
17 | +#include <string.h> | |
18 | +#include <unistd.h> | |
19 | + | |
20 | +#include <cutils/native_handle.h> | |
21 | +#include <hardware/gralloc.h> | |
22 | +#include <sync/sync.h> | |
23 | +#include <system/graphics.h> | |
24 | + | |
25 | +#define ALIGN(A, B) (((A) + (B)-1) / (B) * (B)) | |
26 | +#define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A))) | |
27 | + | |
28 | +#define CHECK(cond) \ | |
29 | + do { \ | |
30 | + if (!(cond)) { \ | |
31 | + fprintf(stderr, "[ FAILED ] check in %s() %s:%d\n", __func__, __FILE__, \ | |
32 | + __LINE__); \ | |
33 | + return 0; \ | |
34 | + } \ | |
35 | + } while (0) | |
36 | + | |
37 | +#define CHECK_NO_MSG(cond) \ | |
38 | + do { \ | |
39 | + if (!(cond)) { \ | |
40 | + return 0; \ | |
41 | + } \ | |
42 | + } while (0) | |
43 | + | |
44 | +/* Private API enumeration -- see <gralloc_drm.h> */ | |
45 | +enum { GRALLOC_DRM_GET_STRIDE, | |
46 | + GRALLOC_DRM_GET_FORMAT, | |
47 | + GRALLOC_DRM_GET_DIMENSIONS, | |
48 | + GRALLOC_DRM_GET_BACKING_STORE, | |
49 | +}; | |
50 | + | |
51 | +struct gralloctest_context { | |
52 | + struct gralloc_module_t *module; | |
53 | + struct alloc_device_t *device; | |
54 | + int api; | |
55 | +}; | |
56 | + | |
57 | +struct gralloc_testcase { | |
58 | + const char *name; | |
59 | + int (*run_test)(struct gralloctest_context *ctx); | |
60 | + int required_api; | |
61 | +}; | |
62 | + | |
63 | +struct combinations { | |
64 | + int32_t format; | |
65 | + int32_t usage; | |
66 | +}; | |
67 | + | |
68 | +// clang-format off | |
69 | +static struct combinations combos[] = { | |
70 | + { HAL_PIXEL_FORMAT_RGBA_8888, | |
71 | + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | | |
72 | + GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | | |
73 | + GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_CURSOR }, | |
74 | + { HAL_PIXEL_FORMAT_RGBA_8888, | |
75 | + GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | | |
76 | + GRALLOC_USAGE_HW_COMPOSER }, | |
77 | + { HAL_PIXEL_FORMAT_RGBX_8888, | |
78 | + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN }, | |
79 | + { HAL_PIXEL_FORMAT_YCbCr_420_888, | |
80 | + GRALLOC_USAGE_EXTERNAL_DISP | GRALLOC_USAGE_HW_COMPOSER | | |
81 | + GRALLOC_USAGE_HW_TEXTURE }, | |
82 | + { HAL_PIXEL_FORMAT_YCbCr_420_888, | |
83 | + GRALLOC_USAGE_RENDERSCRIPT | GRALLOC_USAGE_SW_READ_OFTEN | | |
84 | + GRALLOC_USAGE_SW_WRITE_OFTEN }, | |
85 | + { HAL_PIXEL_FORMAT_YV12, | |
86 | + GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_COMPOSER | | |
87 | + GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP }, | |
88 | + { HAL_PIXEL_FORMAT_RGB_565, | |
89 | + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN }, | |
90 | + { HAL_PIXEL_FORMAT_BGRA_8888, | |
91 | + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN }, | |
92 | + { HAL_PIXEL_FORMAT_BLOB, | |
93 | + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN }, | |
94 | +}; | |
95 | +// clang-format on | |
96 | + | |
97 | +struct grallocinfo { | |
98 | + buffer_handle_t handle; /* handle to the buffer */ | |
99 | + int w; /* width of buffer */ | |
100 | + int h; /* height of buffer */ | |
101 | + int format; /* format of the buffer */ | |
102 | + int usage; /* bitfield indicating usage */ | |
103 | + int fence_fd; /* fence file descriptor */ | |
104 | + void *vaddr; /* buffer virtual memory address */ | |
105 | + int stride; /* stride in pixels */ | |
106 | + struct android_ycbcr ycbcr; /* sw access for yuv buffers */ | |
107 | +}; | |
108 | + | |
109 | +/* This function is meant to initialize the test to commonly used defaults. */ | |
110 | +void grallocinfo_init(struct grallocinfo *info, int w, int h, int format, int usage) | |
111 | +{ | |
112 | + info->w = w; | |
113 | + info->h = h; | |
114 | + info->format = format; | |
115 | + info->usage = usage; | |
116 | + info->fence_fd = -1; | |
117 | + info->vaddr = NULL; | |
118 | + info->ycbcr.y = NULL; | |
119 | + info->ycbcr.cb = NULL; | |
120 | + info->ycbcr.cr = NULL; | |
121 | + info->stride = 0; | |
122 | +} | |
123 | + | |
124 | +static native_handle_t *duplicate_buffer_handle(buffer_handle_t handle) | |
125 | +{ | |
126 | + native_handle_t *hnd = native_handle_create(handle->numFds, handle->numInts); | |
127 | + | |
128 | + if (hnd == NULL) | |
129 | + return NULL; | |
130 | + | |
131 | + const int *old_data = handle->data; | |
132 | + int *new_data = hnd->data; | |
133 | + | |
134 | + int i; | |
135 | + for (i = 0; i < handle->numFds; i++) { | |
136 | + *new_data = dup(*old_data); | |
137 | + old_data++; | |
138 | + new_data++; | |
139 | + } | |
140 | + | |
141 | + memcpy(new_data, old_data, sizeof(int) * handle->numInts); | |
142 | + | |
143 | + return hnd; | |
144 | +} | |
145 | + | |
146 | +/**************************************************************** | |
147 | + * Wrappers around gralloc_module_t and alloc_device_t functions. | |
148 | + * GraphicBufferMapper/GraphicBufferAllocator could replace this | |
149 | + * in theory. | |
150 | + ***************************************************************/ | |
151 | + | |
152 | +static int allocate(struct alloc_device_t *device, struct grallocinfo *info) | |
153 | +{ | |
154 | + int ret; | |
155 | + | |
156 | + ret = device->alloc(device, info->w, info->h, info->format, info->usage, &info->handle, | |
157 | + &info->stride); | |
158 | + | |
159 | + CHECK_NO_MSG(ret == 0); | |
160 | + CHECK_NO_MSG(info->handle->version > 0); | |
161 | + CHECK_NO_MSG(info->handle->numInts >= 0); | |
162 | + CHECK_NO_MSG(info->handle->numFds >= 0); | |
163 | + CHECK_NO_MSG(info->stride >= 0); | |
164 | + | |
165 | + return 1; | |
166 | +} | |
167 | + | |
168 | +static int deallocate(struct alloc_device_t *device, struct grallocinfo *info) | |
169 | +{ | |
170 | + int ret; | |
171 | + ret = device->free(device, info->handle); | |
172 | + CHECK(ret == 0); | |
173 | + return 1; | |
174 | +} | |
175 | + | |
176 | +static int register_buffer(struct gralloc_module_t *module, struct grallocinfo *info) | |
177 | +{ | |
178 | + int ret; | |
179 | + ret = module->registerBuffer(module, info->handle); | |
180 | + return (ret == 0); | |
181 | +} | |
182 | + | |
183 | +static int unregister_buffer(struct gralloc_module_t *module, struct grallocinfo *info) | |
184 | +{ | |
185 | + int ret; | |
186 | + ret = module->unregisterBuffer(module, info->handle); | |
187 | + return (ret == 0); | |
188 | +} | |
189 | + | |
190 | +static int lock(struct gralloc_module_t *module, struct grallocinfo *info) | |
191 | +{ | |
192 | + int ret; | |
193 | + | |
194 | + ret = module->lock(module, info->handle, info->usage, 0, 0, (info->w) / 2, (info->h) / 2, | |
195 | + &info->vaddr); | |
196 | + | |
197 | + return (ret == 0); | |
198 | +} | |
199 | + | |
200 | +static int unlock(struct gralloc_module_t *module, struct grallocinfo *info) | |
201 | +{ | |
202 | + int ret; | |
203 | + ret = module->unlock(module, info->handle); | |
204 | + return (ret == 0); | |
205 | +} | |
206 | + | |
207 | +static int lock_ycbcr(struct gralloc_module_t *module, struct grallocinfo *info) | |
208 | +{ | |
209 | + int ret; | |
210 | + | |
211 | + ret = module->lock_ycbcr(module, info->handle, info->usage, 0, 0, (info->w) / 2, | |
212 | + (info->h) / 2, &info->ycbcr); | |
213 | + | |
214 | + return (ret == 0); | |
215 | +} | |
216 | + | |
217 | +static int lock_async(struct gralloc_module_t *module, struct grallocinfo *info) | |
218 | +{ | |
219 | + int ret; | |
220 | + | |
221 | + ret = module->lockAsync(module, info->handle, info->usage, 0, 0, (info->w) / 2, | |
222 | + (info->h) / 2, &info->vaddr, info->fence_fd); | |
223 | + | |
224 | + return (ret == 0); | |
225 | +} | |
226 | + | |
227 | +static int unlock_async(struct gralloc_module_t *module, struct grallocinfo *info) | |
228 | +{ | |
229 | + int ret; | |
230 | + | |
231 | + ret = module->unlockAsync(module, info->handle, &info->fence_fd); | |
232 | + | |
233 | + return (ret == 0); | |
234 | +} | |
235 | + | |
236 | +static int lock_async_ycbcr(struct gralloc_module_t *module, struct grallocinfo *info) | |
237 | +{ | |
238 | + int ret; | |
239 | + | |
240 | + ret = module->lockAsync_ycbcr(module, info->handle, info->usage, 0, 0, (info->w) / 2, | |
241 | + (info->h) / 2, &info->ycbcr, info->fence_fd); | |
242 | + | |
243 | + return (ret == 0); | |
244 | +} | |
245 | + | |
246 | +/************************************************************** | |
247 | + * END WRAPPERS * | |
248 | + **************************************************************/ | |
249 | + | |
250 | +/* This function tests initialization of gralloc module and allocator. */ | |
251 | +static struct gralloctest_context *test_init_gralloc() | |
252 | +{ | |
253 | + int err; | |
254 | + hw_module_t const *hw_module; | |
255 | + struct gralloctest_context *ctx = calloc(1, sizeof(*ctx)); | |
256 | + | |
257 | + err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &hw_module); | |
258 | + if (err) | |
259 | + return NULL; | |
260 | + | |
261 | + gralloc_open(hw_module, &ctx->device); | |
262 | + ctx->module = (gralloc_module_t *)hw_module; | |
263 | + if (!ctx->module || !ctx->device) | |
264 | + return NULL; | |
265 | + | |
266 | + switch (ctx->module->common.module_api_version) { | |
267 | + case GRALLOC_MODULE_API_VERSION_0_3: | |
268 | + ctx->api = 3; | |
269 | + break; | |
270 | + case GRALLOC_MODULE_API_VERSION_0_2: | |
271 | + ctx->api = 2; | |
272 | + break; | |
273 | + default: | |
274 | + ctx->api = 1; | |
275 | + } | |
276 | + | |
277 | + return ctx; | |
278 | +} | |
279 | + | |
280 | +static int test_close_gralloc(struct gralloctest_context *ctx) | |
281 | +{ | |
282 | + CHECK(gralloc_close(ctx->device) == 0); | |
283 | + return 1; | |
284 | +} | |
285 | + | |
286 | +/* This function tests allocation with varying buffer dimensions. */ | |
287 | +static int test_alloc_varying_sizes(struct gralloctest_context *ctx) | |
288 | +{ | |
289 | + struct grallocinfo info; | |
290 | + int i; | |
291 | + | |
292 | + grallocinfo_init(&info, 0, 0, HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_SW_READ_OFTEN); | |
293 | + | |
294 | + for (i = 1; i < 1920; i++) { | |
295 | + info.w = i; | |
296 | + info.h = i; | |
297 | + CHECK(allocate(ctx->device, &info)); | |
298 | + CHECK(deallocate(ctx->device, &info)); | |
299 | + } | |
300 | + | |
301 | + info.w = 1; | |
302 | + for (i = 1; i < 1920; i++) { | |
303 | + info.h = i; | |
304 | + CHECK(allocate(ctx->device, &info)); | |
305 | + CHECK(deallocate(ctx->device, &info)); | |
306 | + } | |
307 | + | |
308 | + info.h = 1; | |
309 | + for (i = 1; i < 1920; i++) { | |
310 | + info.w = i; | |
311 | + CHECK(allocate(ctx->device, &info)); | |
312 | + CHECK(deallocate(ctx->device, &info)); | |
313 | + } | |
314 | + | |
315 | + return 1; | |
316 | +} | |
317 | + | |
318 | +/* | |
319 | + * This function tests that we find at least one working format for each | |
320 | + * combos which we consider important. | |
321 | + */ | |
322 | +static int test_alloc_combinations(struct gralloctest_context *ctx) | |
323 | +{ | |
324 | + int i; | |
325 | + | |
326 | + struct grallocinfo info; | |
327 | + grallocinfo_init(&info, 512, 512, 0, 0); | |
328 | + | |
329 | + for (i = 0; i < ARRAY_SIZE(combos); i++) { | |
330 | + info.format = combos[i].format; | |
331 | + info.usage = combos[i].usage; | |
332 | + CHECK(allocate(ctx->device, &info)); | |
333 | + CHECK(deallocate(ctx->device, &info)); | |
334 | + } | |
335 | + | |
336 | + return 1; | |
337 | +} | |
338 | + | |
339 | +/* | |
340 | + * This function tests the advertised API version. | |
341 | + * Version_0_2 added (*lock_ycbcr)() method. | |
342 | + * Version_0_3 added fence passing to/from lock/unlock. | |
343 | + */ | |
344 | +static int test_api(struct gralloctest_context *ctx) | |
345 | +{ | |
346 | + | |
347 | + CHECK(ctx->module->registerBuffer); | |
348 | + CHECK(ctx->module->unregisterBuffer); | |
349 | + CHECK(ctx->module->lock); | |
350 | + CHECK(ctx->module->unlock); | |
351 | + | |
352 | + switch (ctx->module->common.module_api_version) { | |
353 | + case GRALLOC_MODULE_API_VERSION_0_3: | |
354 | + CHECK(ctx->module->lock_ycbcr); | |
355 | + CHECK(ctx->module->lockAsync); | |
356 | + CHECK(ctx->module->unlockAsync); | |
357 | + CHECK(ctx->module->lockAsync_ycbcr); | |
358 | + break; | |
359 | + case GRALLOC_MODULE_API_VERSION_0_2: | |
360 | + CHECK(ctx->module->lock_ycbcr); | |
361 | + CHECK(ctx->module->lockAsync == NULL); | |
362 | + CHECK(ctx->module->unlockAsync == NULL); | |
363 | + CHECK(ctx->module->lockAsync_ycbcr == NULL); | |
364 | + break; | |
365 | + case GRALLOC_MODULE_API_VERSION_0_1: | |
366 | + CHECK(ctx->module->lockAsync == NULL); | |
367 | + CHECK(ctx->module->unlockAsync == NULL); | |
368 | + CHECK(ctx->module->lockAsync_ycbcr == NULL); | |
369 | + CHECK(ctx->module->lock_ycbcr == NULL); | |
370 | + break; | |
371 | + default: | |
372 | + return 0; | |
373 | + } | |
374 | + | |
375 | + return 1; | |
376 | +} | |
377 | + | |
378 | +/* | |
379 | + * This function registers, unregisters, locks and unlocks the buffer in | |
380 | + * various orders. | |
381 | + */ | |
382 | +static int test_gralloc_order(struct gralloctest_context *ctx) | |
383 | +{ | |
384 | + struct grallocinfo info, duplicate; | |
385 | + | |
386 | + grallocinfo_init(&info, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_SW_READ_OFTEN); | |
387 | + | |
388 | + grallocinfo_init(&duplicate, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888, | |
389 | + GRALLOC_USAGE_SW_READ_OFTEN); | |
390 | + | |
391 | + CHECK(allocate(ctx->device, &info)); | |
392 | + | |
393 | + /* | |
394 | + * Duplicate the buffer handle to simulate an additional reference | |
395 | + * in same process. | |
396 | + */ | |
397 | + native_handle_t *native_handle = duplicate_buffer_handle(info.handle); | |
398 | + duplicate.handle = native_handle; | |
399 | + | |
400 | + CHECK(unregister_buffer(ctx->module, &duplicate) == 0); | |
401 | + CHECK(register_buffer(ctx->module, &duplicate)); | |
402 | + | |
403 | + CHECK(unlock(ctx->module, &duplicate) == 0); | |
404 | + | |
405 | + CHECK(lock(ctx->module, &duplicate)); | |
406 | + CHECK(duplicate.vaddr); | |
407 | + CHECK(unlock(ctx->module, &duplicate)); | |
408 | + | |
409 | + CHECK(unregister_buffer(ctx->module, &duplicate)); | |
410 | + | |
411 | + CHECK(register_buffer(ctx->module, &duplicate)); | |
412 | + CHECK(unregister_buffer(ctx->module, &duplicate)); | |
413 | + CHECK(unregister_buffer(ctx->module, &duplicate) == 0); | |
414 | + | |
415 | + CHECK(register_buffer(ctx->module, &duplicate)); | |
416 | + CHECK(deallocate(ctx->device, &info)); | |
417 | + | |
418 | + CHECK(lock(ctx->module, &duplicate)); | |
419 | + CHECK(lock(ctx->module, &duplicate)); | |
420 | + CHECK(unlock(ctx->module, &duplicate)); | |
421 | + CHECK(unlock(ctx->module, &duplicate)); | |
422 | + CHECK(unlock(ctx->module, &duplicate) == 0); | |
423 | + CHECK(unregister_buffer(ctx->module, &duplicate)); | |
424 | + | |
425 | + CHECK(native_handle_close(duplicate.handle) == 0); | |
426 | + CHECK(native_handle_delete(native_handle) == 0); | |
427 | + | |
428 | + return 1; | |
429 | +} | |
430 | + | |
431 | +/* This function tests CPU reads and writes. */ | |
432 | +static int test_mapping(struct gralloctest_context *ctx) | |
433 | +{ | |
434 | + struct grallocinfo info; | |
435 | + uint32_t *ptr = NULL; | |
436 | + uint32_t magic_number = 0x000ABBA; | |
437 | + | |
438 | + grallocinfo_init(&info, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888, | |
439 | + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); | |
440 | + | |
441 | + CHECK(allocate(ctx->device, &info)); | |
442 | + CHECK(lock(ctx->module, &info)); | |
443 | + | |
444 | + ptr = (uint32_t *)info.vaddr; | |
445 | + CHECK(ptr); | |
446 | + ptr[(info.w) / 2] = magic_number; | |
447 | + | |
448 | + CHECK(unlock(ctx->module, &info)); | |
449 | + info.vaddr = NULL; | |
450 | + ptr = NULL; | |
451 | + | |
452 | + CHECK(lock(ctx->module, &info)); | |
453 | + ptr = (uint32_t *)info.vaddr; | |
454 | + CHECK(ptr); | |
455 | + CHECK(ptr[info.w / 2] == magic_number); | |
456 | + | |
457 | + CHECK(unlock(ctx->module, &info)); | |
458 | + CHECK(deallocate(ctx->device, &info)); | |
459 | + | |
460 | + return 1; | |
461 | +} | |
462 | + | |
463 | +/* This function tests the private API we use in ARC++ -- not part of official | |
464 | + * gralloc. */ | |
465 | +static int test_perform(struct gralloctest_context *ctx) | |
466 | +{ | |
467 | + int32_t format; | |
468 | + uint64_t id1, id2; | |
469 | + uint32_t stride, width, height; | |
470 | + struct grallocinfo info, duplicate; | |
471 | + struct gralloc_module_t *mod = ctx->module; | |
472 | + | |
473 | + grallocinfo_init(&info, 650, 408, HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_SW_READ_OFTEN); | |
474 | + | |
475 | + CHECK(allocate(ctx->device, &info)); | |
476 | + | |
477 | + CHECK(mod->perform(mod, GRALLOC_DRM_GET_STRIDE, info.handle, &stride) == 0); | |
478 | + CHECK(stride == info.stride); | |
479 | + | |
480 | + CHECK(mod->perform(mod, GRALLOC_DRM_GET_FORMAT, info.handle, &format) == 0); | |
481 | + CHECK(format == info.format); | |
482 | + | |
483 | + CHECK(mod->perform(mod, GRALLOC_DRM_GET_DIMENSIONS, info.handle, &width, &height) == 0); | |
484 | + CHECK(width == info.w); | |
485 | + CHECK(height == info.h); | |
486 | + | |
487 | + native_handle_t *native_handle = duplicate_buffer_handle(info.handle); | |
488 | + duplicate.handle = native_handle; | |
489 | + | |
490 | + CHECK(mod->perform(mod, GRALLOC_DRM_GET_BACKING_STORE, duplicate.handle, &id2)); | |
491 | + CHECK(register_buffer(mod, &duplicate)); | |
492 | + | |
493 | + CHECK(mod->perform(mod, GRALLOC_DRM_GET_BACKING_STORE, info.handle, &id1) == 0); | |
494 | + CHECK(mod->perform(mod, GRALLOC_DRM_GET_BACKING_STORE, duplicate.handle, &id2) == 0); | |
495 | + CHECK(id1 == id2); | |
496 | + | |
497 | + CHECK(unregister_buffer(mod, &duplicate)); | |
498 | + CHECK(deallocate(ctx->device, &info)); | |
499 | + | |
500 | + return 1; | |
501 | +} | |
502 | + | |
503 | +/* This function tests that only YUV buffers work with *lock_ycbcr. */ | |
504 | +static int test_ycbcr(struct gralloctest_context *ctx) | |
505 | + | |
506 | +{ | |
507 | + struct grallocinfo info; | |
508 | + grallocinfo_init(&info, 512, 512, HAL_PIXEL_FORMAT_YCbCr_420_888, | |
509 | + GRALLOC_USAGE_SW_READ_OFTEN); | |
510 | + | |
511 | + CHECK(allocate(ctx->device, &info)); | |
512 | + | |
513 | + CHECK(lock(ctx->module, &info) == 0); | |
514 | + CHECK(lock_ycbcr(ctx->module, &info)); | |
515 | + CHECK(info.ycbcr.y); | |
516 | + CHECK(info.ycbcr.cb); | |
517 | + CHECK(info.ycbcr.cr); | |
518 | + CHECK(unlock(ctx->module, &info)); | |
519 | + | |
520 | + CHECK(deallocate(ctx->device, &info)); | |
521 | + | |
522 | + info.format = HAL_PIXEL_FORMAT_BGRA_8888; | |
523 | + CHECK(allocate(ctx->device, &info)); | |
524 | + | |
525 | + CHECK(lock_ycbcr(ctx->module, &info) == 0); | |
526 | + CHECK(lock(ctx->module, &info)); | |
527 | + CHECK(unlock(ctx->module, &info)); | |
528 | + | |
529 | + CHECK(deallocate(ctx->device, &info)); | |
530 | + | |
531 | + return 1; | |
532 | +} | |
533 | + | |
534 | +/* | |
535 | + * This function tests a method ARC++ uses to query YUV buffer | |
536 | + * info -- not part of official gralloc API. This is used in | |
537 | + * Mali, Mesa, the ArcCodec and wayland_service. | |
538 | + */ | |
539 | +static int test_yuv_info(struct gralloctest_context *ctx) | |
540 | +{ | |
541 | + struct grallocinfo info; | |
542 | + uintptr_t y_size, c_stride, c_size, cr_offset, cb_offset; | |
543 | + uint32_t width, height; | |
544 | + width = height = 512; | |
545 | + | |
546 | + /* <system/graphics.h> defines YV12 as having: | |
547 | + * - an even width | |
548 | + * - an even height | |
549 | + * - a horizontal stride multiple of 16 pixels | |
550 | + * - a vertical stride equal to the height | |
551 | + * | |
552 | + * y_size = stride * height. | |
553 | + * c_stride = ALIGN(stride/2, 16). | |
554 | + * c_size = c_stride * height/2. | |
555 | + * size = y_size + c_size * 2. | |
556 | + * cr_offset = y_size. | |
557 | + * cb_offset = y_size + c_size. | |
558 | + */ | |
559 | + | |
560 | + grallocinfo_init(&info, width, height, HAL_PIXEL_FORMAT_YV12, GRALLOC_USAGE_SW_READ_OFTEN); | |
561 | + | |
562 | + CHECK(allocate(ctx->device, &info)); | |
563 | + | |
564 | + y_size = info.stride * height; | |
565 | + c_stride = ALIGN(info.stride / 2, 16); | |
566 | + c_size = c_stride * height / 2; | |
567 | + cr_offset = y_size; | |
568 | + cb_offset = y_size + c_size; | |
569 | + | |
570 | + info.usage = 0; | |
571 | + | |
572 | + /* | |
573 | + * Check if the (*lock_ycbcr) with usage of zero returns the | |
574 | + * offsets and strides of the YV12 buffer. This is unofficial | |
575 | + * behavior we are testing here. | |
576 | + */ | |
577 | + CHECK(lock_ycbcr(ctx->module, &info)); | |
578 | + | |
579 | + CHECK(info.stride == info.ycbcr.ystride); | |
580 | + CHECK(c_stride == info.ycbcr.cstride); | |
581 | + CHECK(cr_offset == (uintptr_t)info.ycbcr.cr); | |
582 | + CHECK(cb_offset == (uintptr_t)info.ycbcr.cb); | |
583 | + | |
584 | + CHECK(unlock(ctx->module, &info)); | |
585 | + | |
586 | + CHECK(deallocate(ctx->device, &info)); | |
587 | + | |
588 | + return 1; | |
589 | +} | |
590 | + | |
591 | +/* This function tests asynchronous locking and unlocking of buffers. */ | |
592 | +static int test_async(struct gralloctest_context *ctx) | |
593 | + | |
594 | +{ | |
595 | + struct grallocinfo rgba_info, ycbcr_info; | |
596 | + grallocinfo_init(&rgba_info, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888, | |
597 | + GRALLOC_USAGE_SW_READ_OFTEN); | |
598 | + grallocinfo_init(&ycbcr_info, 512, 512, HAL_PIXEL_FORMAT_YCbCr_420_888, | |
599 | + GRALLOC_USAGE_SW_READ_OFTEN); | |
600 | + | |
601 | + CHECK(allocate(ctx->device, &rgba_info)); | |
602 | + CHECK(allocate(ctx->device, &ycbcr_info)); | |
603 | + | |
604 | + CHECK(lock_async(ctx->module, &rgba_info)); | |
605 | + CHECK(lock_async_ycbcr(ctx->module, &ycbcr_info)); | |
606 | + | |
607 | + CHECK(rgba_info.vaddr); | |
608 | + CHECK(ycbcr_info.ycbcr.y); | |
609 | + CHECK(ycbcr_info.ycbcr.cb); | |
610 | + CHECK(ycbcr_info.ycbcr.cr); | |
611 | + | |
612 | + /* | |
613 | + * Wait on the fence returned from unlock_async and check it doesn't | |
614 | + * return an error. | |
615 | + */ | |
616 | + CHECK(unlock_async(ctx->module, &rgba_info)); | |
617 | + CHECK(unlock_async(ctx->module, &ycbcr_info)); | |
618 | + | |
619 | + if (rgba_info.fence_fd >= 0) { | |
620 | + CHECK(sync_wait(rgba_info.fence_fd, 10000) >= 0); | |
621 | + CHECK(close(rgba_info.fence_fd) == 0); | |
622 | + } | |
623 | + | |
624 | + if (ycbcr_info.fence_fd >= 0) { | |
625 | + CHECK(sync_wait(ycbcr_info.fence_fd, 10000) >= 0); | |
626 | + CHECK(close(ycbcr_info.fence_fd) == 0); | |
627 | + } | |
628 | + | |
629 | + CHECK(deallocate(ctx->device, &rgba_info)); | |
630 | + CHECK(deallocate(ctx->device, &ycbcr_info)); | |
631 | + | |
632 | + return 1; | |
633 | +} | |
634 | + | |
635 | +static const struct gralloc_testcase tests[] = { | |
636 | + { "alloc_varying_sizes", test_alloc_varying_sizes, 1 }, | |
637 | + { "alloc_combinations", test_alloc_combinations, 1 }, | |
638 | + { "api", test_api, 1 }, | |
639 | + { "gralloc_order", test_gralloc_order, 1 }, | |
640 | + { "mapping", test_mapping, 1 }, | |
641 | + { "perform", test_perform, 1 }, | |
642 | + { "ycbcr", test_ycbcr, 2 }, | |
643 | + { "yuv_info", test_yuv_info, 2 }, | |
644 | + { "async", test_async, 3 }, | |
645 | +}; | |
646 | + | |
647 | +static void print_help(const char *argv0) | |
648 | +{ | |
649 | + uint32_t i; | |
650 | + printf("usage: %s <test_name>\n\n", argv0); | |
651 | + printf("A valid name test is one the following:\n"); | |
652 | + for (i = 0; i < ARRAY_SIZE(tests); i++) | |
653 | + printf("%s\n", tests[i].name); | |
654 | +} | |
655 | + | |
656 | +int main(int argc, char *argv[]) | |
657 | +{ | |
658 | + int ret = 0; | |
659 | + uint32_t num_run = 0; | |
660 | + | |
661 | + setbuf(stdout, NULL); | |
662 | + if (argc == 2) { | |
663 | + uint32_t i; | |
664 | + char *name = argv[1]; | |
665 | + | |
666 | + struct gralloctest_context *ctx = test_init_gralloc(); | |
667 | + if (!ctx) { | |
668 | + fprintf(stderr, "[ FAILED ] to initialize gralloc.\n"); | |
669 | + return 1; | |
670 | + } | |
671 | + | |
672 | + for (i = 0; i < ARRAY_SIZE(tests); i++) { | |
673 | + if (strcmp(tests[i].name, name) && strcmp("all", name)) | |
674 | + continue; | |
675 | + | |
676 | + int success = 1; | |
677 | + if (ctx->api >= tests[i].required_api) | |
678 | + success = tests[i].run_test(ctx); | |
679 | + | |
680 | + printf("[ RUN ] gralloctest.%s\n", tests[i].name); | |
681 | + if (!success) { | |
682 | + fprintf(stderr, "[ FAILED ] gralloctest.%s\n", tests[i].name); | |
683 | + ret |= 1; | |
684 | + } else { | |
685 | + printf("[ PASSED ] gralloctest.%s\n", tests[i].name); | |
686 | + } | |
687 | + | |
688 | + num_run++; | |
689 | + } | |
690 | + | |
691 | + if (!test_close_gralloc(ctx)) { | |
692 | + fprintf(stderr, "[ FAILED ] to close gralloc.\n"); | |
693 | + return 1; | |
694 | + } | |
695 | + | |
696 | + if (!num_run) | |
697 | + goto print_usage; | |
698 | + | |
699 | + return ret; | |
700 | + } | |
701 | + | |
702 | +print_usage: | |
703 | + print_help(argv[0]); | |
704 | + return 0; | |
705 | +} |