/* * Unit test: RGA composer - tests importbuffer_fd + wrapbuffer_handle_t * Since wrapbuffer_fd_t returns handle=0 on this platform, * we use importbuffer_fd to get a handle, then wrapbuffer_handle_t. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include static int dma_heap_alloc(const char *heap_name, size_t size, int *fd) { char path[64]; snprintf(path, sizeof(path), "/dev/dma_heap/%s", heap_name); int heap_fd = open(path, O_RDWR | O_CLOEXEC); if (heap_fd < 0) return -1; struct dma_heap_allocation_data data = { .len = size, .fd_flags = O_RDWR | O_CLOEXEC }; int ret = ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data); close(heap_fd); if (ret < 0) return -1; *fd = data.fd; return 0; } static rga_buffer_t make_rga_from_fd(int fd, int w, int h, int format) { rga_buffer_t buf; memset(&buf, 0, sizeof(buf)); /* Try wrapbuffer_fd_t first */ buf = wrapbuffer_fd_t(fd, w, h, w, h, format); if (buf.handle != 0) return buf; /* Fallback: importbuffer_fd + wrapbuffer_handle_t */ im_handle_param_t param; memset(¶m, 0, sizeof(param)); param.width = w; param.height = h; param.format = format; rga_buffer_handle_t handle = importbuffer_fd(fd, ¶m); if (handle == 0) { fprintf(stderr, " importbuffer_fd failed for fd=%d\n", fd); return buf; } buf = wrapbuffer_handle_t(handle, w, h, w, h, format); fprintf(stderr, " imported fd=%d => handle=%u (via importbuffer_fd)\n", fd, handle); return buf; } static void test_blit(const char *heap_name, int src_w, int src_h, int dst_w, int dst_h) { printf("=== RGA blit: %s, src=%dx%d, dst=%dx%d ===\n", heap_name, src_w, src_h, dst_w, dst_h); size_t src_sz = src_w * src_h * 3 / 2; size_t dst_sz = dst_w * dst_h * 3 / 2; int src_fd = -1, dst_fd = -1; if (dma_heap_alloc(heap_name, src_sz, &src_fd) < 0) { printf(" FAIL: src alloc\n\n"); return; } if (dma_heap_alloc(heap_name, dst_sz, &dst_fd) < 0) { printf(" FAIL: dst alloc\n"); close(src_fd); return; } void *src_map = mmap(NULL, src_sz, PROT_READ | PROT_WRITE, MAP_SHARED, src_fd, 0); void *dst_map = mmap(NULL, dst_sz, PROT_READ | PROT_WRITE, MAP_SHARED, dst_fd, 0); if (src_map == MAP_FAILED || dst_map == MAP_FAILED) { printf(" FAIL: mmap\n"); close(src_fd); close(dst_fd); return; } /* Fill src with yellow (Y=0xFF, UV=0x40) */ memset(src_map, 0xFF, src_w * src_h); memset((uint8_t*)src_map + src_w * src_h, 0x40, src_w * src_h / 2); memset(dst_map, 0x00, dst_sz); rga_buffer_t src_buf = make_rga_from_fd(src_fd, src_w, src_h, RK_FORMAT_YCbCr_420_SP); rga_buffer_t dst_buf = make_rga_from_fd(dst_fd, dst_w, dst_h, RK_FORMAT_YCbCr_420_SP); printf(" src: handle=%u\n", src_buf.handle); printf(" dst: handle=%u\n", dst_buf.handle); if (src_buf.handle == 0 || dst_buf.handle == 0) { printf(" SKIP blit (handle=0)\n"); goto cleanup; } im_rect src_rect = {0, 0, src_w, src_h}; im_rect dst_rect = {0, 0, dst_w, dst_h}; rga_buffer_t pat; memset(&pat, 0, sizeof(pat)); im_rect prect; memset(&prect, 0, sizeof(prect)); printf(" Running improcess...\n"); int ret = improcess(src_buf, dst_buf, pat, src_rect, dst_rect, prect, IM_SYNC); printf(" improcess => %d (%s)\n", ret, ret == IM_STATUS_SUCCESS ? "OK" : "FAIL"); if (ret == IM_STATUS_SUCCESS) { uint8_t *p = (uint8_t*)dst_map; int nonzero = 0; for (int i = 0; i < dst_w * dst_h && i < 1024; i++) if (p[i] != 0) nonzero++; printf(" dst Y first 1024 bytes: %d non-zero (expect ~1024 for 0xFF fill)\n", nonzero); } cleanup: munmap(src_map, src_sz); munmap(dst_map, dst_sz); close(src_fd); close(dst_fd); printf("\n"); } int main(void) { printf("=== RGA Composer Unit Test v2 ===\n\n"); test_blit("system-uncached", 1920, 1080, 1920, 1080); test_blit("system-uncached", 640, 360, 640, 360); test_blit("system-uncached", 1920, 1080, 640, 360); /* scale down */ test_blit("cma", 1920, 1080, 1920, 1080); printf("=== Done ===\n"); return 0; }