add nv12_test
BUG=chrome-os-partner:41644
TEST=run nv12_test
Change-Id: I03d4a70053d107a566aeca361682c0787e7cdcc0
Signed-off-by: Dominik Behr <dbehr@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/284925
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..1d83aaf
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH := $(call my-dir)
+
+#########################
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := nv12_test.c bo.c dev.c modeset.c
+
+LOCAL_MODULE := nv12_test
+
+LOCAL_C_INCLUDES := \
+ external/libdrm \
+ external/libdrm/include/drm
+LOCAL_CFLAGS := -O2 -g -W -Wall
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+LOCAL_SHARED_LIBRARIES := libdrm
+
+include $(BUILD_EXECUTABLE)
diff --git a/Makefile b/Makefile
index f893787..55e82ff 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@
CFLAGS += $(PC_CFLAGS)
LDLIBS += $(PC_LIBS)
-all: CC_BINARY(null_platform_test) CC_BINARY(vgem_test) CC_BINARY(vgem_fb_test) CC_BINARY(swrast_test) CC_BINARY(atomictest) CC_BINARY(gamma_test)
+all: CC_BINARY(null_platform_test) CC_BINARY(vgem_test) CC_BINARY(vgem_fb_test) CC_BINARY(swrast_test) CC_BINARY(atomictest) CC_BINARY(gamma_test) CC_BINARY(nv12_test)
CC_BINARY(null_platform_test): null_platform_test.o
CC_BINARY(null_platform_test): LDLIBS += $(DRM_LIBS)
@@ -32,3 +32,6 @@
CC_BINARY(gamma_test): gamma_test.o dev.o bo.o modeset.o
CC_BINARY(gamma_test): LDLIBS += -lm $(DRM_LIBS)
+
+CC_BINARY(nv12_test): nv12_test.o dev.o bo.o modeset.o
+CC_BINARY(nv12_test): LDLIBS += -lm $(DRM_LIBS)
diff --git a/bo.c b/bo.c
index 3d2155f..9a0b14d 100644
--- a/bo.c
+++ b/bo.c
@@ -19,34 +19,58 @@
draw_rect(bo, 0, 0, bo->width, bo->height, a, r, g, b);
}
+static uint8_t clampbyte(float f)
+{
+ if (f >= 255.0) return 255;
+ if (f <= 0.0) return 0;
+ return (uint8_t)f;
+}
+
void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
{
uint32_t i, j, xmax = x + width, ymax = y + height;
+ uint8_t Y = 0, Cb = 0, Cr = 0;
if (xmax > bo->width)
xmax = bo->width;
if (ymax > bo->height)
ymax = bo->height;
+ if (bo->format == DRM_FORMAT_NV12 ||
+ bo->format == DRM_FORMAT_NV21) {
+ Y = clampbyte(16 + 0.2567890625 * r + 0.50412890625 * g * 0.09790625);
+ Cb = clampbyte(128 - 0.14822265625 * r - 0.2909921875 * g + 0.43921484375 * b);
+ Cr = clampbyte(128 + 0.43921484375 * r - 0.3677890625 * g - 0.07142578125 * b);
+ }
+
for (i = y; i < ymax; i++) {
uint8_t *row = bo->map_addr + i * bo->pitch;
+ uint8_t *uvrow = bo->map_addr + bo->height * bo->pitch + (i >> 1) * bo->pitch;
for (j = x; j < xmax; j++) {
- uint8_t *pixel = row + j * 4;
-
if (bo->format == DRM_FORMAT_ARGB8888 ||
bo->format == DRM_FORMAT_XRGB8888)
{
+ uint8_t *pixel = row + j * 4;
pixel[0] = b;
pixel[1] = g;
pixel[2] = r;
pixel[3] = a;
} else if (bo->format == DRM_FORMAT_RGBA8888) {
+ uint8_t *pixel = row + j * 4;
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
pixel[3] = a;
+ } else if (bo->format == DRM_FORMAT_NV12) {
+ row[j] = Y;
+ uvrow[(j & ~1u)] = Cb;
+ uvrow[(j & ~1u) + 1] = Cr;
+ } else if (bo->format == DRM_FORMAT_NV21) {
+ row[j] = Y;
+ uvrow[(j & ~1u)] = Cr;
+ uvrow[(j & ~1u) + 1] = Cb;
}
}
}
@@ -60,6 +84,13 @@
handles[0] = bo->handle;
pitches[0] = bo->pitch;
offsets[0] = 0;
+ if (bo->format == DRM_FORMAT_NV12 ||
+ bo->format == DRM_FORMAT_NV21) {
+ bo->height = (bo->height / 3) * 2;
+ handles[1] = bo->handle;
+ pitches[1] = bo->pitch;
+ offsets[1] = bo->height * bo->pitch;
+ }
ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height,
format, handles, pitches, offsets,
diff --git a/dev.c b/dev.c
index 508834f..03e29cb 100644
--- a/dev.c
+++ b/dev.c
@@ -85,7 +85,14 @@
r = drmModeGetResources(dev->fd);
if (!r) {
- printf("failed to get r\n");
+ printf("%s failed to get r\n", devPath);
+ goto err;
+ }
+
+ if (!r->count_crtcs ||
+ !r->count_encoders ||
+ !r->count_connectors) {
+ printf("%s no display resources\n", devPath);
goto err;
}
diff --git a/nv12_test.c b/nv12_test.c
new file mode 100644
index 0000000..ef0ab3e
--- /dev/null
+++ b/nv12_test.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <drm_fourcc.h>
+
+#include "bo.h"
+#include "dev.h"
+
+static int
+is_internal(uint32_t connector_type)
+{
+ return connector_type == DRM_MODE_CONNECTOR_LVDS ||
+ connector_type == DRM_MODE_CONNECTOR_eDP ||
+ connector_type == DRM_MODE_CONNECTOR_DSI;
+}
+
+int
+find_crtc_encoder_connector(int fd, drmModeRes *resources, uint32_t *crtc_id,
+ uint32_t *encoder_id, uint32_t *connector_id)
+{
+ drmModeConnector *connector = NULL;
+ drmModeEncoder *encoder = NULL;
+ int c, e;
+ for (c = 0; c < resources->count_connectors; c++) {
+ printf("Trying connector %d\n", resources->connectors[c]);
+ connector = drmModeGetConnector(fd, resources->connectors[c]);
+ if (!connector)
+ continue;
+ printf("connected %d type %d count_modes %d\n", connector->connection, connector->count_modes, connector->connector_type);
+ if (connector->connection == DRM_MODE_CONNECTED &&
+ connector->count_modes > 0 &&
+ is_internal(connector->connector_type)) {
+ break;
+ }
+ drmModeFreeConnector(connector);
+ connector = NULL;
+ }
+ if (!connector)
+ return 0;
+
+ for (e = 0; e < connector->count_encoders; e++) {
+ printf("trying encoder %d\n", connector->encoders[e]);
+ encoder = drmModeGetEncoder(fd, connector->encoders[e]);
+ if (!encoder)
+ continue;
+
+ for (c = 0; c < resources->count_crtcs; c++) {
+ if (encoder->possible_crtcs & (1u << c)) {
+ printf("trying crtc [%d] = %d\n", c, resources->crtcs[c]);
+ *crtc_id = resources->crtcs[c];
+ *encoder_id = connector->encoders[e];
+ *connector_id = connector->connector_id;
+ drmModeFreeConnector(connector);
+ drmModeFreeEncoder(encoder);
+ return 1;
+ }
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ drmModeFreeConnector(connector);
+ return 0;
+}
+
+int
+find_best_mode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode)
+{
+ int m;
+ int found = 0;
+ drmModeConnector *connector;
+
+ connector = drmModeGetConnector(fd, connector_id);
+ if (!connector)
+ return 0;
+
+ for (m = 0; m < connector->count_modes && !found; m++) {
+ if (connector->modes[m].type & DRM_MODE_TYPE_PREFERRED) {
+ *mode = connector->modes[m];
+ found = 1;
+ }
+ }
+
+ if (!found) {
+ *mode = connector->modes[0];
+ found = 1;
+ }
+ drmModeFreeConnector(connector);
+ return found;
+}
+
+static void
+draw_pattern(struct sp_bo *bo)
+{
+ uint32_t stripw = bo->width / 256;
+ uint32_t striph = bo->height / 4;
+ uint32_t x;
+
+ fill_bo(bo, 0, 0, 0, 0);
+ for (x = 0; x < 256; x++) {
+ draw_rect(bo, x * stripw, 0, stripw, striph, 0, x, x, x);
+ draw_rect(bo, x * stripw, striph, stripw, striph, 0, x, 0, 0);
+ draw_rect(bo, x * stripw, striph * 2, stripw, striph, 0, 0, x, 0);
+ draw_rect(bo, x * stripw, striph * 3, stripw, striph, 0, 0, 0, x);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ drmModeRes *resources;
+ struct sp_dev *dev;
+
+ dev = create_sp_dev();
+ if (!dev) {
+ fprintf(stderr, "Creating DRM device failed\n");
+ return 1;
+ }
+
+ resources = drmModeGetResources(dev->fd);
+ if (!resources) {
+ fprintf(stderr, "drmModeGetResources failed: %s\n",
+ strerror(errno));
+ return 1;
+ }
+
+ {
+ int ret;
+ drmModeModeInfo mode;
+ uint32_t crtc_id = 0, encoder_id = 0, connector_id = 0;
+ struct sp_bo *bo;
+
+ if (!find_crtc_encoder_connector(dev->fd, resources, &crtc_id,
+ &encoder_id, &connector_id)) {
+ fprintf(stderr,
+ "Could not find crtc, connector and encoder\n");
+ return -1;
+ }
+ printf("Using CRTC:%u ENCODER:%u CONNECTOR:%u\n",
+ crtc_id, encoder_id, connector_id);
+
+ if (!find_best_mode(dev->fd, connector_id, &mode)) {
+ fprintf(stderr, "Could not find mode for CRTC %d\n",
+ crtc_id);
+ return -1;
+ }
+ printf("Using mode %s\n", mode.name);
+
+ printf("Creating buffer %ux%u\n", mode.hdisplay, mode.vdisplay);
+ bo = create_sp_bo(dev, mode.hdisplay, mode.vdisplay + mode.vdisplay/2, 8, 8,
+ DRM_FORMAT_NV12, 0);
+
+ draw_pattern(bo);
+
+ ret = drmModeSetCrtc(dev->fd, crtc_id, bo->fb_id, 0, 0,
+ &connector_id, 1, &mode);
+ if (ret < 0) {
+ fprintf(stderr, "Could not set mode on CRTC %d %s\n",
+ crtc_id, strerror(errno));
+ return 1;
+ }
+
+ sleep(5);
+
+ ret = drmModeSetCrtc(dev->fd, crtc_id, 0, 0, 0, NULL, 0,
+ NULL);
+ if (ret < 0) {
+ fprintf(stderr, "Could not disable CRTC %d %s\n",
+ crtc_id, strerror(errno));
+ }
+ free_sp_bo(bo);
+ }
+
+ drmModeFreeResources(resources);
+
+
+ return 0;
+}