summaryrefslogtreecommitdiff
path: root/tests/modetest/buffers.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2014-12-09 22:00:58 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-01-11 14:37:53 +0200
commitd7c0a08bc576deb07df6c3f91f393ca8edd0c4bf (patch)
tree8655e690adaeb888110ef392abf799c3217871e2 /tests/modetest/buffers.c
parent566c3ce877a4be72697e15cdfc421ce965f7c37d (diff)
modetest: Allocate dumb buffers with the correct bpp
The modetest application uses libkms to allocate dumb buffers, leading to overallocation due to the hardcoded 32 bpp value. This can even cause failures in drivers when the resulting pitch is too large for the hardware to handle and gets rejected by the driver when creating the frame buffer. Fix this by computing the required bpp value and allocating dumb buffers directly without going through libkms. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'tests/modetest/buffers.c')
-rw-r--r--tests/modetest/buffers.c216
1 files changed, 172 insertions, 44 deletions
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
index e725c32b..e4e81495 100644
--- a/tests/modetest/buffers.c
+++ b/tests/modetest/buffers.c
@@ -34,9 +34,13 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include "drm.h"
#include "drm_fourcc.h"
-#include "libkms.h"
+
+#include "libdrm.h"
+#include "xf86drm.h"
#include "buffers.h"
@@ -47,6 +51,16 @@
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+struct bo
+{
+ int fd;
+ void *ptr;
+ size_t size;
+ size_t offset;
+ size_t pitch;
+ unsigned handle;
+};
+
/* -----------------------------------------------------------------------------
* Formats
*/
@@ -1001,48 +1015,82 @@ fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3],
* Buffers management
*/
-static struct kms_bo *
-allocate_buffer(struct kms_driver *kms, unsigned int width, unsigned int height,
- unsigned int *stride)
+static struct bo *
+bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp)
{
- struct kms_bo *bo;
- unsigned bo_attribs[] = {
- KMS_WIDTH, 0,
- KMS_HEIGHT, 0,
- KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
- KMS_TERMINATE_PROP_LIST
- };
+ struct drm_mode_create_dumb arg;
+ struct bo *bo;
int ret;
- bo_attribs[1] = width;
- bo_attribs[3] = height;
-
- ret = kms_bo_create(kms, bo_attribs, &bo);
- if (ret) {
- fprintf(stderr, "failed to alloc buffer: %s\n",
- strerror(-ret));
+ bo = malloc(sizeof(*bo));
+ if (bo == NULL) {
+ fprintf(stderr, "failed to allocate buffer object\n");
return NULL;
}
- ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
+ memset(&arg, 0, sizeof(arg));
+ arg.bpp = bpp;
+ arg.width = width;
+ arg.height = height;
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
if (ret) {
- fprintf(stderr, "failed to retreive buffer stride: %s\n",
- strerror(-ret));
- kms_bo_destroy(&bo);
+ fprintf(stderr, "failed to create dumb buffer: %s\n",
+ strerror(errno));
+ free(bo);
return NULL;
}
+ bo->fd = fd;
+ bo->handle = arg.handle;
+ bo->size = arg.size;
+ bo->pitch = arg.pitch;
+
return bo;
}
-struct kms_bo *
-create_test_buffer(struct kms_driver *kms, unsigned int format,
- unsigned int width, unsigned int height,
- unsigned int handles[4], unsigned int pitches[4],
- unsigned int offsets[4], enum fill_pattern pattern)
+static int bo_map(struct bo *bo, void **out)
+{
+ struct drm_mode_map_dumb arg;
+ void *map;
+ int ret;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->handle;
+
+ ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
+ if (ret)
+ return ret;
+
+ map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ bo->fd, arg.offset);
+ if (map == MAP_FAILED)
+ return -EINVAL;
+
+ bo->ptr = map;
+ *out = map;
+
+ return 0;
+}
+
+static void bo_unmap(struct bo *bo)
+{
+ if (!bo->ptr)
+ return;
+
+ drm_munmap(bo->ptr, bo->size);
+ bo->ptr = NULL;
+}
+
+struct bo *
+bo_create(int fd, unsigned int format,
+ unsigned int width, unsigned int height,
+ unsigned int handles[4], unsigned int pitches[4],
+ unsigned int offsets[4], enum fill_pattern pattern)
{
unsigned int virtual_height;
- struct kms_bo *bo;
+ struct bo *bo;
+ unsigned int bpp;
void *planes[3] = { 0, };
void *virtual;
int ret;
@@ -1050,6 +1098,70 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
switch (format) {
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ bpp = 8;
+ break;
+
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRX5551:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ bpp = 16;
+ break;
+
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ bpp = 24;
+ break;
+
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ bpp = 32;
+ break;
+
+ default:
+ fprintf(stderr, "unsupported format 0x%08x\n", format);
+ return NULL;
+ }
+
+ switch (format) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
virtual_height = height * 3 / 2;
break;
@@ -1063,15 +1175,15 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
break;
}
- bo = allocate_buffer(kms, width, virtual_height, &pitches[0]);
+ bo = bo_create_dumb(fd, width, virtual_height, bpp);
if (!bo)
return NULL;
- ret = kms_bo_map(bo, &virtual);
+ ret = bo_map(bo, &virtual);
if (ret) {
fprintf(stderr, "failed to map buffer: %s\n",
- strerror(-ret));
- kms_bo_destroy(&bo);
+ strerror(-errno));
+ bo_destroy(bo);
return NULL;
}
@@ -1084,8 +1196,8 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
case DRM_FORMAT_YUYV:
case DRM_FORMAT_YVYU:
offsets[0] = 0;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
- kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
planes[0] = virtual;
break;
@@ -1095,11 +1207,11 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
offsets[0] = 0;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
- kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
pitches[1] = pitches[0];
offsets[1] = pitches[0] * height;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
+ handles[1] = bo->handle;
planes[0] = virtual;
planes[1] = virtual + offsets[1];
@@ -1108,14 +1220,14 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420:
offsets[0] = 0;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
- kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
pitches[1] = pitches[0] / 2;
offsets[1] = pitches[0] * height;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
+ handles[1] = bo->handle;
pitches[2] = pitches[1];
offsets[2] = offsets[1] + pitches[1] * height / 2;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
+ handles[2] = bo->handle;
planes[0] = virtual;
planes[1] = virtual + offsets[1];
@@ -1159,15 +1271,31 @@ create_test_buffer(struct kms_driver *kms, unsigned int format,
case DRM_FORMAT_BGRA1010102:
case DRM_FORMAT_BGRX1010102:
offsets[0] = 0;
- kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
- kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
planes[0] = virtual;
break;
}
fill_pattern(format, pattern, planes, width, height, pitches[0]);
- kms_bo_unmap(bo);
+ bo_unmap(bo);
return bo;
}
+
+void bo_destroy(struct bo *bo)
+{
+ struct drm_mode_destroy_dumb arg;
+ int ret;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->handle;
+
+ ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
+ if (ret)
+ fprintf(stderr, "failed to destroy dumb buffer: %s\n",
+ strerror(errno));
+
+ free(bo);
+}