/* * Unit test: RGA NV12->RGBX color conversion * Tests the specific conversion that display.c needs. */ #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 import_rga_buf(int fd, int w, int h, int stride_w, int stride_h, int format) { 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 w=%d h=%d fmt=%d\n", fd, w, h, format); rga_buffer_t empty; memset(&empty, 0, sizeof(empty)); return empty; } return wrapbuffer_handle_t(handle, w, h, stride_w, stride_h, format); } static void test_nv12_to_rgbx(const char *heap, int w, int h, int rgbx_rga_fmt, int rgbx_pixel_stride, int rgbx_byte_stride) { printf("=== NV12->RGBX test: heap=%s %dx%d, rgbx_fmt=%d, pixel_stride=%d, byte_stride=%d ===\n", heap, w, h, rgbx_rga_fmt, rgbx_pixel_stride, rgbx_byte_stride); size_t nv12_sz = (size_t)w * h * 3 / 2; size_t rgbx_sz = (size_t)rgbx_byte_stride * h; int nv12_fd = -1, rgbx_fd = -1; if (dma_heap_alloc(heap, nv12_sz, &nv12_fd) < 0) { printf(" FAIL: nv12 alloc\n\n"); return; } if (dma_heap_alloc(heap, rgbx_sz, &rgbx_fd) < 0) { printf(" FAIL: rgbx alloc\n"); close(nv12_fd); return; } void *nv12_map = mmap(NULL, nv12_sz, PROT_READ | PROT_WRITE, MAP_SHARED, nv12_fd, 0); void *rgbx_map = mmap(NULL, rgbx_sz, PROT_READ | PROT_WRITE, MAP_SHARED, rgbx_fd, 0); if (nv12_map == MAP_FAILED || rgbx_map == MAP_FAILED) { printf(" FAIL: mmap\n"); close(nv12_fd); close(rgbx_fd); return; } /* Fill NV12 with white (Y=0xFF, UV=0x80) */ memset(nv12_map, 0xFF, w * h); memset((uint8_t*)nv12_map + w * h, 0x80, w * h / 2); memset(rgbx_map, 0x00, rgbx_sz); /* Test 1: wrapbuffer_fd_t */ printf(" Test 1: wrapbuffer_fd_t (NV12) + wrapbuffer_fd_t (RGBX)...\n"); { rga_buffer_t src = wrapbuffer_fd_t(0, w, h, w, h, RK_FORMAT_YCbCr_420_SP); rga_buffer_t dst = wrapbuffer_fd_t(0, w, h, rgbx_byte_stride, h, rgbx_rga_fmt); printf(" src.handle=%u dst.handle=%u\n", src.handle, dst.handle); } /* Test 2: import NV12, wrapbuffer_fd_t RGBX */ printf(" Test 2: import NV12 + wrapbuffer_fd_t RGBX (byte_stride=%d)...\n", rgbx_byte_stride); { rga_buffer_t src = import_rga_buf(nv12_fd, w, h, w, h, RK_FORMAT_YCbCr_420_SP); rga_buffer_t dst = wrapbuffer_fd_t(0, w, h, rgbx_byte_stride, h, rgbx_rga_fmt); printf(" src.handle=%u dst.handle=%u\n", src.handle, dst.handle); if (src.handle && dst.handle) { im_rect src_rect = {0, 0, w, h}; im_rect dst_rect = {0, 0, w, h}; rga_buffer_t pat; memset(&pat, 0, sizeof(pat)); im_rect prect; memset(&prect, 0, sizeof(prect)); int ret = improcess(src, dst, 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*)rgbx_map; printf(" dst[0..3] = %02x %02x %02x %02x (expect ~FF FF FF 00 for white)\n", p[0], p[1], p[2], p[3]); } } } /* Test 3: import both, pixel stride for RGBX */ printf(" Test 3: import both, RGBX pixel_stride=%d...\n", rgbx_pixel_stride); { rga_buffer_t src = import_rga_buf(nv12_fd, w, h, w, h, RK_FORMAT_YCbCr_420_SP); rga_buffer_t dst = import_rga_buf(rgbx_fd, w, h, rgbx_pixel_stride, h, rgbx_rga_fmt); printf(" src.handle=%u dst.handle=%u\n", src.handle, dst.handle); if (src.handle && dst.handle) { im_rect src_rect = {0, 0, w, h}; im_rect dst_rect = {0, 0, w, h}; rga_buffer_t pat; memset(&pat, 0, sizeof(pat)); im_rect prect; memset(&prect, 0, sizeof(prect)); int ret = improcess(src, dst, 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*)rgbx_map; printf(" dst[0..3] = %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]); } } } /* Test 4: import both, byte stride for RGBX */ printf(" Test 4: import both, RGBX byte_stride=%d...\n", rgbx_byte_stride); { rga_buffer_t src = import_rga_buf(nv12_fd, w, h, w, h, RK_FORMAT_YCbCr_420_SP); rga_buffer_t dst = import_rga_buf(rgbx_fd, w, h, rgbx_byte_stride, h, rgbx_rga_fmt); printf(" src.handle=%u dst.handle=%u\n", src.handle, dst.handle); if (src.handle && dst.handle) { im_rect src_rect = {0, 0, w, h}; im_rect dst_rect = {0, 0, w, h}; rga_buffer_t pat; memset(&pat, 0, sizeof(pat)); im_rect prect; memset(&prect, 0, sizeof(prect)); int ret = improcess(src, dst, 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*)rgbx_map; printf(" dst[0..3] = %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]); } } } /* Test 5: use rkformat_t - try RGB888 */ printf(" Test 5: NV12->RK_FORMAT_RGB_888...\n"); { size_t rgb888_sz = (size_t)w * 3 * h; int rgb888_fd = -1; if (dma_heap_alloc(heap, rgb888_sz, &rgb888_fd) == 0) { void *rgb888_map = mmap(NULL, rgb888_sz, PROT_READ | PROT_WRITE, MAP_SHARED, rgb888_fd, 0); if (rgb888_map != MAP_FAILED) { memset(rgb888_map, 0, rgb888_sz); rga_buffer_t src = import_rga_buf(nv12_fd, w, h, w, h, RK_FORMAT_YCbCr_420_SP); rga_buffer_t dst = import_rga_buf(rgb888_fd, w, h, w * 3, h, RK_FORMAT_RGB_888); printf(" src.handle=%u dst.handle=%u\n", src.handle, dst.handle); if (src.handle && dst.handle) { im_rect src_rect = {0, 0, w, h}; im_rect dst_rect = {0, 0, w, h}; rga_buffer_t pat; memset(&pat, 0, sizeof(pat)); im_rect prect; memset(&prect, 0, sizeof(prect)); int ret = improcess(src, dst, pat, src_rect, dst_rect, prect, IM_SYNC); printf(" improcess => %d (%s)\n", ret, ret == IM_STATUS_SUCCESS ? "OK" : "FAIL"); } munmap(rgb888_map, rgb888_sz); } close(rgb888_fd); } } munmap(nv12_map, nv12_sz); munmap(rgbx_map, rgbx_sz); close(nv12_fd); close(rgbx_fd); printf("\n"); } int main(void) { printf("=== RGA NV12->RGBX Color Conversion Test ===\n\n"); /* Small test first */ test_nv12_to_rgbx("system-uncached", 320, 240, RK_FORMAT_RGBX_8888, 320, 320*4); test_nv12_to_rgbx("system-uncached", 320, 240, RK_FORMAT_BGRA_8888, 320, 320*4); test_nv12_to_rgbx("system-uncached", 320, 240, RK_FORMAT_ARGB_8888, 320, 320*4); /* Full-size */ test_nv12_to_rgbx("system-uncached", 1920, 1080, RK_FORMAT_RGBX_8888, 1920, 1920*4); test_nv12_to_rgbx("system-uncached", 1920, 1080, RK_FORMAT_BGRA_8888, 1920, 1920*4); test_nv12_to_rgbx("system-uncached", 1920, 1080, RK_FORMAT_ARGB_8888, 1920, 1920*4); printf("=== Done ===\n"); return 0; }