sync with OpenBSD -current
This commit is contained in:
parent
abc24a81d1
commit
921461fcd8
53 changed files with 2169 additions and 443 deletions
|
@ -124,16 +124,36 @@ bo_create(int fd, unsigned int format,
|
|||
int ret;
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_C1:
|
||||
bpp = 1;
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_C2:
|
||||
bpp = 2;
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_C4:
|
||||
bpp = 4;
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_C8:
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV61:
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV42:
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
bpp = 8;
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_NV15:
|
||||
case DRM_FORMAT_NV20:
|
||||
case DRM_FORMAT_NV30:
|
||||
bpp = 10;
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_ARGB4444:
|
||||
case DRM_FORMAT_XRGB4444:
|
||||
case DRM_FORMAT_ABGR4444:
|
||||
|
@ -144,6 +164,7 @@ bo_create(int fd, unsigned int format,
|
|||
case DRM_FORMAT_BGRX4444:
|
||||
case DRM_FORMAT_ARGB1555:
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
|
||||
case DRM_FORMAT_ABGR1555:
|
||||
case DRM_FORMAT_XBGR1555:
|
||||
case DRM_FORMAT_RGBA5551:
|
||||
|
@ -151,6 +172,7 @@ bo_create(int fd, unsigned int format,
|
|||
case DRM_FORMAT_BGRA5551:
|
||||
case DRM_FORMAT_BGRX5551:
|
||||
case DRM_FORMAT_RGB565:
|
||||
case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
|
||||
case DRM_FORMAT_BGR565:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
|
@ -198,6 +220,7 @@ bo_create(int fd, unsigned int format,
|
|||
switch (format) {
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV15:
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
virtual_height = height * 3 / 2;
|
||||
|
@ -205,9 +228,16 @@ bo_create(int fd, unsigned int format,
|
|||
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV61:
|
||||
case DRM_FORMAT_NV20:
|
||||
virtual_height = height * 2;
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV42:
|
||||
case DRM_FORMAT_NV30:
|
||||
virtual_height = height * 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
virtual_height = height;
|
||||
break;
|
||||
|
@ -244,6 +274,8 @@ bo_create(int fd, unsigned int format,
|
|||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV61:
|
||||
case DRM_FORMAT_NV15:
|
||||
case DRM_FORMAT_NV20:
|
||||
offsets[0] = 0;
|
||||
handles[0] = bo->handle;
|
||||
pitches[0] = bo->pitch;
|
||||
|
@ -255,6 +287,20 @@ bo_create(int fd, unsigned int format,
|
|||
planes[1] = virtual + offsets[1];
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV42:
|
||||
case DRM_FORMAT_NV30:
|
||||
offsets[0] = 0;
|
||||
handles[0] = bo->handle;
|
||||
pitches[0] = bo->pitch;
|
||||
pitches[1] = pitches[0] * 2;
|
||||
offsets[1] = pitches[0] * height;
|
||||
handles[1] = bo->handle;
|
||||
|
||||
planes[0] = virtual;
|
||||
planes[1] = virtual + offsets[1];
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
offsets[0] = 0;
|
||||
|
@ -272,6 +318,9 @@ bo_create(int fd, unsigned int format,
|
|||
planes[2] = virtual + offsets[2];
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_C1:
|
||||
case DRM_FORMAT_C2:
|
||||
case DRM_FORMAT_C4:
|
||||
case DRM_FORMAT_C8:
|
||||
case DRM_FORMAT_ARGB4444:
|
||||
case DRM_FORMAT_XRGB4444:
|
||||
|
@ -283,6 +332,7 @@ bo_create(int fd, unsigned int format,
|
|||
case DRM_FORMAT_BGRX4444:
|
||||
case DRM_FORMAT_ARGB1555:
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
|
||||
case DRM_FORMAT_ABGR1555:
|
||||
case DRM_FORMAT_XBGR1555:
|
||||
case DRM_FORMAT_RGBA5551:
|
||||
|
@ -290,6 +340,7 @@ bo_create(int fd, unsigned int format,
|
|||
case DRM_FORMAT_BGRA5551:
|
||||
case DRM_FORMAT_BGRX5551:
|
||||
case DRM_FORMAT_RGB565:
|
||||
case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
|
||||
case DRM_FORMAT_BGR565:
|
||||
case DRM_FORMAT_BGR888:
|
||||
case DRM_FORMAT_RGB888:
|
||||
|
@ -338,3 +389,22 @@ void bo_destroy(struct bo *bo)
|
|||
|
||||
free(bo);
|
||||
}
|
||||
|
||||
void bo_dump(struct bo *bo, const char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (!bo || !filename)
|
||||
return;
|
||||
|
||||
fp = fopen(filename, "wb");
|
||||
if (fp) {
|
||||
void *addr;
|
||||
|
||||
bo_map(bo, &addr);
|
||||
printf("Dumping buffer %p to file %s.\n", bo->ptr, filename);
|
||||
fwrite(bo->ptr, 1, bo->size, fp);
|
||||
bo_unmap(bo);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,5 +36,6 @@ struct bo *bo_create(int fd, unsigned int format,
|
|||
unsigned int handles[4], unsigned int pitches[4],
|
||||
unsigned int offsets[4], enum util_fill_pattern pattern);
|
||||
void bo_destroy(struct bo *bo);
|
||||
void bo_dump(struct bo *bo, const char *filename);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,5 +25,6 @@ modetest = executable(
|
|||
include_directories : [inc_root, inc_tests, inc_drm],
|
||||
dependencies : [dep_threads, dep_cairo],
|
||||
link_with : [libdrm, libutil],
|
||||
link_args: '-lm',
|
||||
install : with_install_tests,
|
||||
)
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
|
||||
static enum util_fill_pattern primary_fill = UTIL_PATTERN_SMPTE;
|
||||
static enum util_fill_pattern secondary_fill = UTIL_PATTERN_TILES;
|
||||
static drmModeModeInfo user_mode;
|
||||
|
||||
struct crtc {
|
||||
drmModeCrtc *crtc;
|
||||
|
@ -128,6 +129,7 @@ struct device {
|
|||
|
||||
int use_atomic;
|
||||
drmModeAtomicReq *req;
|
||||
int32_t writeback_fence_fd;
|
||||
};
|
||||
|
||||
static inline int64_t U642I64(uint64_t val)
|
||||
|
@ -137,8 +139,19 @@ static inline int64_t U642I64(uint64_t val)
|
|||
|
||||
static float mode_vrefresh(drmModeModeInfo *mode)
|
||||
{
|
||||
return mode->clock * 1000.00
|
||||
/ (mode->htotal * mode->vtotal);
|
||||
unsigned int num, den;
|
||||
|
||||
num = mode->clock;
|
||||
den = mode->htotal * mode->vtotal;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
num *= 2;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
den *= 2;
|
||||
if (mode->vscan > 1)
|
||||
den *= mode->vscan;
|
||||
|
||||
return num * 1000.00 / den;
|
||||
}
|
||||
|
||||
#define bit_name_fn(res) \
|
||||
|
@ -317,7 +330,7 @@ static void dump_in_formats(struct device *dev, uint32_t blob_id)
|
|||
printf(": ");
|
||||
}
|
||||
|
||||
printf(" %s", modifier_to_string(iter.mod));
|
||||
printf(" %s(0x%"PRIx64")", modifier_to_string(iter.mod), iter.mod);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
@ -804,13 +817,15 @@ struct pipe_arg {
|
|||
unsigned int num_cons;
|
||||
uint32_t crtc_id;
|
||||
char mode_str[64];
|
||||
char format_str[5];
|
||||
char format_str[8]; /* need to leave room for "_BE" and terminating \0 */
|
||||
float vrefresh;
|
||||
unsigned int fourcc;
|
||||
drmModeModeInfo *mode;
|
||||
struct crtc *crtc;
|
||||
unsigned int fb_id[2], current_fb_id;
|
||||
struct timeval start;
|
||||
unsigned int out_fb_id;
|
||||
struct bo *out_bo;
|
||||
|
||||
int swap_count;
|
||||
};
|
||||
|
@ -826,7 +841,7 @@ struct plane_arg {
|
|||
unsigned int old_fb_id;
|
||||
struct bo *bo;
|
||||
struct bo *old_bo;
|
||||
char format_str[5]; /* need to leave room for terminating \0 */
|
||||
char format_str[8]; /* need to leave room for "_BE" and terminating \0 */
|
||||
unsigned int fourcc;
|
||||
};
|
||||
|
||||
|
@ -839,7 +854,25 @@ connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str,
|
|||
int i;
|
||||
|
||||
connector = get_connector_by_id(dev, con_id);
|
||||
if (!connector || !connector->count_modes)
|
||||
if (!connector)
|
||||
return NULL;
|
||||
|
||||
if (strchr(mode_str, ',')) {
|
||||
i = sscanf(mode_str, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu",
|
||||
&user_mode.hdisplay, &user_mode.hsync_start,
|
||||
&user_mode.hsync_end, &user_mode.htotal,
|
||||
&user_mode.vdisplay, &user_mode.vsync_start,
|
||||
&user_mode.vsync_end, &user_mode.vtotal);
|
||||
if (i == 8) {
|
||||
user_mode.clock = roundf(user_mode.htotal * user_mode.vtotal * vrefresh / 1000);
|
||||
user_mode.vrefresh = roundf(vrefresh);
|
||||
snprintf(user_mode.name, sizeof(user_mode.name), "custom%dx%d", user_mode.hdisplay, user_mode.vdisplay);
|
||||
|
||||
return &user_mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (!connector->count_modes)
|
||||
return NULL;
|
||||
|
||||
/* Pick by Index */
|
||||
|
@ -1040,7 +1073,7 @@ static bool set_property(struct device *dev, struct property_arg *p)
|
|||
|
||||
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));
|
||||
obj_type, p->obj_id, p->name, p->value, strerror(-ret));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1116,15 +1149,23 @@ static bool add_property_optional(struct device *dev, uint32_t obj_id,
|
|||
static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
|
||||
{
|
||||
unsigned blob_id = 0;
|
||||
const struct util_format_info *info;
|
||||
/* TODO: support 1024-sized LUTs, when the use-case arises */
|
||||
struct drm_color_lut gamma_lut[256];
|
||||
int i, ret;
|
||||
|
||||
if (fourcc == DRM_FORMAT_C8) {
|
||||
/* TODO: Add C8 support for more patterns */
|
||||
util_smpte_c8_gamma(256, gamma_lut);
|
||||
info = util_format_info_find(fourcc);
|
||||
if (info->ncolors) {
|
||||
memset(gamma_lut, 0, sizeof(gamma_lut));
|
||||
/* TODO: Add index support for more patterns */
|
||||
util_smpte_fill_lut(info->ncolors, gamma_lut);
|
||||
drmModeCreatePropertyBlob(dev->fd, gamma_lut, sizeof(gamma_lut), &blob_id);
|
||||
} else {
|
||||
/*
|
||||
* Initialize gamma_lut to a linear table for the legacy API below.
|
||||
* The modern property API resets to a linear/pass-thru table if blob_id
|
||||
* is 0, hence no PropertyBlob is created here.
|
||||
*/
|
||||
for (i = 0; i < 256; i++) {
|
||||
gamma_lut[i].red =
|
||||
gamma_lut[i].green =
|
||||
|
@ -1135,6 +1176,7 @@ static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
|
|||
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)) {
|
||||
/* If we can't add the GAMMA_LUT property, try the legacy API. */
|
||||
uint16_t r[256], g[256], b[256];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
|
@ -1144,7 +1186,7 @@ static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
|
|||
}
|
||||
|
||||
ret = drmModeCrtcSetGamma(dev->fd, crtc_id, 256, r, g, b);
|
||||
if (ret)
|
||||
if (ret && errno != ENOSYS)
|
||||
fprintf(stderr, "failed to set gamma: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
@ -1441,6 +1483,24 @@ static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool pipe_has_writeback_connector(struct device *dev, struct pipe_arg *pipes,
|
||||
unsigned int count)
|
||||
{
|
||||
drmModeConnector *connector;
|
||||
unsigned int i, j;
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
struct pipe_arg *pipe = &pipes[j];
|
||||
|
||||
for (i = 0; i < pipe->num_cons; i++) {
|
||||
connector = get_connector_by_id(dev, pipe->con_ids[i]);
|
||||
if (connector && connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int pipe_attempt_connector(struct device *dev, drmModeConnector *con,
|
||||
struct pipe_arg *pipe)
|
||||
{
|
||||
|
@ -1503,7 +1563,8 @@ static int pipe_find_preferred(struct device *dev, struct pipe_arg **out_pipes)
|
|||
|
||||
for (i = 0; i < res->count_connectors; i++) {
|
||||
con = res->connectors[i].connector;
|
||||
if (!con || con->connection != DRM_MODE_CONNECTED)
|
||||
if (!con || con->connection != DRM_MODE_CONNECTED ||
|
||||
con->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
continue;
|
||||
connected++;
|
||||
}
|
||||
|
@ -1550,32 +1611,35 @@ static struct plane *get_primary_plane_by_crtc(struct device *dev, struct crtc *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
|
||||
static unsigned int set_mode(struct device *dev, struct pipe_arg **pipe_args, unsigned int count)
|
||||
{
|
||||
unsigned int i, j;
|
||||
int ret, x = 0;
|
||||
int preferred = count == 0;
|
||||
struct pipe_arg *pipes;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct pipe_arg *pipe = &pipes[i];
|
||||
|
||||
ret = pipe_resolve_connectors(dev, pipe);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
ret = pipe_find_crtc_and_mode(dev, pipe);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
}
|
||||
if (preferred) {
|
||||
struct pipe_arg *pipe_args;
|
||||
|
||||
count = pipe_find_preferred(dev, &pipe_args);
|
||||
count = pipe_find_preferred(dev, pipe_args);
|
||||
if (!count) {
|
||||
fprintf(stderr, "can't find any preferred connector/mode.\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pipes = *pipe_args;
|
||||
} else {
|
||||
pipes = *pipe_args;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct pipe_arg *pipe = &pipes[i];
|
||||
|
||||
ret = pipe_resolve_connectors(dev, pipe);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
ret = pipe_find_crtc_and_mode(dev, pipe);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
}
|
||||
pipes = pipe_args;
|
||||
}
|
||||
|
||||
if (!dev->use_atomic) {
|
||||
|
@ -1602,7 +1666,7 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
|
|||
|
||||
if (bo_fb_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height,
|
||||
primary_fill, &dev->mode.bo, &dev->mode.fb_id))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
@ -1634,7 +1698,7 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
|
|||
|
||||
if (ret) {
|
||||
fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_gamma(dev, pipe->crtc_id, pipe->fourcc);
|
||||
|
@ -1660,6 +1724,77 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void writeback_config(struct device *dev, struct pipe_arg *pipes, unsigned int count)
|
||||
{
|
||||
drmModeConnector *connector;
|
||||
unsigned int i, j;
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
struct pipe_arg *pipe = &pipes[j];
|
||||
|
||||
for (i = 0; i < pipe->num_cons; i++) {
|
||||
connector = get_connector_by_id(dev, pipe->con_ids[i]);
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) {
|
||||
if (!pipe->mode) {
|
||||
fprintf(stderr, "no mode for writeback\n");
|
||||
return;
|
||||
}
|
||||
bo_fb_create(dev->fd, pipes[j].fourcc,
|
||||
pipe->mode->hdisplay, pipe->mode->vdisplay,
|
||||
UTIL_PATTERN_PLAIN,
|
||||
&pipe->out_bo, &pipe->out_fb_id);
|
||||
add_property(dev, pipe->con_ids[i], "WRITEBACK_FB_ID",
|
||||
pipe->out_fb_id);
|
||||
add_property(dev, pipe->con_ids[i], "WRITEBACK_OUT_FENCE_PTR",
|
||||
(uintptr_t)(&dev->writeback_fence_fd));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int poll_writeback_fence(int fd, int timeout)
|
||||
{
|
||||
struct pollfd fds = { fd, POLLIN };
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = poll(&fds, 1, timeout);
|
||||
if (ret > 0) {
|
||||
if (fds.revents & (POLLERR | POLLNVAL))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
} else if (ret == 0) {
|
||||
return -ETIMEDOUT;
|
||||
} else {
|
||||
ret = -errno;
|
||||
if (ret == -EINTR || ret == -EAGAIN)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
}
|
||||
|
||||
static void dump_output_fb(struct device *dev, struct pipe_arg *pipes, char *dump_path,
|
||||
unsigned int count)
|
||||
{
|
||||
drmModeConnector *connector;
|
||||
unsigned int i, j;
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
struct pipe_arg *pipe = &pipes[j];
|
||||
|
||||
for (i = 0; i < pipe->num_cons; i++) {
|
||||
connector = get_connector_by_id(dev, pipe->con_ids[i]);
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
bo_dump(pipe->out_bo, dump_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
|
||||
|
@ -1897,8 +2032,9 @@ static int parse_connector(struct pipe_arg *pipe, const char *arg)
|
|||
}
|
||||
|
||||
if (*p == '@') {
|
||||
strncpy(pipe->format_str, p + 1, 4);
|
||||
pipe->format_str[4] = '\0';
|
||||
len = sizeof(pipe->format_str) - 1;
|
||||
strncpy(pipe->format_str, p + 1, len);
|
||||
pipe->format_str[len] = '\0';
|
||||
}
|
||||
|
||||
pipe->fourcc = util_format_fourcc(pipe->format_str);
|
||||
|
@ -1912,6 +2048,7 @@ static int parse_connector(struct pipe_arg *pipe, const char *arg)
|
|||
|
||||
static int parse_plane(struct plane_arg *plane, const char *p)
|
||||
{
|
||||
unsigned int len;
|
||||
char *end;
|
||||
|
||||
plane->plane_id = strtoul(p, &end, 10);
|
||||
|
@ -1950,8 +2087,9 @@ static int parse_plane(struct plane_arg *plane, const char *p)
|
|||
}
|
||||
|
||||
if (*end == '@') {
|
||||
strncpy(plane->format_str, end + 1, 4);
|
||||
plane->format_str[4] = '\0';
|
||||
len = sizeof(plane->format_str) - 1;
|
||||
strncpy(plane->format_str, end + 1, len);
|
||||
plane->format_str[len] = '\0';
|
||||
} else {
|
||||
strcpy(plane->format_str, "XR24");
|
||||
}
|
||||
|
@ -1990,7 +2128,7 @@ static void parse_fill_patterns(char *arg)
|
|||
|
||||
static void usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-acDdefMPpsCvrw]\n", name);
|
||||
fprintf(stderr, "usage: %s [-acDdefMoPpsCvrw]\n", name);
|
||||
|
||||
fprintf(stderr, "\n Query options:\n\n");
|
||||
fprintf(stderr, "\t-c\tlist connectors\n");
|
||||
|
@ -1999,14 +2137,19 @@ static void usage(char *name)
|
|||
fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
|
||||
|
||||
fprintf(stderr, "\n Test options:\n\n");
|
||||
fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n");
|
||||
fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>]\tset a mode\n");
|
||||
fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane, see 'plane-topology'\n");
|
||||
fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:mode[@<format>]\tset a mode, see 'mode-topology'\n");
|
||||
fprintf(stderr, "\t\twhere mode can be specified as:\n");
|
||||
fprintf(stderr, "\t\t<hdisp>x<vdisp>[-<vrefresh>]\n");
|
||||
fprintf(stderr, "\t\t<hdisp>,<hss>,<hse>,<htot>,<vdisp>,<vss>,<vse>,<vtot>-<vrefresh>\n");
|
||||
fprintf(stderr, "\t\t#<mode index>\n");
|
||||
fprintf(stderr, "\t-C\ttest hw cursor\n");
|
||||
fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
|
||||
fprintf(stderr, "\t-r\tset the preferred mode for all connectors\n");
|
||||
fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
|
||||
fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property, see 'property'\n");
|
||||
fprintf(stderr, "\t-a \tuse atomic API\n");
|
||||
fprintf(stderr, "\t-F pattern1,pattern2\tspecify fill patterns\n");
|
||||
fprintf(stderr, "\t-o <desired file path> \t Dump writeback output buffer to file\n");
|
||||
|
||||
fprintf(stderr, "\n Generic options:\n\n");
|
||||
fprintf(stderr, "\t-d\tdrop master after mode set\n");
|
||||
|
@ -2014,10 +2157,29 @@ static void usage(char *name)
|
|||
fprintf(stderr, "\t-D device\tuse the given device\n");
|
||||
|
||||
fprintf(stderr, "\n\tDefault is to dump all info.\n");
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Plane Topology is defined as:\n");
|
||||
fprintf(stderr, "\tplane-topology\t::= plane-id '@' crtc-id ':' width 'x' height ( <plane-offsets> )? ;\n");
|
||||
fprintf(stderr, "\tplane-offsets\t::= '+' x-offset '+' y-offset ( <plane-scale> )? ;\n");
|
||||
fprintf(stderr, "\tplane-scale\t::= '*' scale ( <plane-format> )? ;\n");
|
||||
fprintf(stderr, "\tplane-format\t::= '@' format ;\n");
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Mode Topology is defined as:\n");
|
||||
fprintf(stderr, "\tmode-topology\t::= connector-id ( ',' connector-id )* ( '@' crtc-id )? ':' <mode-selection> ( '@' format )? ;\n");
|
||||
fprintf(stderr, "\tmode-selection\t::= <indexed-mode> | <named-mode> | <custom-mode> ;\n");
|
||||
fprintf(stderr, "\tindexed-mode\t::= '#' mode-index ;\n");
|
||||
fprintf(stderr, "\tnamed-mode\t::= width 'x' height ( '-' vrefresh )? ;\n");
|
||||
fprintf(stderr, "\tcustom-mode\t::= hdisplay ',' hsyncstart ',' hsyncend ',' htotal ',' vdisplay ',' vsyncstart ',' vsyncend ',' vtotal '-' vrefresh ;\n");
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Property is defined as:\n");
|
||||
fprintf(stderr, "\tproperty\t::= object-id ':' property-name ':' value ;\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static char optstr[] = "acdD:efF:M:P:ps:Cvrw:";
|
||||
static char optstr[] = "acdD:efF:M:P:ps:Cvrw:o:";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
@ -2040,6 +2202,7 @@ int main(int argc, char **argv)
|
|||
struct property_arg *prop_args = NULL;
|
||||
unsigned int args = 0;
|
||||
int ret;
|
||||
char *dump_path = NULL;
|
||||
|
||||
memset(&dev, 0, sizeof dev);
|
||||
|
||||
|
@ -2078,6 +2241,9 @@ int main(int argc, char **argv)
|
|||
/* Preserve the default behaviour of dumping all information. */
|
||||
args--;
|
||||
break;
|
||||
case 'o':
|
||||
dump_path = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
plane_args = realloc(plane_args,
|
||||
(plane_count + 1) * sizeof *plane_args);
|
||||
|
@ -2143,8 +2309,8 @@ int main(int argc, char **argv)
|
|||
if (!args)
|
||||
encoders = connectors = crtcs = planes = framebuffers = 1;
|
||||
|
||||
if (test_vsync && !count) {
|
||||
fprintf(stderr, "page flipping requires at least one -s option.\n");
|
||||
if (test_vsync && !count && !set_preferred) {
|
||||
fprintf(stderr, "page flipping requires at least one -s or -r option.\n");
|
||||
return -1;
|
||||
}
|
||||
if (set_preferred && count) {
|
||||
|
@ -2152,17 +2318,13 @@ int main(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (set_preferred && plane_count) {
|
||||
fprintf(stderr, "cannot use -r (preferred) when -P (plane) is set\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev.fd = util_open(device, module);
|
||||
if (dev.fd < 0)
|
||||
return -1;
|
||||
|
||||
if (use_atomic) {
|
||||
ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
||||
drmSetClientCap(dev.fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
|
||||
if (ret) {
|
||||
fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
|
||||
drmClose(dev.fd);
|
||||
|
@ -2186,12 +2348,13 @@ int main(int argc, char **argv)
|
|||
dump_resource(&dev, planes);
|
||||
dump_resource(&dev, framebuffers);
|
||||
|
||||
if (dev.use_atomic)
|
||||
dev.req = drmModeAtomicAlloc();
|
||||
|
||||
for (i = 0; i < prop_count; ++i)
|
||||
set_property(&dev, &prop_args[i]);
|
||||
|
||||
if (dev.use_atomic) {
|
||||
dev.req = drmModeAtomicAlloc();
|
||||
|
||||
if (set_preferred || (count && plane_count)) {
|
||||
uint64_t cap = 0;
|
||||
|
||||
|
@ -2202,7 +2365,16 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (set_preferred || count)
|
||||
set_mode(&dev, pipe_args, count);
|
||||
count = set_mode(&dev, &pipe_args, count);
|
||||
|
||||
if (dump_path) {
|
||||
if (!pipe_has_writeback_connector(&dev, pipe_args, count)) {
|
||||
fprintf(stderr, "No writeback connector found, can not dump.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
writeback_config(&dev, pipe_args, count);
|
||||
}
|
||||
|
||||
if (plane_count)
|
||||
atomic_set_planes(&dev, plane_args, plane_count, false);
|
||||
|
@ -2213,6 +2385,18 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since only writeback connectors have an output fb, this should only be
|
||||
* called for writeback.
|
||||
*/
|
||||
if (dump_path) {
|
||||
ret = poll_writeback_fence(dev.writeback_fence_fd, 1000);
|
||||
if (ret)
|
||||
fprintf(stderr, "Poll for writeback error: %d. Skipping Dump.\n",
|
||||
ret);
|
||||
dump_output_fb(&dev, pipe_args, dump_path, count);
|
||||
}
|
||||
|
||||
if (test_vsync)
|
||||
atomic_test_page_flip(&dev, pipe_args, plane_args, plane_count);
|
||||
|
||||
|
@ -2230,17 +2414,22 @@ int main(int argc, char **argv)
|
|||
|
||||
if (count)
|
||||
atomic_clear_mode(&dev, pipe_args, count);
|
||||
|
||||
ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
|
||||
if (ret)
|
||||
fprintf(stderr, "Atomic Commit failed\n");
|
||||
|
||||
if (plane_count)
|
||||
atomic_clear_FB(&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");
|
||||
|
||||
if (count && plane_count)
|
||||
atomic_clear_FB(&dev, plane_args, plane_count);
|
||||
|
||||
drmModeAtomicFree(dev.req);
|
||||
} else {
|
||||
if (dump_path) {
|
||||
fprintf(stderr, "writeback / dump is only supported in atomic mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (set_preferred || count || plane_count) {
|
||||
uint64_t cap = 0;
|
||||
|
||||
|
@ -2251,7 +2440,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (set_preferred || count)
|
||||
set_mode(&dev, pipe_args, count);
|
||||
count = set_mode(&dev, &pipe_args, count);
|
||||
|
||||
if (plane_count)
|
||||
set_planes(&dev, plane_args, plane_count);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue