这个测试是在libdrm-2.4.92版本上修改的,为了测试drm。 这个测试程序,找到第一个有效的crtc id之后,就覆盖对应所有的plane合成。 添加了alpha参数和blend的mode的参数,rotation目前我的平台不支持所以没有添加到properties的设置中去 之前这段code是运行在Android平台的,修改了下,又拿到yocto的平台测试。有些diff,是从Android版本上带过来的, 主要的code修改在main函数中。 这个程序比较简单,所以只贴了patch
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 62957d8..92e4edc 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -67,6 +67,8 @@
#include "buffers.h"
#include "cursor.h"
+static enum util_fill_pattern primary_fill = UTIL_PATTERN_SMPTE;
+
struct crtc {
drmModeCrtc *crtc;
drmModeObjectProperties *props;
@@ -119,6 +121,9 @@ struct device {
struct bo *bo;
struct bo *cursor_bo;
} mode;
+
+ int use_atomic;
+ drmModeAtomicReq *req;
};
static inline int64_t U642I64(uint64_t val)
@@ -781,7 +786,7 @@ static drmModeEncoder *get_encoder_by_id(struct device *dev, uint32_t id)
* can bind it with a free crtc.
*/
struct pipe_arg {
- const char **cons;
+ char **cons;
uint32_t *con_ids;
unsigned int num_cons;
uint32_t crtc_id;
@@ -798,16 +803,21 @@ struct pipe_arg {
};
struct plane_arg {
- uint32_t plane_id;
+ uint32_t plane_id;
uint32_t crtc_id;
bool has_position;
int32_t x, y;
uint32_t w, h;
double scale;
unsigned int fb_id;
+ unsigned int old_fb_id;
struct bo *bo;
+ struct bo *old_bo;
char format_str[5];
unsigned int fourcc;
+ int32_t alpha;
+ int32_t rotation;
+ int32_t blend_mode;
};
static drmModeModeInfo *
@@ -941,9 +951,10 @@ struct property_arg {
char name[DRM_PROP_NAME_LEN+1];
uint32_t prop_id;
uint64_t value;
+ bool optional;
};
-static void set_property(struct device *dev, struct property_arg *p)
+static bool set_property(struct device *dev, struct property_arg *p)
{
drmModeObjectProperties *props = NULL;
drmModePropertyRes **props_info = NULL;
@@ -975,13 +986,13 @@ static void set_property(struct device *dev, struct property_arg *p)
if (p->obj_type == 0) {
fprintf(stderr, "Object %i not found, can't set property\n",
p->obj_id);
- return;
+ return false;
}
if (!props) {
fprintf(stderr, "%s %i has no properties\n",
obj_type, p->obj_id);
- return;
+ return false;
}
for (i = 0; i < (int)props->count_props; ++i) {
@@ -992,18 +1003,25 @@ static void set_property(struct device *dev, struct property_arg *p)
}
if (i == (int)props->count_props) {
- fprintf(stderr, "%s %i has no %s property\n",
- obj_type, p->obj_id, p->name);
- return;
+ if (!p->optional)
+ fprintf(stderr, "%s %i has no %s property\n",
+ obj_type, p->obj_id, p->name);
+ return false;
}
p->prop_id = props->props[i];
- ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
- p->prop_id, p->value);
+ if (!dev->use_atomic)
+ ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
+ p->prop_id, p->value);
+ else
+ ret = drmModeAtomicAddProperty(dev->req, p->obj_id, p->prop_id, p->value);
+
if (ret < 0)
fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
obj_type, p->obj_id, p->name, p->value, strerror(errno));
+
+ return true;
}
@@ -1049,6 +1067,184 @@ static bool format_support(const drmModePlanePtr ovr, uint32_t fmt)
return false;
}
+static void add_property(struct device *dev, uint32_t obj_id,
+ const char *name, uint64_t value)
+{
+ struct property_arg p;
+
+ p.obj_id = obj_id;
+ strcpy(p.name, name);
+ p.value = value;
+
+ set_property(dev, &p);
+}
+
+static bool add_property_optional(struct device *dev, uint32_t obj_id,
+ const char *name, uint64_t value)
+{
+ struct property_arg p;
+
+ p.obj_id = obj_id;
+ strcpy(p.name, name);
+ p.value = value;
+ p.optional = true;
+
+ return set_property(dev, &p);
+}
+
+static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
+{
+ unsigned blob_id = 0;
+
+ struct drm_color_lut gamma_lut[256];
+ int i, ret;
+
+ if (fourcc == DRM_FORMAT_C8) {
+
+
+ drmModeCreatePropertyBlob(dev->fd, gamma_lut, sizeof(gamma_lut), &blob_id);
+ } else {
+ for (i = 0; i < 256; i++) {
+ gamma_lut[i].red =
+ gamma_lut[i].green =
+ gamma_lut[i].blue = i << 8;
+ }
+ }
+
+ add_property_optional(dev, crtc_id, "DEGAMMA_LUT", 0);
+ add_property_optional(dev, crtc_id, "CTM", 0);
+ if (!add_property_optional(dev, crtc_id, "GAMMA_LUT", blob_id)) {
+ uint16_t r[256], g[256], b[256];
+
+ for (i = 0; i < 256; i++) {
+ r[i] = gamma_lut[i].red;
+ g[i] = gamma_lut[i].green;
+ b[i] = gamma_lut[i].blue;
+ }
+
+ ret = drmModeCrtcSetGamma(dev->fd, crtc_id, 256, r, g, b);
+
+
+ }
+}
+
+static int32_t convert_to_drm(int32_t rot) {
+ int32_t rotation = DRM_MODE_ROTATE_0;
+ switch (rot) {
+ case 0:
+ rotation = DRM_MODE_ROTATE_0;
+ break;
+ case 1:
+ rotation = DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_0;
+ break;
+ case 2:
+ rotation = DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_0;
+ break;
+ case 3:
+ rotation = DRM_MODE_ROTATE_180;
+ break;
+ case 4:
+ rotation = DRM_MODE_ROTATE_270;
+ break;
+ case 5:
+ rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
+ break;
+ case 6:
+ rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_Y;
+ break;
+ case 7:
+ rotation = DRM_MODE_ROTATE_90;
+ break;
+ default:
+ rotation = DRM_MODE_ROTATE_0;
+ break;
+ }
+ return rotation;
+}
+
+static int atomic_set_plane(struct device *dev, struct plane_arg *p,
+ int pattern, bool update)
+{
+ uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+ struct bo *plane_bo;
+ int crtc_x, crtc_y, crtc_w, crtc_h;
+ struct crtc *crtc = NULL;
+ unsigned int i;
+ unsigned int old_fb_id;
+ int32_t rotation;
+
+
+ for (i = 0; i < (unsigned int)dev->resources->res->count_crtcs; i++) {
+ if (p->crtc_id == dev->resources->res->crtcs[i]) {
+ crtc = &dev->resources->crtcs[i];
+ break;
+ }
+ }
+
+ if (!crtc) {
+ fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
+ return -1;
+ }
+
+ if (!update) {
+ fprintf(stderr, "testing w:h = %4d:%4d, x:y = %4dx%4d, @%s on plane %u, crtc %u , display:w:%d, h:%d, scale = %llf, alpha = %d\n\n",
+ p->w, p->h, p->x, p->y, p->format_str, p->plane_id, p->crtc_id, crtc->mode->hdisplay, crtc->mode->vdisplay, p->scale, p->alpha);
+ }
+
+ rotation = convert_to_drm(p->rotation);
+
+ plane_bo = p->old_bo;
+ p->old_bo = p->bo;
+
+ if (!plane_bo) {
+ plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h,
+ handles, pitches, offsets, pattern);
+
+ if (plane_bo == NULL)
+ return -1;
+
+ if (drmModeAddFB2(dev->fd, p->w, p->h, p->fourcc,
+ handles, pitches, offsets, &p->fb_id, 0)) {
+ fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ p->bo = plane_bo;
+
+ old_fb_id = p->fb_id;
+ p->old_fb_id = old_fb_id;
+
+ crtc_w = p->w * p->scale;
+ crtc_h = p->h * p->scale;
+ if (!p->has_position) {
+
+ crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
+ crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
+ } else {
+ crtc_x = p->x;
+ crtc_y = p->y;
+ }
+
+ add_property(dev, p->plane_id, "FB_ID", p->fb_id);
+ add_property(dev, p->plane_id, "CRTC_ID", p->crtc_id);
+ add_property(dev, p->plane_id, "SRC_X", 0);
+ add_property(dev, p->plane_id, "SRC_Y", 0);
+ add_property(dev, p->plane_id, "SRC_W", p->w << 16);
+ add_property(dev, p->plane_id, "SRC_H", p->h << 16);
+ add_property(dev, p->plane_id, "CRTC_X", crtc_x);
+ add_property(dev, p->plane_id, "CRTC_Y", crtc_y);
+ add_property(dev, p->plane_id, "CRTC_W", crtc_w);
+ add_property(dev, p->plane_id, "CRTC_H", crtc_h);
+ add_property(dev, p->plane_id, "alpha", p->alpha);
+
+ add_property(dev, p->plane_id, "pixel blend mode", p->blend_mode);
+
+ return 0;
+}
+
static int set_plane(struct device *dev, struct plane_arg *p)
{
drmModePlane *ovr;
@@ -1060,6 +1256,7 @@ static int set_plane(struct device *dev, struct plane_arg *p)
struct crtc *crtc = NULL;
unsigned int pipe;
unsigned int i;
+ int32_t rotation;
if (drmModeSetPlane(dev->fd, plane_id, crtc->crtc->crtc_id, p->fb_id,
@@ -1145,6 +1352,69 @@ static int set_plane(struct device *dev, struct plane_arg *p)
return 0;
}
+static void atomic_set_planes(struct device *dev, struct plane_arg *p,
+ unsigned int count, bool update)
+{
+ unsigned int i, pattern = primary_fill;
+
+
+ for (i = 0; i < count; i++) {
+
+ pattern = primary_fill;
+
+
+
+ if (atomic_set_plane(dev, &p[i], pattern, update))
+ return;
+ }
+}
+
+static void atomic_clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ add_property(dev, p[i].plane_id, "FB_ID", 0);
+ add_property(dev, p[i].plane_id, "CRTC_ID", 0);
+ add_property(dev, p[i].plane_id, "SRC_X", 0);
+ add_property(dev, p[i].plane_id, "SRC_Y", 0);
+ add_property(dev, p[i].plane_id, "SRC_W", 0);
+ add_property(dev, p[i].plane_id, "SRC_H", 0);
+ add_property(dev, p[i].plane_id, "CRTC_X", 0);
+ add_property(dev, p[i].plane_id, "CRTC_Y", 0);
+ add_property(dev, p[i].plane_id, "CRTC_W", 0);
+ add_property(dev, p[i].plane_id, "CRTC_H", 0);
+ add_property(dev, p[i].plane_id, "alpha", 255);
+
+ add_property(dev, p[i].plane_id, "pixel blend mode", 0);
+ }
+}
+
+static void atomic_clear_FB(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ if (p[i].fb_id) {
+ drmModeRmFB(dev->fd, p[i].fb_id);
+ p[i].fb_id = 0;
+ }
+ if (p[i].old_fb_id) {
+ drmModeRmFB(dev->fd, p[i].old_fb_id);
+ p[i].old_fb_id = 0;
+ }
+ if (p[i].bo) {
+ bo_destroy(p[i].bo);
+ p[i].bo = NULL;
+ }
+ if (p[i].old_bo) {
+ bo_destroy(p[i].old_bo);
+ p[i].old_bo = NULL;
+ }
+
+ }
+}
+
static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
{
unsigned int i;
@@ -1157,6 +1427,178 @@ static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int c
}
}
+static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
+{
+ drmModeConnector *connector;
+ unsigned int i;
+ uint32_t id;
+ char *endp;
+
+ for (i = 0; i < pipe->num_cons; i++) {
+ id = strtoul(pipe->cons[i], &endp, 10);
+ if (endp == pipe->cons[i]) {
+ connector = get_connector_by_name(dev, pipe->cons[i]);
+ if (!connector) {
+ fprintf(stderr, "no connector named '%s'\n",
+ pipe->cons[i]);
+ return -ENODEV;
+ }
+
+ id = connector->connector_id;
+ }
+
+ pipe->con_ids[i] = id;
+ }
+
+ return 0;
+}
+
+static int get_valid_pipes(struct device *dev, struct pipe_arg *pipes) {
+ drmModeEncoder *encoder = NULL;
+ int i = 0;
+ int j = 0;
+ int k = 0;
+
+ struct pipe_arg *pipe = &pipes[0];
+ for (i = 0; i < dev->resources->res->count_encoders; i++) {
+ encoder = dev->resources->encoders[i].encoder;
+ if (!encoder)
+ continue;
+
+ printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+ encoder->encoder_id,
+ encoder->crtc_id,
+ util_lookup_encoder_type_name(encoder->encoder_type),
+ encoder->possible_crtcs,
+ encoder->possible_clones);
+ for (j = 0; j < dev->resources->res->count_connectors; j++) {
+ struct connector *_connector = &dev->resources->connectors[i];
+ drmModeConnector *connector = _connector->connector;
+ if (!connector)
+ continue;
+
+ printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t\n",
+ connector->connector_id,
+ connector->encoder_id,
+ util_lookup_connector_status_name(connector->connection),
+ _connector->name,
+ connector->mmWidth, connector->mmHeight,
+ connector->count_modes);
+ for (k = 0; k < connector->count_encoders; k++) {
+ if (encoder->encoder_id == connector->encoders[k]) {
+ pipe->num_cons = 1;
+ pipe->vrefresh = 0;
+ pipe->con_ids = calloc(pipe->num_cons, sizeof(*pipe->con_ids));
+ pipe->cons = calloc(pipe->num_cons, sizeof(*pipe->cons));
+ if (pipe->con_ids == NULL || pipe->cons == NULL) {
+ printf("Fail to alloc pipe->cons or pipe->con_ids\n");
+ return -1;
+ }
+ char temp[10];
+ memset(temp, '\0', 10);
+ sprintf(temp, "%d", connector->connector_id);
+ pipe->cons[0] = strndup(temp, strlen(temp) + 1);
+ fprintf(stderr, "Success to find the first vaild connector id = %s, cons = %s\n",temp, pipe->cons[0]);
+ pipe->crtc_id = encoder->crtc_id;
+ strcpy(pipe->format_str, "XR24");
+ if (pipe_resolve_connectors(dev, pipe) < 0)
+ return -1;
+
+ if (connector->count_modes) {
+ drmModeModeInfo *mode = &connector->modes[0];
+ strncpy(pipe->mode_str, mode->name, strlen(mode->name));
+ fprintf(stderr, "mode name = %s\n", pipe->mode_str);
+ } else {
+ fprintf(stderr, "mode count is 0 !!! \n");
+ return -1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int get_max_count_for_format(struct device *dev) {
+ int max = 0;
+ int i = 0;
+
+ if (!dev->resources->plane_res)
+ return max;
+
+ for (i = 0; i < dev->resources->plane_res->count_planes; i++) {
+ struct plane *plane = &dev->resources->planes[i];
+ drmModePlane *ovr = plane->plane;
+ if (!ovr)
+ continue;
+
+ printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%-8d\t0x%08x\n",
+ ovr->plane_id, ovr->crtc_id, ovr->fb_id,
+ ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
+ ovr->gamma_size, ovr->possible_crtcs);
+
+ if (!ovr->count_formats)
+ continue;
+ if (max < ovr->count_formats)
+ max = ovr->count_formats;
+ }
+ return max;
+}
+
+static void atomic_set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+ unsigned int i;
+ unsigned int j;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+
+ ret = pipe_find_crtc_and_mode(dev, pipe);
+ if (ret < 0)
+ continue;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+ uint32_t blob_id;
+
+ if (pipe->mode == NULL)
+ continue;
+
+ printf("setting mode %s-%dHz on connectors ",
+ pipe->mode_str, pipe->mode->vrefresh);
+ for (j = 0; j < pipe->num_cons; ++j) {
+ printf("%s, ", pipe->cons[j]);
+ add_property(dev, pipe->con_ids[j], "CRTC_ID", pipe->crtc->crtc->crtc_id);
+ }
+ printf("crtc %d\n", pipe->crtc->crtc->crtc_id);
+
+ drmModeCreatePropertyBlob(dev->fd, pipe->mode, sizeof(*pipe->mode), &blob_id);
+ add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", blob_id);
+ add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 1);
+ }
+}
+
+static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+ unsigned int i;
+ unsigned int j;
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+
+ if (pipe->mode == NULL)
+ continue;
+
+ for (j = 0; j < pipe->num_cons; ++j)
+ add_property(dev, pipe->con_ids[j], "CRTC_ID",0);
+
+ add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", 0);
+ add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 0);
+ }
+}
static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
{
@@ -1185,7 +1627,7 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width,
dev->mode.height, handles, pitches, offsets,
- UTIL_PATTERN_SMPTE);
+ primary_fill);
if (bo == NULL)
return;
@@ -1227,6 +1669,8 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
return;
}
+
+ set_gamma(dev, pipe->crtc->crtc->crtc_id, pipe->fourcc);
}
}
@@ -1499,13 +1943,32 @@ static int parse_plane(struct plane_arg *plane, const char *p)
} else {
plane->scale = 1.0;
}
-
- if (*end == '@') {
+ if (*end == 'R') {
p = end + 1;
- if (strlen(p) != 4)
- return -EINVAL;
+ plane->rotation = strtol(p, &end, 10);
+ } else {
+ plane->rotation = 0;
+ }
+ fprintf(stderr, "rotation %d\n", plane->rotation);
+ if (*end == 'A') {
+ p = end + 1;
+ plane->alpha = strtol(p, &end, 10);
+ fprintf(stderr, "alpha %d\n", plane->alpha);
+ } else {
+ plane->alpha = 255;
+ }
+ fprintf(stderr, "alpha %d\n", plane->alpha);
+ if (*end == 'M') {
+ p = end + 1;
+ plane->blend_mode = strtol(p, &end, 10);
+ } else {
+ plane->blend_mode = 1;
+ }
+ fprintf(stderr, "blend mode %d\n", plane->blend_mode);
- strcpy(plane->format_str, p);
+ if (*end == '@') {
+ strncpy(plane->format_str, end + 1, 4);
+ plane->format_str[4] = '\0';
} else {
strcpy(plane->format_str, "XR24");
}
@@ -1532,7 +1995,7 @@ static int parse_property(struct property_arg *p, const char *arg)
static void usage(char *name)
{
- fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
+ fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
fprintf(stderr, "\n Query options:\n\n");
fprintf(stderr, "\t-c\tlist connectors\n");
@@ -1546,6 +2009,8 @@ static void usage(char *name)
fprintf(stderr, "\t-C\ttest hw cursor\n");
fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
+ fprintf(stderr, "\t-a \tuse atomic API\n");
+ fprintf(stderr, "\t-F pattern1,pattern2\tspecify fill patterns\n");
fprintf(stderr, "\n Generic options:\n\n");
fprintf(stderr, "\t-d\tdrop master after mode set\n");
@@ -1583,33 +2048,14 @@ static int cursor_supported(void)
return 1;
}
-static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
-{
- drmModeConnector *connector;
- unsigned int i;
- uint32_t id;
- char *endp;
-
- for (i = 0; i < pipe->num_cons; i++) {
- id = strtoul(pipe->cons[i], &endp, 10);
- if (endp == pipe->cons[i]) {
- connector = get_connector_by_name(dev, pipe->cons[i]);
- if (!connector) {
- fprintf(stderr, "no connector named '%s'\n",
- pipe->cons[i]);
- return -ENODEV;
- }
-
- id = connector->connector_id;
- }
-
- pipe->con_ids[i] = id;
- }
-
- return 0;
+static void get_fourcc(char* format, uint32_t fourcc) {
+ sprintf(format, "%c", fourcc);
+ sprintf(format + 1, "%c", fourcc >> 8);
+ sprintf(format + 2, "%c", fourcc >> 16);
+ sprintf(format + 3, "%c", fourcc >> 24);
}
-static char optstr[] = "cdD:efM:P:ps:Cvw:";
+static char optstr[] = "acdD:efF:M:P:ps:Cvw:A";
int main(int argc, char **argv)
{
@@ -1620,6 +2066,7 @@ int main(int argc, char **argv)
int drop_master = 0;
int test_vsync = 0;
int test_cursor = 0;
+ int use_atomic = 0;
char *device = NULL;
char *module = NULL;
unsigned int i;
@@ -1630,6 +2077,8 @@ int main(int argc, char **argv)
struct property_arg *prop_args = NULL;
unsigned int args = 0;
int ret;
+ bool abort = false;
+ bool test_all = false;
memset(&dev, 0, sizeof dev);
@@ -1638,6 +2087,9 @@ int main(int argc, char **argv)
args++;
switch (c) {
+ case 'a':
+ use_atomic = 1;
+ break;
case 'c':
connectors = 1;
break;
@@ -1711,25 +2163,37 @@ int main(int argc, char **argv)
prop_count++;
break;
+ case 'A':
+ test_all = true;
+ break;
default:
usage(argv[0]);
break;
}
}
- if (!args)
+ if (!args || (args == 1 && use_atomic))
encoders = connectors = crtcs = planes = framebuffers = 1;
dev.fd = util_open(device, module);
if (dev.fd < 0)
return -1;
+ ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
+ if (ret && use_atomic) {
+ fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
+ drmClose(dev.fd);
+ return -1;
+ }
+
+ dev.use_atomic = use_atomic;
+
if (test_vsync && !page_flipping_supported()) {
fprintf(stderr, "page flipping not supported by drm.\n");
return -1;
}
- if (test_vsync && !count) {
+ if (!test_all && test_vsync && !count) {
fprintf(stderr, "page flipping requires at least one -s option.\n");
return -1;
}
@@ -1741,15 +2205,18 @@ int main(int argc, char **argv)
dev.resources = get_resources(&dev);
if (!dev.resources) {
+ fprintf(stderr, "failed to find the resources\n");
drmClose(dev.fd);
return 1;
}
- for (i = 0; i < count; i++) {
- if (pipe_resolve_connectors(&dev, &pipe_args[i]) < 0) {
- free_resources(dev.resources);
- drmClose(dev.fd);
- return 1;
+ if (!test_all) {
+ for (i = 0; i < count; i++) {
+ if (pipe_resolve_connectors(&dev, &pipe_args[i]) < 0) {
+ free_resources(dev.resources);
+ drmClose(dev.fd);
+ return 1;
+ }
}
}
@@ -1764,40 +2231,247 @@ int main(int argc, char **argv)
for (i = 0; i < prop_count; ++i)
set_property(&dev, &prop_args[i]);
- if (count || plane_count) {
- uint64_t cap = 0;
+ if (dev.use_atomic) {
+ dev.req = drmModeAtomicAlloc();
+
+ if (count && plane_count && !test_all) {
+ uint64_t cap = 0;
+ int connect_id = 0;
+
+ ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+ if (ret || cap == 0) {
+ fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+ return 1;
+ }
+
+ atomic_set_mode(&dev, pipe_args, count);
+ atomic_set_planes(&dev, plane_args, plane_count, false);
+
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed [1]\n");
+ return 1;
+ }
+
+ gettimeofday(&pipe_args->start, NULL);
+ pipe_args->swap_count = 0;
+
+ while (test_vsync) {
+ drmModeAtomicFree(dev.req);
+ dev.req = drmModeAtomicAlloc();
+ atomic_set_planes(&dev, plane_args, plane_count, true);
+
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed [2]\n");
+ return 1;
+ }
+
+ pipe_args->swap_count++;
+ if (pipe_args->swap_count == 60) {
+ struct timeval end;
+ double t;
+
+ gettimeofday(&end, NULL);
+ t = end.tv_sec + end.tv_usec * 1e-6 -
+ (pipe_args->start.tv_sec + pipe_args->start.tv_usec * 1e-6);
+ fprintf(stderr, "freq: %.02fHz\n", pipe_args->swap_count / t);
+ pipe_args->swap_count = 0;
+ pipe_args->start = end;
+ }
+ }
+ drmModeAtomicFree(dev.req);
+ dev.req = drmModeAtomicAlloc();
+ if (drop_master)
+ drmDropMaster(dev.fd);
+
+ getchar();
+
+ atomic_clear_mode(&dev, pipe_args, count);
+ atomic_clear_planes(&dev, plane_args, plane_count);
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed\n");
+ return 1;
+ }
+
+ atomic_clear_FB(&dev, plane_args, plane_count);
+
+ drmModeAtomicFree(dev.req);
+ } else {
+ struct pipe_arg *pipes = NULL;
+ struct plane_arg *planes = NULL;
+ uint32_t i = 0;
+ uint32_t j = 0;
+ int max_format_count = 0;
+ char format[5];
+ uint64_t cap = 0;
+ int connect_id = 0;
+ int valid_plane_count = 0;
+ int vdisplay = 0;
+ int hdisplay = 0;
+ int valid_planes = 0;
+ struct pipe_arg *pipe = NULL;
+ fprintf(stderr, "\n\n");
+ fprintf(stderr, "For checking the plane color, you'd best to know info about color:\n");
+ fprintf(stderr, "| postion | color | format |\n");
+ fprintf(stderr, "| top middle bottom | red/grey/ini-phase | XR4H XB4H AR4H AB4H |\n");
+ fprintf(stderr, "| top middle bottom | magenta/black/super white | AR24 XR24 AB24 XB24 RA24 RX24 BA24 BX24 AR30 XR30 AB30 XB30 RA30 RX30 BA30 BX30 |\n");
+ fprintf(stderr, "| top middle bottom | yellow/green/black | AR12 XR12 AB12 XB12 RA12 RX12 BA12 BX12 AR15 XR15 AB15 XB15 RA15 RX15 BA15 BX15 RG16 BG16 |\n");
+ fprintf(stderr, "| top middle bottom | cyan/grey/quarature | BG24 RG24 |\n");
+ fprintf(stderr, "| top middle bottom | green/blue/black | NV21 NV21 NV16 NV61 YU12 YV12 |\n");
+ fprintf(stderr, "| top middle bottom | red/blue/green | UYVY VYUY YUYV YVYU |\n");
+ fprintf(stderr, "\n\n");
+
+ ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+ if (ret || cap == 0) {
+ fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+ return 1;
+ }
- ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
- if (ret || cap == 0) {
- fprintf(stderr, "driver doesn't support the dumb buffer API\n");
- return 1;
+ pipes = realloc(pipes, sizeof(*pipes));
+ if (pipes == NULL) {
+ fprintf(stderr, "memory allocation failed\n");
+ return 1;
+ }
+ memset(&pipes[0], 0, sizeof(*pipes));
+ if (get_valid_pipes(&dev, pipes)) {
+ free_resources(dev.resources);
+ drmClose(dev.fd);
+ return 1;
+ }
+ if (!dev.resources->plane_res) {
+ fprintf(stderr, "plane resource is null \n");
+ return 1;
+ }
+
+ max_format_count = get_max_count_for_format(&dev);
+ pipe = &pipes[0];
+ for (j = 0; j < dev.resources->plane_res->count_planes; j++) {
+ struct plane *plane = &dev.resources->planes[j];
+ drmModePlane *drm_plane = plane->plane;
+ if (drm_plane->crtc_id == 0) {
+ drm_plane->crtc_id = pipe->crtc->crtc->crtc_id;
+ }
+ planes = realloc(planes,
+ (valid_plane_count + 1) * sizeof *planes);
+ if (planes == NULL) {
+ fprintf(stderr, "memory allocation failed\n");
+ return 1;
+ }
+ memset(&planes[valid_plane_count], 0, sizeof(*planes));
+ valid_plane_count++;
+ }
+ for (i = 0; i < max_format_count * 2; i++) {
+ valid_planes = 0;
+ atomic_set_mode(&dev, pipes, 1);
+ vdisplay = pipe->crtc->mode->vdisplay;
+ hdisplay = pipe->crtc->mode->hdisplay;
+ if (hdisplay % 16 != 0)
+ hdisplay = hdisplay + 16 - hdisplay % 16;
+
+
+ for (j = 0; j < dev.resources->plane_res->count_planes; j++) {
+ struct plane *plane = &dev.resources->planes[j];
+ drmModePlane *drm_plane = plane->plane;
+ if (drm_plane->crtc_id == 0) {
+ drm_plane->crtc_id = pipe->crtc->crtc->crtc_id;
+ }
+ int index = j;
+ int sub = (valid_plane_count - 1) * 2 * 16;
+ int iformat = (i + j * 6) % max_format_count;
+ if (iformat >= drm_plane->count_formats) {
+ iformat = drm_plane->count_formats-1;
+ }
+ get_fourcc(format, drm_plane->formats[iformat]);
+ if (strcmp(format, "BX24") == 0)
+ continue;
+ strncpy(planes[valid_planes].format_str, format, 4);
+ planes[valid_planes].fourcc = drm_plane->formats[iformat];
+ planes[valid_planes].plane_id = drm_plane->plane_id;
+ planes[valid_planes].w = index % valid_plane_count * 16 + (hdisplay - sub);
+ planes[valid_planes].h = index % valid_plane_count * 16 + (hdisplay - sub);
+ planes[valid_planes].crtc_id = drm_plane->crtc_id;
+ planes[valid_planes].x = (index % valid_plane_count) * 16;
+ planes[valid_planes].y = (index % valid_plane_count) * 16;
+ planes[valid_planes].scale = ((i + j + 4) % 10) * 0.1 + 0.1;
+ planes[valid_planes].rotation = (i + j) % 8;
+ planes[valid_planes].blend_mode = (i + j) % 3;
+ planes[valid_planes].alpha = ((j + i) * 100 + 80) % 255;
+ planes[valid_planes].has_position = true;
+ planes[valid_planes].bo = NULL;
+ planes[valid_planes].old_bo = NULL;
+
+ fprintf(stderr, " planesetting 2 [valid_planes = %d\n", valid_planes);
+ valid_planes++;
+ }
+ atomic_set_planes(&dev, planes, valid_planes, false);
+
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed [1] ret = %d \n", ret);
+ return 1;
+ }
+ sleep(8);
+
+ atomic_clear_FB(&dev, planes, valid_planes);
+ drmModeAtomicFree(dev.req);
+ dev.req = drmModeAtomicAlloc();
+ }
+
+ atomic_clear_mode(&dev, pipes, count);
+ atomic_clear_planes(&dev, planes, valid_planes);
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed\n");
+ return 1;
+ }
}
+ } else {
+ if (count || plane_count) {
+ uint64_t cap = 0;
- if (count)
- set_mode(&dev, pipe_args, count);
+ ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+ if (ret || cap == 0) {
+ fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+ return 1;
+ }
- if (plane_count)
- set_planes(&dev, plane_args, plane_count);
+ if (count)
+ set_mode(&dev, pipe_args, count);
- if (test_cursor)
- set_cursors(&dev, pipe_args, count);
+ if (plane_count)
+ set_planes(&dev, plane_args, plane_count);
- if (test_vsync)
- test_page_flip(&dev, pipe_args, count);
+ if (test_cursor)
+ set_cursors(&dev, pipe_args, count);
- if (drop_master)
- drmDropMaster(dev.fd);
+ if (test_vsync)
+ test_page_flip(&dev, pipe_args, count);
- getchar();
+ if (drop_master)
+ drmDropMaster(dev.fd);
- if (test_cursor)
- clear_cursors(&dev);
+ getchar();
- if (plane_count)
- clear_planes(&dev, plane_args, plane_count);
+ if (test_cursor)
+ clear_cursors(&dev);
- if (count)
- clear_mode(&dev);
+ if (plane_count)
+ clear_planes(&dev, plane_args, plane_count);
+
+ if (count)
+ clear_mode(&dev);
+ }
}
free_resources(dev.resources);
|