diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2016-03-20 10:20:15 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2016-03-20 10:20:15 +0000 |
commit | 463789b8671482b661f77e2cebfb7be3bda94309 (patch) | |
tree | febd90adea88473ce0558056b04ab792c26eb20d /lib | |
parent | 7566c3dace59661ce2bb9d4aa5de5552101e61f8 (diff) |
Import libdrm 2.4.67
Diffstat (limited to 'lib')
92 files changed, 9247 insertions, 1721 deletions
diff --git a/lib/libdrm/Android.mk b/lib/libdrm/Android.mk index 90cdcb323..1d8cd6517 100644 --- a/lib/libdrm/Android.mk +++ b/lib/libdrm/Android.mk @@ -27,6 +27,8 @@ include $(CLEAR_VARS) # Import variables LIBDRM_{,H_,INCLUDE_H_,INCLUDE_VMWGFX_H_}FILES include $(LOCAL_PATH)/Makefile.sources +#static library for the device (recovery) +include $(CLEAR_VARS) LOCAL_MODULE := libdrm LOCAL_MODULE_TAGS := optional @@ -41,7 +43,24 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DHAVE_VISIBILITY=1 \ -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1 +include $(BUILD_STATIC_LIBRARY) + +# Shared library for the device +include $(CLEAR_VARS) +LOCAL_MODULE := libdrm +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := $(LIBDRM_FILES) +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/include/drm + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include/drm + +LOCAL_CFLAGS := \ + -DHAVE_VISIBILITY=1 \ + -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1 include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/lib/libdrm/Makefile.sources b/lib/libdrm/Makefile.sources index a77f48dee..1a1f0fecb 100644 --- a/lib/libdrm/Makefile.sources +++ b/lib/libdrm/Makefile.sources @@ -32,6 +32,7 @@ LIBDRM_INCLUDE_H_FILES := \ include/drm/savage_drm.h \ include/drm/sis_drm.h \ include/drm/tegra_drm.h \ + include/drm/vc4_drm.h \ include/drm/via_drm.h LIBDRM_INCLUDE_VMWGFX_H_FILES := \ diff --git a/lib/libdrm/amdgpu/amdgpu-symbol-check b/lib/libdrm/amdgpu/amdgpu-symbol-check index 9a0b36cb3..648db9b6c 100755 --- a/lib/libdrm/amdgpu/amdgpu-symbol-check +++ b/lib/libdrm/amdgpu/amdgpu-symbol-check @@ -24,11 +24,15 @@ amdgpu_bo_set_metadata amdgpu_bo_va_op amdgpu_bo_wait_for_idle amdgpu_create_bo_from_user_mem +amdgpu_cs_create_semaphore amdgpu_cs_ctx_create amdgpu_cs_ctx_free +amdgpu_cs_destroy_semaphore amdgpu_cs_query_fence_status amdgpu_cs_query_reset_state +amdgpu_cs_signal_semaphore amdgpu_cs_submit +amdgpu_cs_wait_semaphore amdgpu_device_deinitialize amdgpu_device_initialize amdgpu_query_buffer_size_alignment diff --git a/lib/libdrm/amdgpu/amdgpu.h b/lib/libdrm/amdgpu/amdgpu.h index e44d802b3..08513061e 100644 --- a/lib/libdrm/amdgpu/amdgpu.h +++ b/lib/libdrm/amdgpu/amdgpu.h @@ -124,6 +124,11 @@ typedef struct amdgpu_bo_list *amdgpu_bo_list_handle; */ typedef struct amdgpu_va *amdgpu_va_handle; +/** + * Define handle for semaphore + */ +typedef struct amdgpu_semaphore *amdgpu_semaphore_handle; + /*--------------------------------------------------------------------------*/ /* -------------------------- Structures ---------------------------------- */ /*--------------------------------------------------------------------------*/ @@ -1180,4 +1185,64 @@ int amdgpu_bo_va_op(amdgpu_bo_handle bo, uint64_t flags, uint32_t ops); +/** + * create semaphore + * + * \param sem - \c [out] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem); + +/** + * signal semaphore + * + * \param context - \c [in] GPU Context + * \param ip_type - \c [in] Hardware IP block type = AMDGPU_HW_IP_* + * \param ip_instance - \c [in] Index of the IP block of the same type + * \param ring - \c [in] Specify ring index of the IP + * \param sem - \c [in] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem); + +/** + * wait semaphore + * + * \param context - \c [in] GPU Context + * \param ip_type - \c [in] Hardware IP block type = AMDGPU_HW_IP_* + * \param ip_instance - \c [in] Index of the IP block of the same type + * \param ring - \c [in] Specify ring index of the IP + * \param sem - \c [in] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem); + +/** + * destroy semaphore + * + * \param sem - \c [in] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem); + #endif /* #ifdef _AMDGPU_H_ */ diff --git a/lib/libdrm/amdgpu/amdgpu_cs.c b/lib/libdrm/amdgpu/amdgpu_cs.c index 4da982144..fb5b3a8c4 100644 --- a/lib/libdrm/amdgpu/amdgpu_cs.c +++ b/lib/libdrm/amdgpu/amdgpu_cs.c @@ -40,6 +40,9 @@ #include "amdgpu_drm.h" #include "amdgpu_internal.h" +static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem); +static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem); + /** * Create command submission context * @@ -53,6 +56,7 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, { struct amdgpu_context *gpu_context; union drm_amdgpu_ctx args; + int i, j, k; int r; if (NULL == dev) @@ -66,6 +70,10 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, gpu_context->dev = dev; + r = pthread_mutex_init(&gpu_context->sequence_mutex, NULL); + if (r) + goto error; + /* Create the context */ memset(&args, 0, sizeof(args)); args.in.op = AMDGPU_CTX_OP_ALLOC_CTX; @@ -74,11 +82,16 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, goto error; gpu_context->id = args.out.alloc.ctx_id; + for (i = 0; i < AMDGPU_HW_IP_NUM; i++) + for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) + for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) + list_inithead(&gpu_context->sem_list[i][j][k]); *context = (amdgpu_context_handle)gpu_context; return 0; error: + pthread_mutex_destroy(&gpu_context->sequence_mutex); free(gpu_context); return r; } @@ -94,18 +107,32 @@ error: int amdgpu_cs_ctx_free(amdgpu_context_handle context) { union drm_amdgpu_ctx args; + int i, j, k; int r; if (NULL == context) return -EINVAL; + pthread_mutex_destroy(&context->sequence_mutex); + /* now deal with kernel side */ memset(&args, 0, sizeof(args)); args.in.op = AMDGPU_CTX_OP_FREE_CTX; args.in.ctx_id = context->id; r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, &args, sizeof(args)); - + for (i = 0; i < AMDGPU_HW_IP_NUM; i++) { + for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) { + for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) { + amdgpu_semaphore_handle sem; + LIST_FOR_EACH_ENTRY(sem, &context->sem_list[i][j][k], list) { + list_del(&sem->list); + amdgpu_cs_reset_sem(sem); + amdgpu_cs_unreference_sem(sem); + } + } + } + } free(context); return r; @@ -150,7 +177,10 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, struct drm_amdgpu_cs_chunk *chunks; struct drm_amdgpu_cs_chunk_data *chunk_data; struct drm_amdgpu_cs_chunk_dep *dependencies = NULL; - uint32_t i, size; + struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL; + struct list_head *sem_list; + amdgpu_semaphore_handle sem, tmp; + uint32_t i, size, sem_count = 0; bool user_fence; int r = 0; @@ -160,9 +190,13 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, return -EINVAL; if (ibs_request->number_of_ibs > AMDGPU_CS_MAX_IBS_PER_SUBMIT) return -EINVAL; + if (ibs_request->number_of_ibs == 0) { + ibs_request->seq_no = AMDGPU_NULL_SUBMIT_SEQ; + return 0; + } user_fence = (ibs_request->fence_info.handle != NULL); - size = ibs_request->number_of_ibs + (user_fence ? 2 : 1); + size = ibs_request->number_of_ibs + (user_fence ? 2 : 1) + 1; chunk_array = alloca(sizeof(uint64_t) * size); chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size); @@ -196,6 +230,8 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, chunk_data[i].ib_data.flags = ib->flags; } + pthread_mutex_lock(&context->sequence_mutex); + if (user_fence) { i = cs.in.num_chunks++; @@ -240,15 +276,49 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies; } + sem_list = &context->sem_list[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring]; + LIST_FOR_EACH_ENTRY(sem, sem_list, list) + sem_count++; + if (sem_count) { + sem_dependencies = malloc(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_count); + if (!sem_dependencies) { + r = -ENOMEM; + goto error_unlock; + } + sem_count = 0; + LIST_FOR_EACH_ENTRY_SAFE(sem, tmp, sem_list, list) { + struct amdgpu_cs_fence *info = &sem->signal_fence; + struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++]; + dep->ip_type = info->ip_type; + dep->ip_instance = info->ip_instance; + dep->ring = info->ring; + dep->ctx_id = info->context->id; + dep->handle = info->fence; + + list_del(&sem->list); + amdgpu_cs_reset_sem(sem); + amdgpu_cs_unreference_sem(sem); + } + i = cs.in.num_chunks++; + + /* dependencies chunk */ + chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i]; + chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES; + chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count; + chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies; + } + r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CS, &cs, sizeof(cs)); if (r) goto error_unlock; ibs_request->seq_no = cs.out.handle; - + context->last_seq[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring] = ibs_request->seq_no; error_unlock: + pthread_mutex_unlock(&context->sequence_mutex); free(dependencies); + free(sem_dependencies); return r; } @@ -289,12 +359,18 @@ drm_private uint64_t amdgpu_cs_calculate_timeout(uint64_t timeout) if (timeout != AMDGPU_TIMEOUT_INFINITE) { struct timespec current; + uint64_t current_ns; r = clock_gettime(CLOCK_MONOTONIC, ¤t); - if (r) - return r; + if (r) { + fprintf(stderr, "clock_gettime() returned error (%d)!", errno); + return AMDGPU_TIMEOUT_INFINITE; + } - timeout += ((uint64_t)current.tv_sec) * 1000000000ull; - timeout += current.tv_nsec; + current_ns = ((uint64_t)current.tv_sec) * 1000000000ull; + current_ns += current.tv_nsec; + timeout += current_ns; + if (timeout < current_ns) + timeout = AMDGPU_TIMEOUT_INFINITE; } return timeout; } @@ -350,6 +426,10 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, return -EINVAL; if (fence->ring >= AMDGPU_CS_MAX_RINGS) return -EINVAL; + if (fence->fence == AMDGPU_NULL_SUBMIT_SEQ) { + *expired = true; + return 0; + } *expired = false; @@ -363,3 +443,102 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, return r; } +int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem) +{ + struct amdgpu_semaphore *gpu_semaphore; + + if (NULL == sem) + return -EINVAL; + + gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore)); + if (NULL == gpu_semaphore) + return -ENOMEM; + + atomic_set(&gpu_semaphore->refcount, 1); + *sem = gpu_semaphore; + + return 0; +} + +int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem) +{ + if (NULL == ctx) + return -EINVAL; + if (ip_type >= AMDGPU_HW_IP_NUM) + return -EINVAL; + if (ring >= AMDGPU_CS_MAX_RINGS) + return -EINVAL; + if (NULL == sem) + return -EINVAL; + /* sem has been signaled */ + if (sem->signal_fence.context) + return -EINVAL; + pthread_mutex_lock(&ctx->sequence_mutex); + sem->signal_fence.context = ctx; + sem->signal_fence.ip_type = ip_type; + sem->signal_fence.ip_instance = ip_instance; + sem->signal_fence.ring = ring; + sem->signal_fence.fence = ctx->last_seq[ip_type][ip_instance][ring]; + update_references(NULL, &sem->refcount); + pthread_mutex_unlock(&ctx->sequence_mutex); + return 0; +} + +int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem) +{ + if (NULL == ctx) + return -EINVAL; + if (ip_type >= AMDGPU_HW_IP_NUM) + return -EINVAL; + if (ring >= AMDGPU_CS_MAX_RINGS) + return -EINVAL; + if (NULL == sem) + return -EINVAL; + /* must signal first */ + if (NULL == sem->signal_fence.context) + return -EINVAL; + + pthread_mutex_lock(&ctx->sequence_mutex); + list_add(&sem->list, &ctx->sem_list[ip_type][ip_instance][ring]); + pthread_mutex_unlock(&ctx->sequence_mutex); + return 0; +} + +static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem) +{ + if (NULL == sem) + return -EINVAL; + if (NULL == sem->signal_fence.context) + return -EINVAL; + + sem->signal_fence.context = NULL;; + sem->signal_fence.ip_type = 0; + sem->signal_fence.ip_instance = 0; + sem->signal_fence.ring = 0; + sem->signal_fence.fence = 0; + + return 0; +} + +static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem) +{ + if (NULL == sem) + return -EINVAL; + + if (update_references(&sem->refcount, NULL)) + free(sem); + return 0; +} + +int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem) +{ + return amdgpu_cs_unreference_sem(sem); +} diff --git a/lib/libdrm/amdgpu/amdgpu_internal.h b/lib/libdrm/amdgpu/amdgpu_internal.h index 7dd5c1c72..4f039b68f 100644 --- a/lib/libdrm/amdgpu/amdgpu_internal.h +++ b/lib/libdrm/amdgpu/amdgpu_internal.h @@ -44,6 +44,7 @@ #define ROUND_DOWN(x, y) ((x) & ~__round_mask(x, y)) #define AMDGPU_INVALID_VA_ADDRESS 0xffffffffffffffff +#define AMDGPU_NULL_SUBMIT_SEQ 0 struct amdgpu_bo_va_hole { struct list_head list; @@ -111,8 +112,23 @@ struct amdgpu_bo_list { struct amdgpu_context { struct amdgpu_device *dev; + /** Mutex for accessing fences and to maintain command submissions + in good sequence. */ + pthread_mutex_t sequence_mutex; /* context id*/ uint32_t id; + uint64_t last_seq[AMDGPU_HW_IP_NUM][AMDGPU_HW_IP_INSTANCE_MAX_COUNT][AMDGPU_CS_MAX_RINGS]; + struct list_head sem_list[AMDGPU_HW_IP_NUM][AMDGPU_HW_IP_INSTANCE_MAX_COUNT][AMDGPU_CS_MAX_RINGS]; +}; + +/** + * Structure describing sw semaphore based on scheduler + * + */ +struct amdgpu_semaphore { + atomic_t refcount; + struct list_head list; + struct amdgpu_cs_fence signal_fence; }; /** diff --git a/lib/libdrm/amdgpu/amdgpu_vamgr.c b/lib/libdrm/amdgpu/amdgpu_vamgr.c index 04d288179..8a707cbcd 100644 --- a/lib/libdrm/amdgpu/amdgpu_vamgr.c +++ b/lib/libdrm/amdgpu/amdgpu_vamgr.c @@ -57,8 +57,8 @@ drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) { - struct amdgpu_bo_va_hole *hole; - LIST_FOR_EACH_ENTRY(hole, &mgr->va_holes, list) { + struct amdgpu_bo_va_hole *hole, *tmp; + LIST_FOR_EACH_ENTRY_SAFE(hole, tmp, &mgr->va_holes, list) { list_del(&hole->list); free(hole); } @@ -124,8 +124,10 @@ amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, } if (base_required) { - if (base_required < mgr->va_offset) + if (base_required < mgr->va_offset) { + pthread_mutex_unlock(&mgr->bo_va_mutex); return AMDGPU_INVALID_VA_ADDRESS; + } offset = mgr->va_offset; waste = base_required - mgr->va_offset; } else { diff --git a/lib/libdrm/amdgpu/libdrm_amdgpu.pc.in b/lib/libdrm/amdgpu/libdrm_amdgpu.pc.in index 417865e57..f1c552a62 100644 --- a/lib/libdrm/amdgpu/libdrm_amdgpu.pc.in +++ b/lib/libdrm/amdgpu/libdrm_amdgpu.pc.in @@ -8,3 +8,4 @@ Description: Userspace interface to kernel DRM services for amdgpu Version: @PACKAGE_VERSION@ Libs: -L${libdir} -ldrm_amdgpu Cflags: -I${includedir} -I${includedir}/libdrm +Requires.private: libdrm diff --git a/lib/libdrm/exynos/exynos-symbol-check b/lib/libdrm/exynos/exynos-symbol-check index 1a1be89ea..9692caa68 100755 --- a/lib/libdrm/exynos/exynos-symbol-check +++ b/lib/libdrm/exynos/exynos-symbol-check @@ -22,12 +22,15 @@ exynos_device_destroy exynos_prime_fd_to_handle exynos_prime_handle_to_fd exynos_vidi_connection +exynos_handle_event g2d_blend g2d_copy g2d_copy_with_scale g2d_exec +g2d_config_event g2d_fini g2d_init +g2d_move g2d_scale_and_blend g2d_solid_fill EOF diff --git a/lib/libdrm/exynos/exynos_drm.c b/lib/libdrm/exynos/exynos_drm.c index df9b8ed4d..e689781da 100644 --- a/lib/libdrm/exynos/exynos_drm.c +++ b/lib/libdrm/exynos/exynos_drm.c @@ -32,6 +32,7 @@ #include <stdio.h> #include <string.h> #include <errno.h> +#include <unistd.h> #include <sys/mman.h> #include <linux/stddef.h> @@ -42,6 +43,8 @@ #include "exynos_drm.h" #include "exynos_drmif.h" +#define U642VOID(x) ((void *)(unsigned long)(x)) + /* * Create exynos drm device object. * @@ -374,3 +377,76 @@ exynos_vidi_connection(struct exynos_device *dev, uint32_t connect, return 0; } + +static void +exynos_handle_vendor(int fd, struct drm_event *e, void *ctx) +{ + struct drm_exynos_g2d_event *g2d; + struct exynos_event_context *ectx = ctx; + + switch (e->type) { + case DRM_EXYNOS_G2D_EVENT: + if (ectx->version < 1 || ectx->g2d_event_handler == NULL) + break; + g2d = (struct drm_exynos_g2d_event *)e; + ectx->g2d_event_handler(fd, g2d->cmdlist_no, g2d->tv_sec, + g2d->tv_usec, U642VOID(g2d->user_data)); + break; + + default: + break; + } +} + +int +exynos_handle_event(struct exynos_device *dev, struct exynos_event_context *ctx) +{ + char buffer[1024]; + int len, i; + struct drm_event *e; + struct drm_event_vblank *vblank; + drmEventContextPtr evctx = &ctx->base; + + /* The DRM read semantics guarantees that we always get only + * complete events. */ + len = read(dev->fd, buffer, sizeof buffer); + if (len == 0) + return 0; + if (len < (int)sizeof *e) + return -1; + + i = 0; + while (i < len) { + e = (struct drm_event *) &buffer[i]; + switch (e->type) { + case DRM_EVENT_VBLANK: + if (evctx->version < 1 || + evctx->vblank_handler == NULL) + break; + vblank = (struct drm_event_vblank *) e; + evctx->vblank_handler(dev->fd, + vblank->sequence, + vblank->tv_sec, + vblank->tv_usec, + U642VOID (vblank->user_data)); + break; + case DRM_EVENT_FLIP_COMPLETE: + if (evctx->version < 2 || + evctx->page_flip_handler == NULL) + break; + vblank = (struct drm_event_vblank *) e; + evctx->page_flip_handler(dev->fd, + vblank->sequence, + vblank->tv_sec, + vblank->tv_usec, + U642VOID (vblank->user_data)); + break; + default: + exynos_handle_vendor(dev->fd, e, evctx); + break; + } + i += e->length; + } + + return 0; +} diff --git a/lib/libdrm/exynos/exynos_drm.h b/lib/libdrm/exynos/exynos_drm.h index 256c02f02..c3af0ac5f 100644 --- a/lib/libdrm/exynos/exynos_drm.h +++ b/lib/libdrm/exynos/exynos_drm.h @@ -157,4 +157,16 @@ struct drm_exynos_g2d_exec { #define DRM_IOCTL_EXYNOS_G2D_EXEC DRM_IOWR(DRM_COMMAND_BASE + \ DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec) +/* EXYNOS specific events */ +#define DRM_EXYNOS_G2D_EVENT 0x80000000 + +struct drm_exynos_g2d_event { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 cmdlist_no; + __u32 reserved; +}; + #endif diff --git a/lib/libdrm/exynos/exynos_drmif.h b/lib/libdrm/exynos/exynos_drmif.h index c7c1d442b..626e39985 100644 --- a/lib/libdrm/exynos/exynos_drmif.h +++ b/lib/libdrm/exynos/exynos_drmif.h @@ -54,6 +54,25 @@ struct exynos_bo { uint32_t name; }; +#define EXYNOS_EVENT_CONTEXT_VERSION 1 + +/* + * Exynos Event Context structure. + * + * @base: base context (for core events). + * @version: version info similar to the one in 'drmEventContext'. + * @g2d_event_handler: handler for G2D events. + */ +struct exynos_event_context { + drmEventContext base; + + int version; + + void (*g2d_event_handler)(int fd, unsigned int cmdlist_no, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data); +}; + /* * device related functions: */ @@ -83,4 +102,11 @@ int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect, uint32_t ext, void *edid); +/* + * event handling related functions: + */ +int exynos_handle_event(struct exynos_device *dev, + struct exynos_event_context *ctx); + + #endif /* EXYNOS_DRMIF_H_ */ diff --git a/lib/libdrm/exynos/exynos_fimg2d.c b/lib/libdrm/exynos/exynos_fimg2d.c index 24a06d0fe..7f1d105a5 100644 --- a/lib/libdrm/exynos/exynos_fimg2d.c +++ b/lib/libdrm/exynos/exynos_fimg2d.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <string.h> #include <errno.h> +#include <assert.h> #include <sys/mman.h> #include <linux/stddef.h> @@ -41,11 +42,67 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MSG_PREFIX "exynos/fimg2d: " + +#define G2D_MAX_CMD_NR 64 +#define G2D_MAX_GEM_CMD_NR 64 +#define G2D_MAX_CMD_LIST_NR 64 + +struct g2d_context { + int fd; + unsigned int major; + unsigned int minor; + struct drm_exynos_g2d_cmd cmd[G2D_MAX_CMD_NR]; + struct drm_exynos_g2d_cmd cmd_buf[G2D_MAX_GEM_CMD_NR]; + unsigned int cmd_nr; + unsigned int cmd_buf_nr; + unsigned int cmdlist_nr; + void *event_userdata; +}; + enum g2d_base_addr_reg { g2d_dst = 0, g2d_src }; +enum e_g2d_dir_mode { + G2D_DIR_MODE_POSITIVE = 0, + G2D_DIR_MODE_NEGATIVE = 1 +}; + +union g2d_direction_val { + unsigned int val[2]; + struct { + /* SRC_MSK_DIRECT_REG [0:1] (source) */ + enum e_g2d_dir_mode src_x_direction:1; + enum e_g2d_dir_mode src_y_direction:1; + + /* SRC_MSK_DIRECT_REG [2:3] */ + unsigned int reversed1:2; + + /* SRC_MSK_DIRECT_REG [4:5] (mask) */ + enum e_g2d_dir_mode mask_x_direction:1; + enum e_g2d_dir_mode mask_y_direction:1; + + /* SRC_MSK_DIRECT_REG [6:31] */ + unsigned int padding1:26; + + /* DST_PAT_DIRECT_REG [0:1] (destination) */ + enum e_g2d_dir_mode dst_x_direction:1; + enum e_g2d_dir_mode dst_y_direction:1; + + /* DST_PAT_DIRECT_REG [2:3] */ + unsigned int reversed2:2; + + /* DST_PAT_DIRECT_REG [4:5] (pattern) */ + enum e_g2d_dir_mode pat_x_direction:1; + enum e_g2d_dir_mode pat_y_direction:1; + + /* DST_PAT_DIRECT_REG [6:31] */ + unsigned int padding2:26; + } data; +}; + static unsigned int g2d_get_scaling(unsigned int src, unsigned int dst) { /* @@ -64,6 +121,11 @@ static unsigned int g2d_get_blend_op(enum e_g2d_op op) val.val = 0; + /* + * The switch statement is missing the default branch since + * we assume that the caller checks the blending operation + * via g2d_validate_blending_op() first. + */ switch (op) { case G2D_OP_CLEAR: case G2D_OP_DISJOINT_CLEAR: @@ -91,24 +153,87 @@ static unsigned int g2d_get_blend_op(enum e_g2d_op op) SET_BF(val, G2D_COEFF_MODE_SRC_ALPHA, 0, 0, 0, G2D_COEFF_MODE_SRC_ALPHA, 1, 0, 0); break; - default: - fprintf(stderr, "Not support operation(%d).\n", op); - SET_BF(val, G2D_COEFF_MODE_ONE, 0, 0, 0, G2D_COEFF_MODE_ZERO, - 0, 0, 0); - break; } return val.val; } /* + * g2d_check_space - check if command buffers have enough space left. + * + * @ctx: a pointer to g2d_context structure. + * @num_cmds: number of (regular) commands. + * @num_gem_cmds: number of GEM commands. + */ +static unsigned int g2d_check_space(const struct g2d_context *ctx, + unsigned int num_cmds, unsigned int num_gem_cmds) +{ + if (ctx->cmd_nr + num_cmds >= G2D_MAX_CMD_NR || + ctx->cmd_buf_nr + num_gem_cmds >= G2D_MAX_GEM_CMD_NR) + return 1; + else + return 0; +} + +/* + * g2d_validate_select_mode - validate select mode. + * + * @mode: the mode to validate + * + * Returns zero for an invalid mode and one otherwise. + */ +static int g2d_validate_select_mode( + enum e_g2d_select_mode mode) +{ + switch (mode) { + case G2D_SELECT_MODE_NORMAL: + case G2D_SELECT_MODE_FGCOLOR: + case G2D_SELECT_MODE_BGCOLOR: + return 1; + } + + return 0; +} + +/* + * g2d_validate_blending_op - validate blending operation. + * + * @operation: the operation to validate + * + * Returns zero for an invalid mode and one otherwise. + */ +static int g2d_validate_blending_op( + enum e_g2d_op operation) +{ + switch (operation) { + case G2D_OP_CLEAR: + case G2D_OP_SRC: + case G2D_OP_DST: + case G2D_OP_OVER: + case G2D_OP_INTERPOLATE: + case G2D_OP_DISJOINT_CLEAR: + case G2D_OP_DISJOINT_SRC: + case G2D_OP_DISJOINT_DST: + case G2D_OP_CONJOINT_CLEAR: + case G2D_OP_CONJOINT_SRC: + case G2D_OP_CONJOINT_DST: + return 1; + } + + return 0; +} + +/* * g2d_add_cmd - set given command and value to user side command buffer. * * @ctx: a pointer to g2d_context structure. * @cmd: command data. * @value: value data. + * + * The caller has to make sure that the commands buffers have enough space + * left to hold the command. Use g2d_check_space() to ensure this. */ -static int g2d_add_cmd(struct g2d_context *ctx, unsigned long cmd, +static void g2d_add_cmd(struct g2d_context *ctx, unsigned long cmd, unsigned long value) { switch (cmd & ~(G2D_BUF_USERPTR)) { @@ -118,28 +243,20 @@ static int g2d_add_cmd(struct g2d_context *ctx, unsigned long cmd, case DST_PLANE2_BASE_ADDR_REG: case PAT_BASE_ADDR_REG: case MASK_BASE_ADDR_REG: - if (ctx->cmd_buf_nr >= G2D_MAX_GEM_CMD_NR) { - fprintf(stderr, "Overflow cmd_gem size.\n"); - return -EINVAL; - } + assert(ctx->cmd_buf_nr < G2D_MAX_GEM_CMD_NR); ctx->cmd_buf[ctx->cmd_buf_nr].offset = cmd; ctx->cmd_buf[ctx->cmd_buf_nr].data = value; ctx->cmd_buf_nr++; break; default: - if (ctx->cmd_nr >= G2D_MAX_CMD_NR) { - fprintf(stderr, "Overflow cmd size.\n"); - return -EINVAL; - } + assert(ctx->cmd_nr < G2D_MAX_CMD_NR); ctx->cmd[ctx->cmd_nr].offset = cmd; ctx->cmd[ctx->cmd_nr].data = value; ctx->cmd_nr++; break; } - - return 0; } /* @@ -163,6 +280,19 @@ static void g2d_add_base_addr(struct g2d_context *ctx, struct g2d_image *img, } /* + * g2d_set_direction - setup direction register (useful for overlapping blits). + * + * @ctx: a pointer to g2d_context structure. + * @dir: a pointer to the g2d_direction_val structure. + */ +static void g2d_set_direction(struct g2d_context *ctx, + const union g2d_direction_val *dir) +{ + g2d_add_cmd(ctx, SRC_MASK_DIRECT_REG, dir->val[0]); + g2d_add_cmd(ctx, DST_PAT_DIRECT_REG, dir->val[1]); +} + +/* * g2d_reset - reset fimg2d hardware. * * @ctx: a pointer to g2d_context structure. @@ -191,10 +321,10 @@ static int g2d_flush(struct g2d_context *ctx) struct drm_exynos_g2d_set_cmdlist cmdlist = {0}; if (ctx->cmd_nr == 0 && ctx->cmd_buf_nr == 0) - return -1; + return 0; if (ctx->cmdlist_nr >= G2D_MAX_CMD_LIST_NR) { - fprintf(stderr, "Overflow cmdlist.\n"); + fprintf(stderr, MSG_PREFIX "command list overflow.\n"); return -EINVAL; } @@ -202,15 +332,22 @@ static int g2d_flush(struct g2d_context *ctx) cmdlist.cmd_buf = (uint64_t)(uintptr_t)&ctx->cmd_buf[0]; cmdlist.cmd_nr = ctx->cmd_nr; cmdlist.cmd_buf_nr = ctx->cmd_buf_nr; - cmdlist.event_type = G2D_EVENT_NOT; - cmdlist.user_data = 0; + + if (ctx->event_userdata) { + cmdlist.event_type = G2D_EVENT_NONSTOP; + cmdlist.user_data = (uint64_t)(uintptr_t)(ctx->event_userdata); + ctx->event_userdata = NULL; + } else { + cmdlist.event_type = G2D_EVENT_NOT; + cmdlist.user_data = 0; + } ctx->cmd_nr = 0; ctx->cmd_buf_nr = 0; ret = drmIoctl(ctx->fd, DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST, &cmdlist); if (ret < 0) { - fprintf(stderr, "failed to set cmdlist.\n"); + fprintf(stderr, MSG_PREFIX "failed to set cmdlist.\n"); return ret; } @@ -232,7 +369,7 @@ struct g2d_context *g2d_init(int fd) ctx = calloc(1, sizeof(*ctx)); if (!ctx) { - fprintf(stderr, "failed to allocate context.\n"); + fprintf(stderr, MSG_PREFIX "failed to allocate context.\n"); return NULL; } @@ -240,7 +377,7 @@ struct g2d_context *g2d_init(int fd) ret = drmIoctl(fd, DRM_IOCTL_EXYNOS_G2D_GET_VER, &ver); if (ret < 0) { - fprintf(stderr, "failed to get version.\n"); + fprintf(stderr, MSG_PREFIX "failed to get version.\n"); free(ctx); return NULL; } @@ -248,7 +385,7 @@ struct g2d_context *g2d_init(int fd) ctx->major = ver.major; ctx->minor = ver.minor; - printf("g2d version(%d.%d).\n", ctx->major, ctx->minor); + printf(MSG_PREFIX "G2D version (%d.%d).\n", ctx->major, ctx->minor); return ctx; } @@ -258,6 +395,22 @@ void g2d_fini(struct g2d_context *ctx) } /** + * g2d_config_event - setup userdata configuration for a g2d event. + * The next invocation of a g2d call (e.g. g2d_solid_fill) is + * then going to flag the command buffer as 'nonstop'. + * Completion of the command buffer execution can then be + * determined by using drmHandleEvent on the DRM fd. + * The userdata is 'consumed' in the process. + * + * @ctx: a pointer to g2d_context structure. + * @userdata: a pointer to the user data + */ +void g2d_config_event(struct g2d_context *ctx, void *userdata) +{ + ctx->event_userdata = userdata; +} + +/** * g2d_exec - start the dma to process all commands summited by g2d_flush(). * * @ctx: a pointer to g2d_context structure. @@ -274,7 +427,7 @@ int g2d_exec(struct g2d_context *ctx) ret = drmIoctl(ctx->fd, DRM_IOCTL_EXYNOS_G2D_EXEC, &exec); if (ret < 0) { - fprintf(stderr, "failed to execute.\n"); + fprintf(stderr, MSG_PREFIX "failed to execute.\n"); return ret; } @@ -302,6 +455,9 @@ g2d_solid_fill(struct g2d_context *ctx, struct g2d_image *img, union g2d_bitblt_cmd_val bitblt; union g2d_point_val pt; + if (g2d_check_space(ctx, 7, 1)) + return -ENOSPC; + g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(ctx, DST_COLOR_MODE_REG, img->color_mode); g2d_add_base_addr(ctx, img, g2d_dst); @@ -312,15 +468,12 @@ g2d_solid_fill(struct g2d_context *ctx, struct g2d_image *img, if (y + h > img->height) h = img->height - y; - pt.val = 0; pt.data.x = x; pt.data.y = y; g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = x + w; pt.data.y = y + h; - g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); g2d_add_cmd(ctx, SF_COLOR_REG, img->color); @@ -355,7 +508,32 @@ g2d_copy(struct g2d_context *ctx, struct g2d_image *src, { union g2d_rop4_val rop4; union g2d_point_val pt; - unsigned int src_w = 0, src_h = 0, dst_w = 0, dst_h = 0; + unsigned int src_w, src_h, dst_w, dst_h; + + src_w = w; + src_h = h; + if (src_x + src->width > w) + src_w = src->width - src_x; + if (src_y + src->height > h) + src_h = src->height - src_y; + + dst_w = w; + dst_h = w; + if (dst_x + dst->width > w) + dst_w = dst->width - dst_x; + if (dst_y + dst->height > h) + dst_h = dst->height - dst_y; + + w = MIN(src_w, dst_w); + h = MIN(src_h, dst_h); + + if (w <= 0 || h <= 0) { + fprintf(stderr, MSG_PREFIX "invalid width or height.\n"); + return -EINVAL; + } + + if (g2d_check_space(ctx, 11, 2)) + return -ENOSPC; g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); g2d_add_cmd(ctx, DST_COLOR_MODE_REG, dst->color_mode); @@ -367,43 +545,111 @@ g2d_copy(struct g2d_context *ctx, struct g2d_image *src, g2d_add_base_addr(ctx, src, g2d_src); g2d_add_cmd(ctx, SRC_STRIDE_REG, src->stride); + pt.data.x = src_x; + pt.data.y = src_y; + g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val); + pt.data.x = src_x + w; + pt.data.y = src_y + h; + g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val); + + pt.data.x = dst_x; + pt.data.y = dst_y; + g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); + pt.data.x = dst_x + w; + pt.data.y = dst_y + h; + g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); + + rop4.val = 0; + rop4.data.unmasked_rop3 = G2D_ROP3_SRC; + g2d_add_cmd(ctx, ROP4_REG, rop4.val); + + return g2d_flush(ctx); +} + +/** + * g2d_move - copy content inside single buffer. + * Similar to libc's memmove() this copies a rectangular + * region of the provided buffer to another location, while + * properly handling the situation where source and + * destination rectangle overlap. + * + * @ctx: a pointer to g2d_context structure. + * @img: a pointer to g2d_image structure providing + * buffer information. + * @src_x: x position of source rectangle. + * @src_y: y position of source rectangle. + * @dst_x: x position of destination rectangle. + * @dst_y: y position of destination rectangle. + * @w: width of rectangle to move. + * @h: height of rectangle to move. + */ +int +g2d_move(struct g2d_context *ctx, struct g2d_image *img, + unsigned int src_x, unsigned int src_y, + unsigned int dst_x, unsigned dst_y, unsigned int w, + unsigned int h) +{ + union g2d_rop4_val rop4; + union g2d_point_val pt; + union g2d_direction_val dir; + unsigned int src_w, src_h, dst_w, dst_h; + src_w = w; src_h = h; - if (src_x + src->width > w) - src_w = src->width - src_x; - if (src_y + src->height > h) - src_h = src->height - src_y; + if (src_x + img->width > w) + src_w = img->width - src_x; + if (src_y + img->height > h) + src_h = img->height - src_y; dst_w = w; dst_h = w; - if (dst_x + dst->width > w) - dst_w = dst->width - dst_x; - if (dst_y + dst->height > h) - dst_h = dst->height - dst_y; + if (dst_x + img->width > w) + dst_w = img->width - dst_x; + if (dst_y + img->height > h) + dst_h = img->height - dst_y; w = MIN(src_w, dst_w); h = MIN(src_h, dst_h); - if (w <= 0 || h <= 0) { - fprintf(stderr, "invalid width or height.\n"); - g2d_reset(ctx); + if (w == 0 || h == 0) { + fprintf(stderr, MSG_PREFIX "invalid width or height.\n"); return -EINVAL; } - pt.val = 0; + if (g2d_check_space(ctx, 13, 2)) + return -ENOSPC; + + g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); + g2d_add_cmd(ctx, SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); + + g2d_add_cmd(ctx, DST_COLOR_MODE_REG, img->color_mode); + g2d_add_cmd(ctx, SRC_COLOR_MODE_REG, img->color_mode); + + g2d_add_base_addr(ctx, img, g2d_dst); + g2d_add_base_addr(ctx, img, g2d_src); + + g2d_add_cmd(ctx, DST_STRIDE_REG, img->stride); + g2d_add_cmd(ctx, SRC_STRIDE_REG, img->stride); + + dir.val[0] = dir.val[1] = 0; + + if (dst_x >= src_x) + dir.data.src_x_direction = dir.data.dst_x_direction = 1; + if (dst_y >= src_y) + dir.data.src_y_direction = dir.data.dst_y_direction = 1; + + g2d_set_direction(ctx, &dir); + pt.data.x = src_x; pt.data.y = src_y; g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = src_x + w; pt.data.y = src_y + h; g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val); - pt.val = 0; pt.data.x = dst_x; pt.data.y = dst_y; g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = dst_x + w; pt.data.y = dst_y + h; g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); @@ -445,23 +691,12 @@ g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, { union g2d_rop4_val rop4; union g2d_point_val pt; - unsigned int scale; + unsigned int scale, repeat_pad; unsigned int scale_x, scale_y; - g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); - g2d_add_cmd(ctx, DST_COLOR_MODE_REG, dst->color_mode); - g2d_add_base_addr(ctx, dst, g2d_dst); - g2d_add_cmd(ctx, DST_STRIDE_REG, dst->stride); - - g2d_add_cmd(ctx, SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); - g2d_add_cmd(ctx, SRC_COLOR_MODE_REG, src->color_mode); - - g2d_add_cmd(ctx, SRC_REPEAT_MODE_REG, src->repeat_mode); - if (src->repeat_mode == G2D_REPEAT_MODE_PAD) - g2d_add_cmd(ctx, SRC_PAD_VALUE_REG, dst->color); - - g2d_add_base_addr(ctx, src, g2d_src); - g2d_add_cmd(ctx, SRC_STRIDE_REG, src->stride); + /* Sanitize this parameter to facilitate space computation below. */ + if (negative) + negative = 1; if (src_w == dst_w && src_h == dst_h) scale = 0; @@ -471,6 +706,8 @@ g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, scale_y = g2d_get_scaling(src_h, dst_h); } + repeat_pad = src->repeat_mode == G2D_REPEAT_MODE_PAD ? 1 : 0; + if (src_x + src_w > src->width) src_w = src->width - src_x; if (src_y + src_h > src->height) @@ -482,42 +719,54 @@ g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, dst_h = dst->height - dst_y; if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { - fprintf(stderr, "invalid width or height.\n"); - g2d_reset(ctx); + fprintf(stderr, MSG_PREFIX "invalid width or height.\n"); return -EINVAL; } + if (g2d_check_space(ctx, 12 + scale * 3 + negative + repeat_pad, 2)) + return -ENOSPC; + + g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); + g2d_add_cmd(ctx, DST_COLOR_MODE_REG, dst->color_mode); + g2d_add_base_addr(ctx, dst, g2d_dst); + g2d_add_cmd(ctx, DST_STRIDE_REG, dst->stride); + + g2d_add_cmd(ctx, SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); + g2d_add_cmd(ctx, SRC_COLOR_MODE_REG, src->color_mode); + + g2d_add_cmd(ctx, SRC_REPEAT_MODE_REG, src->repeat_mode); + if (repeat_pad) + g2d_add_cmd(ctx, SRC_PAD_VALUE_REG, dst->color); + + g2d_add_base_addr(ctx, src, g2d_src); + g2d_add_cmd(ctx, SRC_STRIDE_REG, src->stride); + + rop4.val = 0; + rop4.data.unmasked_rop3 = G2D_ROP3_SRC; + if (negative) { g2d_add_cmd(ctx, BG_COLOR_REG, 0x00FFFFFF); - rop4.val = 0; - rop4.data.unmasked_rop3 = G2D_ROP3_SRC^G2D_ROP3_DST; - g2d_add_cmd(ctx, ROP4_REG, rop4.val); - } else { - rop4.val = 0; - rop4.data.unmasked_rop3 = G2D_ROP3_SRC; - g2d_add_cmd(ctx, ROP4_REG, rop4.val); + rop4.data.unmasked_rop3 ^= G2D_ROP3_DST; } + g2d_add_cmd(ctx, ROP4_REG, rop4.val); + if (scale) { g2d_add_cmd(ctx, SRC_SCALE_CTRL_REG, G2D_SCALE_MODE_BILINEAR); g2d_add_cmd(ctx, SRC_XSCALE_REG, scale_x); g2d_add_cmd(ctx, SRC_YSCALE_REG, scale_y); } - pt.val = 0; pt.data.x = src_x; pt.data.y = src_y; g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = src_x + src_w; pt.data.y = src_y + src_h; g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val); - pt.val = 0; pt.data.x = dst_x; pt.data.y = dst_y; g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = dst_x + dst_w; pt.data.y = dst_y + dst_h; g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); @@ -550,7 +799,45 @@ g2d_blend(struct g2d_context *ctx, struct g2d_image *src, union g2d_point_val pt; union g2d_bitblt_cmd_val bitblt; union g2d_blend_func_val blend; - unsigned int src_w = 0, src_h = 0, dst_w = 0, dst_h = 0; + unsigned int gem_space; + unsigned int src_w, src_h, dst_w, dst_h; + + src_w = w; + src_h = h; + if (src_x + w > src->width) + src_w = src->width - src_x; + if (src_y + h > src->height) + src_h = src->height - src_y; + + dst_w = w; + dst_h = h; + if (dst_x + w > dst->width) + dst_w = dst->width - dst_x; + if (dst_y + h > dst->height) + dst_h = dst->height - dst_y; + + w = MIN(src_w, dst_w); + h = MIN(src_h, dst_h); + + if (w <= 0 || h <= 0) { + fprintf(stderr, MSG_PREFIX "invalid width or height.\n"); + return -EINVAL; + } + + if (!g2d_validate_select_mode(src->select_mode)) { + fprintf(stderr , MSG_PREFIX "invalid select mode for source.\n"); + return -EINVAL; + } + + if (!g2d_validate_blending_op(op)) { + fprintf(stderr , MSG_PREFIX "unsupported blending operation.\n"); + return -EINVAL; + } + + gem_space = src->select_mode == G2D_SELECT_MODE_NORMAL ? 2 : 1; + + if (g2d_check_space(ctx, 12, gem_space)) + return -ENOSPC; bitblt.val = 0; blend.val = 0; @@ -578,32 +865,6 @@ g2d_blend(struct g2d_context *ctx, struct g2d_image *src, case G2D_SELECT_MODE_BGCOLOR: g2d_add_cmd(ctx, BG_COLOR_REG, src->color); break; - default: - fprintf(stderr , "failed to set src.\n"); - return -EINVAL; - } - - src_w = w; - src_h = h; - if (src_x + w > src->width) - src_w = src->width - src_x; - if (src_y + h > src->height) - src_h = src->height - src_y; - - dst_w = w; - dst_h = h; - if (dst_x + w > dst->width) - dst_w = dst->width - dst_x; - if (dst_y + h > dst->height) - dst_h = dst->height - dst_y; - - w = MIN(src_w, dst_w); - h = MIN(src_h, dst_h); - - if (w <= 0 || h <= 0) { - fprintf(stderr, "invalid width or height.\n"); - g2d_reset(ctx); - return -EINVAL; } bitblt.data.alpha_blend_mode = G2D_ALPHA_BLEND_MODE_ENABLE; @@ -611,20 +872,16 @@ g2d_blend(struct g2d_context *ctx, struct g2d_image *src, g2d_add_cmd(ctx, BITBLT_COMMAND_REG, bitblt.val); g2d_add_cmd(ctx, BLEND_FUNCTION_REG, blend.val); - pt.val = 0; pt.data.x = src_x; pt.data.y = src_y; g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = src_x + w; pt.data.y = src_y + h; g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val); - pt.val = 0; pt.data.x = dst_x; pt.data.y = dst_y; g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = dst_x + w; pt.data.y = dst_y + h; g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); @@ -660,9 +917,47 @@ g2d_scale_and_blend(struct g2d_context *ctx, struct g2d_image *src, union g2d_point_val pt; union g2d_bitblt_cmd_val bitblt; union g2d_blend_func_val blend; - unsigned int scale; + unsigned int scale, gem_space; unsigned int scale_x, scale_y; + if (src_w == dst_w && src_h == dst_h) + scale = 0; + else { + scale = 1; + scale_x = g2d_get_scaling(src_w, dst_w); + scale_y = g2d_get_scaling(src_h, dst_h); + } + + if (src_x + src_w > src->width) + src_w = src->width - src_x; + if (src_y + src_h > src->height) + src_h = src->height - src_y; + + if (dst_x + dst_w > dst->width) + dst_w = dst->width - dst_x; + if (dst_y + dst_h > dst->height) + dst_h = dst->height - dst_y; + + if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { + fprintf(stderr, MSG_PREFIX "invalid width or height.\n"); + return -EINVAL; + } + + if (!g2d_validate_select_mode(src->select_mode)) { + fprintf(stderr , MSG_PREFIX "invalid select mode for source.\n"); + return -EINVAL; + } + + if (!g2d_validate_blending_op(op)) { + fprintf(stderr , MSG_PREFIX "unsupported blending operation.\n"); + return -EINVAL; + } + + gem_space = src->select_mode == G2D_SELECT_MODE_NORMAL ? 2 : 1; + + if (g2d_check_space(ctx, 12 + scale * 3, gem_space)) + return -ENOSPC; + bitblt.val = 0; blend.val = 0; @@ -672,12 +967,7 @@ g2d_scale_and_blend(struct g2d_context *ctx, struct g2d_image *src, g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(ctx, DST_COLOR_MODE_REG, dst->color_mode); - if (dst->buf_type == G2D_IMGBUF_USERPTR) - g2d_add_cmd(ctx, DST_BASE_ADDR_REG | G2D_BUF_USERPTR, - (unsigned long)&dst->user_ptr[0]); - else - g2d_add_cmd(ctx, DST_BASE_ADDR_REG, dst->bo[0]); - + g2d_add_base_addr(ctx, dst, g2d_dst); g2d_add_cmd(ctx, DST_STRIDE_REG, dst->stride); g2d_add_cmd(ctx, SRC_SELECT_REG, src->select_mode); @@ -685,12 +975,7 @@ g2d_scale_and_blend(struct g2d_context *ctx, struct g2d_image *src, switch (src->select_mode) { case G2D_SELECT_MODE_NORMAL: - if (src->buf_type == G2D_IMGBUF_USERPTR) - g2d_add_cmd(ctx, SRC_BASE_ADDR_REG | G2D_BUF_USERPTR, - (unsigned long)&src->user_ptr[0]); - else - g2d_add_cmd(ctx, SRC_BASE_ADDR_REG, src->bo[0]); - + g2d_add_base_addr(ctx, src, g2d_src); g2d_add_cmd(ctx, SRC_STRIDE_REG, src->stride); break; case G2D_SELECT_MODE_FGCOLOR: @@ -699,33 +984,6 @@ g2d_scale_and_blend(struct g2d_context *ctx, struct g2d_image *src, case G2D_SELECT_MODE_BGCOLOR: g2d_add_cmd(ctx, BG_COLOR_REG, src->color); break; - default: - fprintf(stderr , "failed to set src.\n"); - return -EINVAL; - } - - if (src_w == dst_w && src_h == dst_h) - scale = 0; - else { - scale = 1; - scale_x = g2d_get_scaling(src_w, dst_w); - scale_y = g2d_get_scaling(src_h, dst_h); - } - - if (src_x + src_w > src->width) - src_w = src->width - src_x; - if (src_y + src_h > src->height) - src_h = src->height - src_y; - - if (dst_x + dst_w > dst->width) - dst_w = dst->width - dst_x; - if (dst_y + dst_h > dst->height) - dst_h = dst->height - dst_y; - - if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { - fprintf(stderr, "invalid width or height.\n"); - g2d_reset(ctx); - return -EINVAL; } if (scale) { @@ -739,20 +997,16 @@ g2d_scale_and_blend(struct g2d_context *ctx, struct g2d_image *src, g2d_add_cmd(ctx, BITBLT_COMMAND_REG, bitblt.val); g2d_add_cmd(ctx, BLEND_FUNCTION_REG, blend.val); - pt.val = 0; pt.data.x = src_x; pt.data.y = src_y; g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = src_x + src_w; pt.data.y = src_y + src_h; g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val); - pt.val = 0; pt.data.x = dst_x; pt.data.y = dst_y; g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val); - pt.val = 0; pt.data.x = dst_x + dst_w; pt.data.y = dst_y + dst_h; g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val); diff --git a/lib/libdrm/exynos/exynos_fimg2d.h b/lib/libdrm/exynos/exynos_fimg2d.h index 9db0c88b1..a825c6831 100644 --- a/lib/libdrm/exynos/exynos_fimg2d.h +++ b/lib/libdrm/exynos/exynos_fimg2d.h @@ -13,9 +13,6 @@ #ifndef _FIMG2D_H_ #define _FIMG2D_H_ -#define G2D_MAX_CMD_NR 64 -#define G2D_MAX_GEM_CMD_NR 64 -#define G2D_MAX_CMD_LIST_NR 64 #define G2D_PLANE_MAX_NR 2 enum e_g2d_color_mode { @@ -289,19 +286,11 @@ struct g2d_image { void *mapped_ptr[G2D_PLANE_MAX_NR]; }; -struct g2d_context { - int fd; - unsigned int major; - unsigned int minor; - struct drm_exynos_g2d_cmd cmd[G2D_MAX_CMD_NR]; - struct drm_exynos_g2d_cmd cmd_buf[G2D_MAX_GEM_CMD_NR]; - unsigned int cmd_nr; - unsigned int cmd_buf_nr; - unsigned int cmdlist_nr; -}; +struct g2d_context; struct g2d_context *g2d_init(int fd); void g2d_fini(struct g2d_context *ctx); +void g2d_config_event(struct g2d_context *ctx, void *userdata); int g2d_exec(struct g2d_context *ctx); int g2d_solid_fill(struct g2d_context *ctx, struct g2d_image *img, unsigned int x, unsigned int y, unsigned int w, @@ -310,6 +299,9 @@ int g2d_copy(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int dst_x, unsigned int dst_y, unsigned int w, unsigned int h); +int g2d_move(struct g2d_context *ctx, struct g2d_image *img, + unsigned int src_x, unsigned int src_y, unsigned int dst_x, + unsigned dst_y, unsigned int w, unsigned int h); int g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int src_w, diff --git a/lib/libdrm/exynos/libdrm_exynos.pc.in b/lib/libdrm/exynos/libdrm_exynos.pc.in index 5ce911866..ff1c43203 100644 --- a/lib/libdrm/exynos/libdrm_exynos.pc.in +++ b/lib/libdrm/exynos/libdrm_exynos.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: libdrm_exynos Description: Userspace interface to exynos kernel DRM services -Version: 0.6 +Version: 0.7 Libs: -L${libdir} -ldrm_exynos Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/exynos Requires.private: libdrm diff --git a/lib/libdrm/freedreno/freedreno_bo.c b/lib/libdrm/freedreno/freedreno_bo.c index 1cb67595b..a23c65d06 100644 --- a/lib/libdrm/freedreno/freedreno_bo.c +++ b/lib/libdrm/freedreno/freedreno_bo.c @@ -298,11 +298,6 @@ void fd_bo_del(struct fd_bo *bo) if (!atomic_dec_and_test(&bo->refcnt)) return; - if (bo->fd >= 0) { - close(bo->fd); - bo->fd = -1; - } - pthread_mutex_lock(&table_lock); if (bo->bo_reuse) { @@ -371,6 +366,7 @@ int fd_bo_get_name(struct fd_bo *bo, uint32_t *name) pthread_mutex_lock(&table_lock); set_name(bo, req.name); pthread_mutex_unlock(&table_lock); + bo->bo_reuse = 0; } *name = bo->name; @@ -385,18 +381,18 @@ uint32_t fd_bo_handle(struct fd_bo *bo) int fd_bo_dmabuf(struct fd_bo *bo) { - if (bo->fd < 0) { - int ret, prime_fd; + int ret, prime_fd; - ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC, - &prime_fd); - if (ret) { - return ret; - } - - bo->fd = prime_fd; + ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC, + &prime_fd); + if (ret) { + ERROR_MSG("failed to get dmabuf fd: %d", ret); + return ret; } - return dup(bo->fd); + + bo->bo_reuse = 0; + + return prime_fd; } uint32_t fd_bo_size(struct fd_bo *bo) diff --git a/lib/libdrm/freedreno/freedreno_drmif.h b/lib/libdrm/freedreno/freedreno_drmif.h index 5547e9439..950fd63be 100644 --- a/lib/libdrm/freedreno/freedreno_drmif.h +++ b/lib/libdrm/freedreno/freedreno_drmif.h @@ -50,6 +50,7 @@ enum fd_param_id { FD_GMEM_SIZE, FD_GPU_ID, FD_CHIP_ID, + FD_MAX_FREQ, }; /* bo flags: */ diff --git a/lib/libdrm/freedreno/freedreno_priv.h b/lib/libdrm/freedreno/freedreno_priv.h index 4e442e420..53817b197 100644 --- a/lib/libdrm/freedreno/freedreno_priv.h +++ b/lib/libdrm/freedreno/freedreno_priv.h @@ -138,7 +138,6 @@ struct fd_bo { uint32_t size; uint32_t handle; uint32_t name; - int fd; /* dmabuf handle */ void *map; atomic_t refcnt; const struct fd_bo_funcs *funcs; diff --git a/lib/libdrm/freedreno/kgsl/kgsl_bo.c b/lib/libdrm/freedreno/kgsl/kgsl_bo.c index b8ac10261..2b45b5e20 100644 --- a/lib/libdrm/freedreno/kgsl/kgsl_bo.c +++ b/lib/libdrm/freedreno/kgsl/kgsl_bo.c @@ -168,7 +168,6 @@ drm_private struct fd_bo * kgsl_bo_from_handle(struct fd_device *dev, bo = &kgsl_bo->base; bo->funcs = &funcs; - bo->fd = -1; for (i = 0; i < ARRAY_SIZE(kgsl_bo->list); i++) list_inithead(&kgsl_bo->list[i]); diff --git a/lib/libdrm/freedreno/kgsl/kgsl_pipe.c b/lib/libdrm/freedreno/kgsl/kgsl_pipe.c index 58b3b4d50..5569da0a8 100644 --- a/lib/libdrm/freedreno/kgsl/kgsl_pipe.c +++ b/lib/libdrm/freedreno/kgsl/kgsl_pipe.c @@ -50,6 +50,9 @@ static int kgsl_pipe_get_param(struct fd_pipe *pipe, case FD_CHIP_ID: *value = kgsl_pipe->devinfo.chip_id; return 0; + case FD_MAX_FREQ: + /* unsupported on kgsl */ + return -1; default: ERROR_MSG("invalid param id: %d", param); return -1; diff --git a/lib/libdrm/freedreno/msm/msm_bo.c b/lib/libdrm/freedreno/msm/msm_bo.c index ee668aba9..cd05a6cd4 100644 --- a/lib/libdrm/freedreno/msm/msm_bo.c +++ b/lib/libdrm/freedreno/msm/msm_bo.c @@ -136,7 +136,6 @@ drm_private struct fd_bo * msm_bo_from_handle(struct fd_device *dev, bo = &msm_bo->base; bo->funcs = &funcs; - bo->fd = -1; return bo; } diff --git a/lib/libdrm/freedreno/msm/msm_drm.h b/lib/libdrm/freedreno/msm/msm_drm.h index f7474c594..baf505ce1 100644 --- a/lib/libdrm/freedreno/msm/msm_drm.h +++ b/lib/libdrm/freedreno/msm/msm_drm.h @@ -58,6 +58,7 @@ struct drm_msm_timespec { #define MSM_PARAM_GPU_ID 0x01 #define MSM_PARAM_GMEM_SIZE 0x02 #define MSM_PARAM_CHIP_ID 0x03 +#define MSM_PARAM_MAX_FREQ 0x04 struct drm_msm_param { uint32_t pipe; /* in, MSM_PIPE_x */ diff --git a/lib/libdrm/freedreno/msm/msm_pipe.c b/lib/libdrm/freedreno/msm/msm_pipe.c index aa0866b4a..f539b9aec 100644 --- a/lib/libdrm/freedreno/msm/msm_pipe.c +++ b/lib/libdrm/freedreno/msm/msm_pipe.c @@ -32,6 +32,25 @@ #include "msm_priv.h" +static int query_param(struct fd_pipe *pipe, uint32_t param, + uint64_t *value) +{ + struct msm_pipe *msm_pipe = to_msm_pipe(pipe); + struct drm_msm_param req = { + .pipe = msm_pipe->pipe, + .param = param, + }; + int ret; + + ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_GET_PARAM, + &req, sizeof(req)); + if (ret) + return ret; + + *value = req.value; + + return 0; +} static int msm_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value) @@ -48,6 +67,8 @@ static int msm_pipe_get_param(struct fd_pipe *pipe, case FD_CHIP_ID: *value = msm_pipe->chip_id; return 0; + case FD_MAX_FREQ: + return query_param(pipe, MSM_PARAM_MAX_FREQ, value); default: ERROR_MSG("invalid param id: %d", param); return -1; @@ -87,21 +108,15 @@ static const struct fd_pipe_funcs funcs = { .destroy = msm_pipe_destroy, }; -static uint64_t get_param(struct fd_device *dev, uint32_t pipe, uint32_t param) +static uint64_t get_param(struct fd_pipe *pipe, uint32_t param) { - struct drm_msm_param req = { - .pipe = pipe, - .param = param, - }; - int ret; - - ret = drmCommandWriteRead(dev->fd, DRM_MSM_GET_PARAM, &req, sizeof(req)); + uint64_t value; + int ret = query_param(pipe, param, &value); if (ret) { ERROR_MSG("get-param failed! %d (%s)", ret, strerror(errno)); return 0; } - - return req.value; + return value; } drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, @@ -123,10 +138,14 @@ drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, pipe = &msm_pipe->base; pipe->funcs = &funcs; + /* initialize before get_param(): */ + pipe->dev = dev; msm_pipe->pipe = pipe_id[id]; - msm_pipe->gpu_id = get_param(dev, pipe_id[id], MSM_PARAM_GPU_ID); - msm_pipe->gmem = get_param(dev, pipe_id[id], MSM_PARAM_GMEM_SIZE); - msm_pipe->chip_id = get_param(dev, pipe_id[id], MSM_PARAM_CHIP_ID); + + /* these params should be supported since the first version of drm/msm: */ + msm_pipe->gpu_id = get_param(pipe, MSM_PARAM_GPU_ID); + msm_pipe->gmem = get_param(pipe, MSM_PARAM_GMEM_SIZE); + msm_pipe->chip_id = get_param(pipe, MSM_PARAM_CHIP_ID); if (! msm_pipe->gpu_id) goto fail; diff --git a/lib/libdrm/freedreno/msm/msm_ringbuffer.c b/lib/libdrm/freedreno/msm/msm_ringbuffer.c index ee6af0ba0..becf24589 100644 --- a/lib/libdrm/freedreno/msm/msm_ringbuffer.c +++ b/lib/libdrm/freedreno/msm/msm_ringbuffer.c @@ -253,7 +253,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start cmd->nr_relocs = (b > a) ? b - a : 0; } - DEBUG_MSG("nr_cmds=%u, nr_bos=%u\n", req.nr_cmds, req.nr_bos); + DEBUG_MSG("nr_cmds=%u, nr_bos=%u", req.nr_cmds, req.nr_bos); ret = drmCommandWriteRead(ring->pipe->dev->fd, DRM_MSM_GEM_SUBMIT, &req, sizeof(req)); @@ -267,7 +267,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start for (i = 0; i < msm_ring->submit.nr_cmds; i++) { struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; struct drm_msm_gem_submit_reloc *relocs = U642VOID(cmd->relocs); - ERROR_MSG(" cmd[%d]: type=%u, submit_idx=%u, submit_offset=%u, size=%u\n", + ERROR_MSG(" cmd[%d]: type=%u, submit_idx=%u, submit_offset=%u, size=%u", i, cmd->type, cmd->submit_idx, cmd->submit_offset, cmd->size); for (j = 0; j < cmd->nr_relocs; j++) { struct drm_msm_gem_submit_reloc *r = &relocs[j]; diff --git a/lib/libdrm/include/drm/drm_fourcc.h b/lib/libdrm/include/drm/drm_fourcc.h index 63a80ca5b..e741b09a0 100644 --- a/lib/libdrm/include/drm/drm_fourcc.h +++ b/lib/libdrm/include/drm/drm_fourcc.h @@ -149,7 +149,7 @@ /* add more to the end as needed */ #define fourcc_mod_code(vendor, val) \ - ((((u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) + ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) /* * Format Modifier tokens: diff --git a/lib/libdrm/include/drm/nouveau_drm.h b/lib/libdrm/include/drm/nouveau_drm.h index 87aefc5e9..e418f9f38 100644 --- a/lib/libdrm/include/drm/nouveau_drm.h +++ b/lib/libdrm/include/drm/nouveau_drm.h @@ -200,6 +200,7 @@ struct drm_nouveau_sarea { #define DRM_NOUVEAU_GROBJ_ALLOC 0x04 #define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 #define DRM_NOUVEAU_GPUOBJ_FREE 0x06 +#define DRM_NOUVEAU_NVIF 0x07 #define DRM_NOUVEAU_GEM_NEW 0x40 #define DRM_NOUVEAU_GEM_PUSHBUF 0x41 #define DRM_NOUVEAU_GEM_CPU_PREP 0x42 diff --git a/lib/libdrm/include/drm/vc4_drm.h b/lib/libdrm/include/drm/vc4_drm.h new file mode 100644 index 000000000..da3caa081 --- /dev/null +++ b/lib/libdrm/include/drm/vc4_drm.h @@ -0,0 +1,279 @@ +/* + * Copyright © 2014-2015 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _VC4_DRM_H_ +#define _VC4_DRM_H_ + +#include "drm.h" + +#define DRM_VC4_SUBMIT_CL 0x00 +#define DRM_VC4_WAIT_SEQNO 0x01 +#define DRM_VC4_WAIT_BO 0x02 +#define DRM_VC4_CREATE_BO 0x03 +#define DRM_VC4_MMAP_BO 0x04 +#define DRM_VC4_CREATE_SHADER_BO 0x05 +#define DRM_VC4_GET_HANG_STATE 0x06 + +#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) +#define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) +#define DRM_IOCTL_VC4_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_BO, struct drm_vc4_wait_bo) +#define DRM_IOCTL_VC4_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_BO, struct drm_vc4_create_bo) +#define DRM_IOCTL_VC4_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_MMAP_BO, struct drm_vc4_mmap_bo) +#define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo) +#define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state) + +struct drm_vc4_submit_rcl_surface { + __u32 hindex; /* Handle index, or ~0 if not present. */ + __u32 offset; /* Offset to start of buffer. */ + /* + * Bits for either render config (color_write) or load/store packet. + * Bits should all be 0 for MSAA load/stores. + */ + __u16 bits; + +#define VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES (1 << 0) + __u16 flags; +}; + +/** + * struct drm_vc4_submit_cl - ioctl argument for submitting commands to the 3D + * engine. + * + * Drivers typically use GPU BOs to store batchbuffers / command lists and + * their associated state. However, because the VC4 lacks an MMU, we have to + * do validation of memory accesses by the GPU commands. If we were to store + * our commands in BOs, we'd need to do uncached readback from them to do the + * validation process, which is too expensive. Instead, userspace accumulates + * commands and associated state in plain memory, then the kernel copies the + * data to its own address space, and then validates and stores it in a GPU + * BO. + */ +struct drm_vc4_submit_cl { + /* Pointer to the binner command list. + * + * This is the first set of commands executed, which runs the + * coordinate shader to determine where primitives land on the screen, + * then writes out the state updates and draw calls necessary per tile + * to the tile allocation BO. + */ + __u64 bin_cl; + + /* Pointer to the shader records. + * + * Shader records are the structures read by the hardware that contain + * pointers to uniforms, shaders, and vertex attributes. The + * reference to the shader record has enough information to determine + * how many pointers are necessary (fixed number for shaders/uniforms, + * and an attribute count), so those BO indices into bo_handles are + * just stored as __u32s before each shader record passed in. + */ + __u64 shader_rec; + + /* Pointer to uniform data and texture handles for the textures + * referenced by the shader. + * + * For each shader state record, there is a set of uniform data in the + * order referenced by the record (FS, VS, then CS). Each set of + * uniform data has a __u32 index into bo_handles per texture + * sample operation, in the order the QPU_W_TMUn_S writes appear in + * the program. Following the texture BO handle indices is the actual + * uniform data. + * + * The individual uniform state blocks don't have sizes passed in, + * because the kernel has to determine the sizes anyway during shader + * code validation. + */ + __u64 uniforms; + __u64 bo_handles; + + /* Size in bytes of the binner command list. */ + __u32 bin_cl_size; + /* Size in bytes of the set of shader records. */ + __u32 shader_rec_size; + /* Number of shader records. + * + * This could just be computed from the contents of shader_records and + * the address bits of references to them from the bin CL, but it + * keeps the kernel from having to resize some allocations it makes. + */ + __u32 shader_rec_count; + /* Size in bytes of the uniform state. */ + __u32 uniforms_size; + + /* Number of BO handles passed in (size is that times 4). */ + __u32 bo_handle_count; + + /* RCL setup: */ + __u16 width; + __u16 height; + __u8 min_x_tile; + __u8 min_y_tile; + __u8 max_x_tile; + __u8 max_y_tile; + struct drm_vc4_submit_rcl_surface color_read; + struct drm_vc4_submit_rcl_surface color_write; + struct drm_vc4_submit_rcl_surface zs_read; + struct drm_vc4_submit_rcl_surface zs_write; + struct drm_vc4_submit_rcl_surface msaa_color_write; + struct drm_vc4_submit_rcl_surface msaa_zs_write; + __u32 clear_color[2]; + __u32 clear_z; + __u8 clear_s; + + __u32 pad:24; + +#define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0) + __u32 flags; + + /* Returned value of the seqno of this render job (for the + * wait ioctl). + */ + __u64 seqno; +}; + +/** + * struct drm_vc4_wait_seqno - ioctl argument for waiting for + * DRM_VC4_SUBMIT_CL completion using its returned seqno. + * + * timeout_ns is the timeout in nanoseconds, where "0" means "don't + * block, just return the status." + */ +struct drm_vc4_wait_seqno { + __u64 seqno; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_wait_bo - ioctl argument for waiting for + * completion of the last DRM_VC4_SUBMIT_CL on a BO. + * + * This is useful for cases where multiple processes might be + * rendering to a BO and you want to wait for all rendering to be + * completed. + */ +struct drm_vc4_wait_bo { + __u32 handle; + __u32 pad; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_create_bo - ioctl argument for creating VC4 BOs. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_create_bo { + __u32 size; + __u32 flags; + /** Returned GEM handle for the BO. */ + __u32 handle; + __u32 pad; +}; + +/** + * struct drm_vc4_mmap_bo - ioctl argument for mapping VC4 BOs. + * + * This doesn't actually perform an mmap. Instead, it returns the + * offset you need to use in an mmap on the DRM device node. This + * means that tools like valgrind end up knowing about the mapped + * memory. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_mmap_bo { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 flags; + /** offset into the drm node to use for subsequent mmap call. */ + __u64 offset; +}; + +/** + * struct drm_vc4_create_shader_bo - ioctl argument for creating VC4 + * shader BOs. + * + * Since allowing a shader to be overwritten while it's also being + * executed from would allow privlege escalation, shaders must be + * created using this ioctl, and they can't be mmapped later. + */ +struct drm_vc4_create_shader_bo { + /* Size of the data argument. */ + __u32 size; + /* Flags, currently must be 0. */ + __u32 flags; + + /* Pointer to the data. */ + __u64 data; + + /** Returned GEM handle for the BO. */ + __u32 handle; + /* Pad, must be 0. */ + __u32 pad; +}; + +struct drm_vc4_get_hang_state_bo { + __u32 handle; + __u32 paddr; + __u32 size; + __u32 pad; +}; + +/** + * struct drm_vc4_hang_state - ioctl argument for collecting state + * from a GPU hang for analysis. +*/ +struct drm_vc4_get_hang_state { + /** Pointer to array of struct drm_vc4_get_hang_state_bo. */ + __u64 bo; + /** + * On input, the size of the bo array. Output is the number + * of bos to be returned. + */ + __u32 bo_count; + + __u32 start_bin, start_render; + + __u32 ct0ca, ct0ea; + __u32 ct1ca, ct1ea; + __u32 ct0cs, ct1cs; + __u32 ct0ra0, ct1ra0; + + __u32 bpca, bpcs; + __u32 bpoa, bpos; + + __u32 vpmbase; + + __u32 dbge; + __u32 fdbgo; + __u32 fdbgb; + __u32 fdbgr; + __u32 fdbgs; + __u32 errstat; + + /* Pad that we may save more registers into in the future. */ + __u32 pad[16]; +}; + +#endif /* _VC4_DRM_H_ */ diff --git a/lib/libdrm/intel/intel-symbol-check b/lib/libdrm/intel/intel-symbol-check index c555e6dae..bde7634c3 100755 --- a/lib/libdrm/intel/intel-symbol-check +++ b/lib/libdrm/intel/intel-symbol-check @@ -34,11 +34,13 @@ drm_intel_bo_mrb_exec drm_intel_bo_pin drm_intel_bo_reference drm_intel_bo_references +drm_intel_bo_set_softpin_offset drm_intel_bo_set_tiling drm_intel_bo_subdata drm_intel_bo_unmap drm_intel_bo_unpin drm_intel_bo_unreference +drm_intel_bo_use_48b_address_range drm_intel_bo_wait_rendering drm_intel_bufmgr_check_aperture_space drm_intel_bufmgr_destroy diff --git a/lib/libdrm/nouveau/Makefile.am b/lib/libdrm/nouveau/Makefile.am index 25ea6dc15..76cdecad9 100644 --- a/lib/libdrm/nouveau/Makefile.am +++ b/lib/libdrm/nouveau/Makefile.am @@ -14,9 +14,18 @@ libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ libdrm_nouveau_la_SOURCES = $(LIBDRM_NOUVEAU_FILES) -libdrm_nouveauincludedir = ${includedir}/libdrm +libdrm_nouveauincludedir = ${includedir}/libdrm/nouveau libdrm_nouveauinclude_HEADERS = $(LIBDRM_NOUVEAU_H_FILES) +libdrm_nouveaunvifincludedir = ${includedir}/libdrm/nouveau/nvif +libdrm_nouveaunvifinclude_HEADERS = nvif/class.h \ + nvif/cl0080.h \ + nvif/cl9097.h \ + nvif/if0002.h \ + nvif/if0003.h \ + nvif/ioctl.h \ + nvif/unpack.h + pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_nouveau.pc diff --git a/lib/libdrm/nouveau/abi16.c b/lib/libdrm/nouveau/abi16.c index 59bc43605..ee38c0cb2 100644 --- a/lib/libdrm/nouveau/abi16.c +++ b/lib/libdrm/nouveau/abi16.c @@ -29,14 +29,16 @@ #include <stdlib.h> #include <stdint.h> #include <stddef.h> +#include <errno.h> #include "private.h" +#include "nvif/class.h" -drm_private int +static int abi16_chan_nv04(struct nouveau_object *obj) { - struct nouveau_device *dev = (struct nouveau_device *)obj->parent; + struct nouveau_drm *drm = nouveau_drm(obj); struct nv04_fifo *nv04 = obj->data; struct drm_nouveau_channel_alloc req = { .fb_ctxdma_handle = nv04->vram, @@ -44,7 +46,7 @@ abi16_chan_nv04(struct nouveau_object *obj) }; int ret; - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_CHANNEL_ALLOC, &req, sizeof(req)); if (ret) return ret; @@ -57,15 +59,15 @@ abi16_chan_nv04(struct nouveau_object *obj) return 0; } -drm_private int +static int abi16_chan_nvc0(struct nouveau_object *obj) { - struct nouveau_device *dev = (struct nouveau_device *)obj->parent; + struct nouveau_drm *drm = nouveau_drm(obj); struct drm_nouveau_channel_alloc req = {}; struct nvc0_fifo *nvc0 = obj->data; int ret; - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_CHANNEL_ALLOC, &req, sizeof(req)); if (ret) return ret; @@ -78,10 +80,10 @@ abi16_chan_nvc0(struct nouveau_object *obj) return 0; } -drm_private int +static int abi16_chan_nve0(struct nouveau_object *obj) { - struct nouveau_device *dev = (struct nouveau_device *)obj->parent; + struct nouveau_drm *drm = nouveau_drm(obj); struct drm_nouveau_channel_alloc req = {}; struct nve0_fifo *nve0 = obj->data; int ret; @@ -91,7 +93,7 @@ abi16_chan_nve0(struct nouveau_object *obj) req.tt_ctxdma_handle = nve0->engine; } - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_CHANNEL_ALLOC, &req, sizeof(req)); if (ret) return ret; @@ -104,19 +106,39 @@ abi16_chan_nve0(struct nouveau_object *obj) return 0; } -drm_private int +static int abi16_engobj(struct nouveau_object *obj) { + struct nouveau_drm *drm = nouveau_drm(obj); struct drm_nouveau_grobj_alloc req = { .channel = obj->parent->handle, .handle = obj->handle, .class = obj->oclass, }; - struct nouveau_device *dev; int ret; - dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); - ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC, + /* Older kernel versions did not have the concept of nouveau- + * specific classes and abused some NVIDIA-assigned ones for + * a SW class. The ABI16 layer has compatibility in place to + * translate these older identifiers to the newer ones. + * + * Clients that have been updated to use NVIF are required to + * use the newer class identifiers, which means that they'll + * break if running on an older kernel. + * + * To handle this case, when using ABI16, we translate to the + * older values which work on any kernel. + */ + switch (req.class) { + case NVIF_CLASS_SW_NV04 : req.class = 0x006e; break; + case NVIF_CLASS_SW_NV10 : req.class = 0x016e; break; + case NVIF_CLASS_SW_NV50 : req.class = 0x506e; break; + case NVIF_CLASS_SW_GF100: req.class = 0x906e; break; + default: + break; + } + + ret = drmCommandWrite(drm->fd, DRM_NOUVEAU_GROBJ_ALLOC, &req, sizeof(req)); if (ret) return ret; @@ -125,20 +147,19 @@ abi16_engobj(struct nouveau_object *obj) return 0; } -drm_private int +static int abi16_ntfy(struct nouveau_object *obj) { + struct nouveau_drm *drm = nouveau_drm(obj); struct nv04_notify *ntfy = obj->data; struct drm_nouveau_notifierobj_alloc req = { .channel = obj->parent->handle, .handle = ntfy->object->handle, .size = ntfy->length, }; - struct nouveau_device *dev; int ret; - dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, &req, sizeof(req)); if (ret) return ret; @@ -148,6 +169,110 @@ abi16_ntfy(struct nouveau_object *obj) return 0; } +drm_private int +abi16_sclass(struct nouveau_object *obj, struct nouveau_sclass **psclass) +{ + struct nouveau_sclass *sclass; + struct nouveau_device *dev; + + if (!(sclass = calloc(8, sizeof(*sclass)))) + return -ENOMEM; + *psclass = sclass; + + switch (obj->oclass) { + case NOUVEAU_FIFO_CHANNEL_CLASS: + /* Older kernel versions were exposing the wrong video engine + * classes on certain G98:GF100 boards. This has since been + * corrected, but ABI16 has compatibility in place to avoid + * breaking older userspace. + * + * Clients that have been updated to use NVIF are required to + * use the correct classes, which means that they'll break if + * running on an older kernel. + * + * To handle this issue, if using the older kernel interfaces, + * we'll magic up a list containing the vdec classes that the + * kernel will accept for these boards. Clients should make + * use of this information instead of hardcoding classes for + * specific chipsets. + */ + dev = (struct nouveau_device *)obj->parent; + if (dev->chipset >= 0x98 && + dev->chipset != 0xa0 && + dev->chipset < 0xc0) { + *sclass++ = (struct nouveau_sclass){ + GT212_MSVLD, -1, -1 + }; + *sclass++ = (struct nouveau_sclass){ + GT212_MSPDEC, -1, -1 + }; + *sclass++ = (struct nouveau_sclass){ + GT212_MSPPP, -1, -1 + }; + } + break; + default: + break; + } + + return sclass - *psclass; +} + +drm_private void +abi16_delete(struct nouveau_object *obj) +{ + struct nouveau_drm *drm = nouveau_drm(obj); + if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) { + struct drm_nouveau_channel_free req; + req.channel = obj->handle; + drmCommandWrite(drm->fd, DRM_NOUVEAU_CHANNEL_FREE, + &req, sizeof(req)); + } else { + struct drm_nouveau_gpuobj_free req; + req.channel = obj->parent->handle; + req.handle = obj->handle; + drmCommandWrite(drm->fd, DRM_NOUVEAU_GPUOBJ_FREE, + &req, sizeof(req)); + } +} + +drm_private bool +abi16_object(struct nouveau_object *obj, int (**func)(struct nouveau_object *)) +{ + struct nouveau_object *parent = obj->parent; + + /* nouveau_object::length is (ab)used to determine whether the + * object is a legacy object (!=0), or a real NVIF object. + */ + if ((parent->length != 0 && parent->oclass == NOUVEAU_DEVICE_CLASS) || + (parent->length == 0 && parent->oclass == NV_DEVICE)) { + if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) { + struct nouveau_device *dev = (void *)parent; + if (dev->chipset < 0xc0) + *func = abi16_chan_nv04; + else + if (dev->chipset < 0xe0) + *func = abi16_chan_nvc0; + else + *func = abi16_chan_nve0; + return true; + } + } else + if ((parent->length != 0 && + parent->oclass == NOUVEAU_FIFO_CHANNEL_CLASS)) { + if (obj->oclass == NOUVEAU_NOTIFIER_CLASS) { + *func = abi16_ntfy; + return true; + } + + *func = abi16_engobj; + return false; /* try NVIF, if supported, before calling func */ + } + + *func = NULL; + return false; +} + drm_private void abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info) { @@ -187,6 +312,7 @@ abi16_bo_init(struct nouveau_bo *bo, uint32_t alignment, union nouveau_bo_config *config) { struct nouveau_device *dev = bo->device; + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct drm_nouveau_gem_new req = {}; struct drm_nouveau_gem_info *info = &req.info; int ret; @@ -229,7 +355,7 @@ abi16_bo_init(struct nouveau_bo *bo, uint32_t alignment, if (!nouveau_device(dev)->have_bo_usage) info->tile_flags &= 0x0000ff00; - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req)); if (ret == 0) abi16_bo_info(bo, &req.info); diff --git a/lib/libdrm/nouveau/libdrm_nouveau.pc.in b/lib/libdrm/nouveau/libdrm_nouveau.pc.in index 9abfd811d..7d0622e9a 100644 --- a/lib/libdrm/nouveau/libdrm_nouveau.pc.in +++ b/lib/libdrm/nouveau/libdrm_nouveau.pc.in @@ -7,5 +7,5 @@ Name: libdrm_nouveau Description: Userspace interface to nouveau kernel DRM services Version: @PACKAGE_VERSION@ Libs: -L${libdir} -ldrm_nouveau -Cflags: -I${includedir} -I${includedir}/libdrm +Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/libdrm/nouveau Requires.private: libdrm diff --git a/lib/libdrm/nouveau/nouveau-symbol-check b/lib/libdrm/nouveau/nouveau-symbol-check index 0fef56323..b265cea46 100755 --- a/lib/libdrm/nouveau/nouveau-symbol-check +++ b/lib/libdrm/nouveau/nouveau-symbol-check @@ -27,13 +27,19 @@ nouveau_bufctx_reset nouveau_client_del nouveau_client_new nouveau_device_del +nouveau_device_new nouveau_device_open nouveau_device_open_existing nouveau_device_wrap +nouveau_drm_del +nouveau_drm_new nouveau_getparam nouveau_object_del -nouveau_object_find +nouveau_object_mclass +nouveau_object_mthd nouveau_object_new +nouveau_object_sclass_get +nouveau_object_sclass_put nouveau_pushbuf_bufctx nouveau_pushbuf_data nouveau_pushbuf_del diff --git a/lib/libdrm/nouveau/nouveau.c b/lib/libdrm/nouveau/nouveau.c index 97fd77b93..e113a8fe7 100644 --- a/lib/libdrm/nouveau/nouveau.c +++ b/lib/libdrm/nouveau/nouveau.c @@ -45,6 +45,11 @@ #include "nouveau.h" #include "private.h" +#include "nvif/class.h" +#include "nvif/cl0080.h" +#include "nvif/ioctl.h" +#include "nvif/unpack.h" + #ifdef DEBUG drm_private uint32_t nouveau_debug = 0; @@ -59,6 +64,295 @@ debug_init(char *args) } #endif +static int +nouveau_object_ioctl(struct nouveau_object *obj, void *data, uint32_t size) +{ + struct nouveau_drm *drm = nouveau_drm(obj); + union { + struct nvif_ioctl_v0 v0; + } *args = data; + uint32_t argc = size; + int ret = -ENOSYS; + + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { + if (!obj->length) { + if (obj != &drm->client) + args->v0.object = (unsigned long)(void *)obj; + else + args->v0.object = 0; + args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; + args->v0.route = 0x00; + } else { + args->v0.route = 0xff; + args->v0.token = obj->handle; + } + } else + return ret; + + return drmCommandWriteRead(drm->fd, DRM_NOUVEAU_NVIF, args, argc); +} + +int +nouveau_object_mthd(struct nouveau_object *obj, + uint32_t mthd, void *data, uint32_t size) +{ + struct nouveau_drm *drm = nouveau_drm(obj); + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_mthd_v0 mthd; + } *args; + uint32_t argc = sizeof(*args) + size; + uint8_t stack[128]; + int ret; + + if (!drm->nvif) + return -ENOSYS; + + if (argc > sizeof(stack)) { + if (!(args = malloc(argc))) + return -ENOMEM; + } else { + args = (void *)stack; + } + args->ioctl.version = 0; + args->ioctl.type = NVIF_IOCTL_V0_MTHD; + args->mthd.version = 0; + args->mthd.method = mthd; + + memcpy(args->mthd.data, data, size); + ret = nouveau_object_ioctl(obj, args, argc); + memcpy(data, args->mthd.data, size); + if (args != (void *)stack) + free(args); + return ret; +} + +void +nouveau_object_sclass_put(struct nouveau_sclass **psclass) +{ + free(*psclass); + *psclass = NULL; +} + +int +nouveau_object_sclass_get(struct nouveau_object *obj, + struct nouveau_sclass **psclass) +{ + struct nouveau_drm *drm = nouveau_drm(obj); + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_sclass_v0 sclass; + } *args = NULL; + struct nouveau_sclass *sclass; + int ret, cnt = 0, i; + uint32_t size; + + if (!drm->nvif) + return abi16_sclass(obj, psclass); + + while (1) { + size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]); + if (!(args = malloc(size))) + return -ENOMEM; + args->ioctl.version = 0; + args->ioctl.type = NVIF_IOCTL_V0_SCLASS; + args->sclass.version = 0; + args->sclass.count = cnt; + + ret = nouveau_object_ioctl(obj, args, size); + if (ret == 0 && args->sclass.count <= cnt) + break; + cnt = args->sclass.count; + free(args); + if (ret != 0) + return ret; + } + + if ((sclass = calloc(args->sclass.count, sizeof(*sclass)))) { + for (i = 0; i < args->sclass.count; i++) { + sclass[i].oclass = args->sclass.oclass[i].oclass; + sclass[i].minver = args->sclass.oclass[i].minver; + sclass[i].maxver = args->sclass.oclass[i].maxver; + } + *psclass = sclass; + ret = args->sclass.count; + } else { + ret = -ENOMEM; + } + + free(args); + return ret; +} + +int +nouveau_object_mclass(struct nouveau_object *obj, + const struct nouveau_mclass *mclass) +{ + struct nouveau_sclass *sclass; + int ret = -ENODEV; + int cnt, i, j; + + cnt = nouveau_object_sclass_get(obj, &sclass); + if (cnt < 0) + return cnt; + + for (i = 0; ret < 0 && mclass[i].oclass; i++) { + for (j = 0; j < cnt; j++) { + if (mclass[i].oclass == sclass[j].oclass && + mclass[i].version >= sclass[j].minver && + mclass[i].version <= sclass[j].maxver) { + ret = i; + break; + } + } + } + + nouveau_object_sclass_put(&sclass); + return ret; +} + +static void +nouveau_object_fini(struct nouveau_object *obj) +{ + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_del del; + } args = { + .ioctl.type = NVIF_IOCTL_V0_DEL, + }; + + if (obj->data) { + abi16_delete(obj); + free(obj->data); + obj->data = NULL; + return; + } + + nouveau_object_ioctl(obj, &args, sizeof(args)); +} + +static int +nouveau_object_init(struct nouveau_object *parent, uint32_t handle, + int32_t oclass, void *data, uint32_t size, + struct nouveau_object *obj) +{ + struct nouveau_drm *drm = nouveau_drm(parent); + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_new_v0 new; + } *args; + uint32_t argc = sizeof(*args) + size; + int (*func)(struct nouveau_object *); + int ret = -ENOSYS; + + obj->parent = parent; + obj->handle = handle; + obj->oclass = oclass; + obj->length = 0; + obj->data = NULL; + + if (!abi16_object(obj, &func) && drm->nvif) { + if (!(args = malloc(argc))) + return -ENOMEM; + args->ioctl.version = 0; + args->ioctl.type = NVIF_IOCTL_V0_NEW; + args->new.version = 0; + args->new.route = NVIF_IOCTL_V0_ROUTE_NVIF; + args->new.token = (unsigned long)(void *)obj; + args->new.object = (unsigned long)(void *)obj; + args->new.handle = handle; + args->new.oclass = oclass; + memcpy(args->new.data, data, size); + ret = nouveau_object_ioctl(parent, args, argc); + memcpy(data, args->new.data, size); + free(args); + } else + if (func) { + obj->length = size ? size : sizeof(struct nouveau_object *); + if (!(obj->data = malloc(obj->length))) + return -ENOMEM; + if (data) + memcpy(obj->data, data, obj->length); + *(struct nouveau_object **)obj->data = obj; + + ret = func(obj); + } + + if (ret) { + nouveau_object_fini(obj); + return ret; + } + + return 0; +} + +int +nouveau_object_new(struct nouveau_object *parent, uint64_t handle, + uint32_t oclass, void *data, uint32_t length, + struct nouveau_object **pobj) +{ + struct nouveau_object *obj; + int ret; + + if (!(obj = malloc(sizeof(*obj)))) + return -ENOMEM; + + ret = nouveau_object_init(parent, handle, oclass, data, length, obj); + if (ret) { + free(obj); + return ret; + } + + *pobj = obj; + return 0; +} + +void +nouveau_object_del(struct nouveau_object **pobj) +{ + struct nouveau_object *obj = *pobj; + if (obj) { + nouveau_object_fini(obj); + free(obj); + *pobj = NULL; + } +} + +void +nouveau_drm_del(struct nouveau_drm **pdrm) +{ + free(*pdrm); + *pdrm = NULL; +} + +int +nouveau_drm_new(int fd, struct nouveau_drm **pdrm) +{ + struct nouveau_drm *drm; + drmVersionPtr ver; + +#ifdef DEBUG + debug_init(getenv("NOUVEAU_LIBDRM_DEBUG")); +#endif + + if (!(drm = calloc(1, sizeof(*drm)))) + return -ENOMEM; + drm->fd = fd; + + if (!(ver = drmGetVersion(fd))) { + nouveau_drm_del(&drm); + return -EINVAL; + } + *pdrm = drm; + + drm->version = (ver->version_major << 24) | + (ver->version_minor << 8) | + ver->version_patchlevel; + drm->nvif = (drm->version >= 0x01000301); + drmFreeVersion(ver); + return 0; +} + /* this is the old libdrm's version of nouveau_device_wrap(), the symbol * is kept here to prevent AIGLX from crashing if the DDX is linked against * the new libdrm, but the DRI driver against the old @@ -71,80 +365,124 @@ nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd, } int -nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) +nouveau_device_new(struct nouveau_object *parent, int32_t oclass, + void *data, uint32_t size, struct nouveau_device **pdev) { - struct nouveau_device_priv *nvdev = calloc(1, sizeof(*nvdev)); - struct nouveau_device *dev = &nvdev->base; - uint64_t chipset, vram, gart, bousage; - drmVersionPtr ver; - int ret; + struct nv_device_info_v0 info = {}; + union { + struct nv_device_v0 v0; + } *args = data; + uint32_t argc = size; + struct nouveau_drm *drm = nouveau_drm(parent); + struct nouveau_device_priv *nvdev; + struct nouveau_device *dev; + uint64_t v; char *tmp; + int ret = -ENOSYS; -#ifdef DEBUG - debug_init(getenv("NOUVEAU_LIBDRM_DEBUG")); -#endif + if (oclass != NV_DEVICE || + nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)) + return ret; - if (!nvdev) + if (!(nvdev = calloc(1, sizeof(*nvdev)))) return -ENOMEM; - ret = pthread_mutex_init(&nvdev->lock, NULL); - if (ret) { - free(nvdev); - return ret; - } + dev = *pdev = &nvdev->base; + dev->fd = -1; - nvdev->base.fd = fd; + if (drm->nvif) { + ret = nouveau_object_init(parent, 0, oclass, args, argc, + &dev->object); + if (ret) + goto done; - ver = drmGetVersion(fd); - if (ver) dev->drm_version = (ver->version_major << 24) | - (ver->version_minor << 8) | - ver->version_patchlevel; - drmFreeVersion(ver); + info.version = 0; - if ( dev->drm_version != 0x00000010 && - (dev->drm_version < 0x01000000 || - dev->drm_version >= 0x02000000)) { - nouveau_device_del(&dev); - return -EINVAL; - } + ret = nouveau_object_mthd(&dev->object, NV_DEVICE_V0_INFO, + &info, sizeof(info)); + if (ret) + goto done; + + nvdev->base.chipset = info.chipset; + nvdev->have_bo_usage = true; + } else + if (args->v0.device == ~0ULL) { + nvdev->base.object.parent = &drm->client; + nvdev->base.object.handle = ~0ULL; + nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; + nvdev->base.object.length = ~0; + + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &v); + if (ret) + goto done; + nvdev->base.chipset = v; - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset); - if (ret == 0) - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram); - if (ret == 0) - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart); - if (ret) { - nouveau_device_del(&dev); - return ret; - } + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &v); + if (ret == 0) + nvdev->have_bo_usage = (v != 0); + } else + return -ENOSYS; - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage); - if (ret == 0) - nvdev->have_bo_usage = (bousage != 0); + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &v); + if (ret) + goto done; + nvdev->base.vram_size = v; - nvdev->close = close; + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &v); + if (ret) + goto done; + nvdev->base.gart_size = v; tmp = getenv("NOUVEAU_LIBDRM_VRAM_LIMIT_PERCENT"); if (tmp) nvdev->vram_limit_percent = atoi(tmp); else nvdev->vram_limit_percent = 80; + + nvdev->base.vram_limit = + (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100; + tmp = getenv("NOUVEAU_LIBDRM_GART_LIMIT_PERCENT"); if (tmp) nvdev->gart_limit_percent = atoi(tmp); else nvdev->gart_limit_percent = 80; - DRMINITLISTHEAD(&nvdev->bo_list); - nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; - nvdev->base.lib_version = 0x01000000; - nvdev->base.chipset = chipset; - nvdev->base.vram_size = vram; - nvdev->base.gart_size = gart; - nvdev->base.vram_limit = - (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100; + nvdev->base.gart_limit = (nvdev->base.gart_size * nvdev->gart_limit_percent) / 100; - *pdev = &nvdev->base; + ret = pthread_mutex_init(&nvdev->lock, NULL); + DRMINITLISTHEAD(&nvdev->bo_list); +done: + if (ret) + nouveau_device_del(pdev); + return ret; +} + +int +nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) +{ + struct nouveau_drm *drm; + struct nouveau_device_priv *nvdev; + int ret; + + ret = nouveau_drm_new(fd, &drm); + if (ret) + return ret; + drm->nvif = false; + + ret = nouveau_device_new(&drm->client, NV_DEVICE, + &(struct nv_device_v0) { + .device = ~0ULL, + }, sizeof(struct nv_device_v0), pdev); + if (ret) { + nouveau_drm_del(&drm); + return ret; + } + + nvdev = nouveau_device(*pdev); + nvdev->base.fd = drm->fd; + nvdev->base.drm_version = drm->version; + nvdev->close = close; return 0; } @@ -165,10 +503,15 @@ nouveau_device_del(struct nouveau_device **pdev) { struct nouveau_device_priv *nvdev = nouveau_device(*pdev); if (nvdev) { - if (nvdev->close) - drmClose(nvdev->base.fd); free(nvdev->client); pthread_mutex_destroy(&nvdev->lock); + if (nvdev->base.fd >= 0) { + struct nouveau_drm *drm = + nouveau_drm(&nvdev->base.object); + nouveau_drm_del(&drm); + if (nvdev->close) + drmClose(nvdev->base.fd); + } free(nvdev); *pdev = NULL; } @@ -177,8 +520,9 @@ nouveau_device_del(struct nouveau_device **pdev) int nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value) { + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct drm_nouveau_getparam r = { .param = param }; - int fd = dev->fd, ret = + int fd = drm->fd, ret = drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r)); *value = r.value; return ret; @@ -187,8 +531,9 @@ nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value) int nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value) { + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct drm_nouveau_setparam r = { .param = param, .value = value }; - return drmCommandWrite(dev->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r)); + return drmCommandWrite(drm->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r)); } int @@ -246,106 +591,10 @@ nouveau_client_del(struct nouveau_client **pclient) } } -int -nouveau_object_new(struct nouveau_object *parent, uint64_t handle, - uint32_t oclass, void *data, uint32_t length, - struct nouveau_object **pobj) -{ - struct nouveau_device *dev; - struct nouveau_object *obj; - int ret = -EINVAL; - - if (length == 0) - length = sizeof(struct nouveau_object *); - obj = malloc(sizeof(*obj) + length); - obj->parent = parent; - obj->handle = handle; - obj->oclass = oclass; - obj->length = length; - obj->data = obj + 1; - if (data) - memcpy(obj->data, data, length); - *(struct nouveau_object **)obj->data = obj; - - dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); - switch (parent->oclass) { - case NOUVEAU_DEVICE_CLASS: - switch (obj->oclass) { - case NOUVEAU_FIFO_CHANNEL_CLASS: - { - if (dev->chipset < 0xc0) - ret = abi16_chan_nv04(obj); - else - if (dev->chipset < 0xe0) - ret = abi16_chan_nvc0(obj); - else - ret = abi16_chan_nve0(obj); - } - break; - default: - break; - } - break; - case NOUVEAU_FIFO_CHANNEL_CLASS: - switch (obj->oclass) { - case NOUVEAU_NOTIFIER_CLASS: - ret = abi16_ntfy(obj); - break; - default: - ret = abi16_engobj(obj); - break; - } - default: - break; - } - - if (ret) { - free(obj); - return ret; - } - - *pobj = obj; - return 0; -} - -void -nouveau_object_del(struct nouveau_object **pobj) -{ - struct nouveau_object *obj = *pobj; - struct nouveau_device *dev; - if (obj) { - dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); - if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) { - struct drm_nouveau_channel_free req; - req.channel = obj->handle; - drmCommandWrite(dev->fd, DRM_NOUVEAU_CHANNEL_FREE, - &req, sizeof(req)); - } else { - struct drm_nouveau_gpuobj_free req; - req.channel = obj->parent->handle; - req.handle = obj->handle; - drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE, - &req, sizeof(req)); - } - } - free(obj); - *pobj = NULL; -} - -void * -nouveau_object_find(struct nouveau_object *obj, uint32_t pclass) -{ - while (obj && obj->oclass != pclass) { - obj = obj->parent; - if (pclass == NOUVEAU_PARENT_CLASS) - break; - } - return obj; -} - static void nouveau_bo_del(struct nouveau_bo *bo) { + struct nouveau_drm *drm = nouveau_drm(&bo->device->object); struct nouveau_device_priv *nvdev = nouveau_device(bo->device); struct nouveau_bo_priv *nvbo = nouveau_bo(bo); struct drm_gem_close req = { .handle = bo->handle }; @@ -362,11 +611,11 @@ nouveau_bo_del(struct nouveau_bo *bo) * might cause the bo to be closed accidentally while * re-importing. */ - drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req); + drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &req); } pthread_mutex_unlock(&nvdev->lock); } else { - drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req); + drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &req); } if (bo->map) drm_munmap(bo->map, bo->size); @@ -403,6 +652,7 @@ static int nouveau_bo_wrap_locked(struct nouveau_device *dev, uint32_t handle, struct nouveau_bo **pbo, int name) { + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct nouveau_device_priv *nvdev = nouveau_device(dev); struct drm_nouveau_gem_info req = { .handle = handle }; struct nouveau_bo_priv *nvbo; @@ -432,7 +682,7 @@ nouveau_bo_wrap_locked(struct nouveau_device *dev, uint32_t handle, } } - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_INFO, &req, sizeof(req)); if (ret) return ret; @@ -479,6 +729,7 @@ int nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name, struct nouveau_bo **pbo) { + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct nouveau_device_priv *nvdev = nouveau_device(dev); struct nouveau_bo_priv *nvbo; struct drm_gem_open req = { .name = name }; @@ -494,7 +745,7 @@ nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name, } } - ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req); + ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &req); if (ret == 0) { ret = nouveau_bo_wrap_locked(dev, req.handle, pbo, name); } @@ -507,11 +758,12 @@ int nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name) { struct drm_gem_flink req = { .handle = bo->handle }; + struct nouveau_drm *drm = nouveau_drm(&bo->device->object); struct nouveau_bo_priv *nvbo = nouveau_bo(bo); *name = nvbo->name; if (!*name) { - int ret = drmIoctl(bo->device->fd, DRM_IOCTL_GEM_FLINK, &req); + int ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &req); if (ret) { *name = 0; @@ -542,6 +794,7 @@ int nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, struct nouveau_bo **bo) { + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct nouveau_device_priv *nvdev = nouveau_device(dev); int ret; unsigned int handle; @@ -549,7 +802,7 @@ nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, nouveau_bo_ref(NULL, bo); pthread_mutex_lock(&nvdev->lock); - ret = drmPrimeFDToHandle(dev->fd, prime_fd, &handle); + ret = drmPrimeFDToHandle(drm->fd, prime_fd, &handle); if (ret == 0) { ret = nouveau_bo_wrap_locked(dev, handle, bo, 0); } @@ -560,10 +813,11 @@ nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, int nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd) { + struct nouveau_drm *drm = nouveau_drm(&bo->device->object); struct nouveau_bo_priv *nvbo = nouveau_bo(bo); int ret; - ret = drmPrimeHandleToFD(bo->device->fd, nvbo->base.handle, DRM_CLOEXEC, prime_fd); + ret = drmPrimeHandleToFD(drm->fd, nvbo->base.handle, DRM_CLOEXEC, prime_fd); if (ret) return ret; @@ -575,6 +829,7 @@ int nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) { + struct nouveau_drm *drm = nouveau_drm(&bo->device->object); struct nouveau_bo_priv *nvbo = nouveau_bo(bo); struct drm_nouveau_gem_cpu_prep req; struct nouveau_pushbuf *push; @@ -598,7 +853,7 @@ nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access, if (access & NOUVEAU_BO_NOBLOCK) req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT; - ret = drmCommandWrite(bo->device->fd, DRM_NOUVEAU_GEM_CPU_PREP, + ret = drmCommandWrite(drm->fd, DRM_NOUVEAU_GEM_CPU_PREP, &req, sizeof(req)); if (ret == 0) nvbo->access = 0; @@ -609,10 +864,11 @@ int nouveau_bo_map(struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) { + struct nouveau_drm *drm = nouveau_drm(&bo->device->object); struct nouveau_bo_priv *nvbo = nouveau_bo(bo); if (bo->map == NULL) { bo->map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, - MAP_SHARED, bo->device->fd, nvbo->map_handle); + MAP_SHARED, drm->fd, nvbo->map_handle); if (bo->map == MAP_FAILED) { bo->map = NULL; return -errno; diff --git a/lib/libdrm/nouveau/nouveau.h b/lib/libdrm/nouveau/nouveau.h index 4adda0e35..335ce77dc 100644 --- a/lib/libdrm/nouveau/nouveau.h +++ b/lib/libdrm/nouveau/nouveau.h @@ -4,76 +4,66 @@ #include <stdint.h> #include <stdbool.h> -#define NOUVEAU_DEVICE_CLASS 0x80000000 -#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001 -#define NOUVEAU_NOTIFIER_CLASS 0x80000002 -#define NOUVEAU_PARENT_CLASS 0xffffffff +/* Supported class information, provided by the kernel */ +struct nouveau_sclass { + int32_t oclass; + int minver; + int maxver; +}; -struct nouveau_list { - struct nouveau_list *prev; - struct nouveau_list *next; +/* Client-provided array describing class versions that are desired. + * + * These are used to match against the kernel's list of supported classes. + */ +struct nouveau_mclass { + int32_t oclass; + int version; + void *data; }; struct nouveau_object { struct nouveau_object *parent; uint64_t handle; uint32_t oclass; - uint32_t length; - void *data; -}; - -struct nouveau_fifo { - struct nouveau_object *object; - uint32_t channel; - uint32_t pushbuf; - uint64_t unused1[3]; -}; - -struct nv04_fifo { - struct nouveau_fifo base; - uint32_t vram; - uint32_t gart; - uint32_t notify; -}; - -struct nvc0_fifo { - struct nouveau_fifo base; - uint32_t notify; + uint32_t length; /* deprecated */ + void *data; /* deprecated */ }; -#define NVE0_FIFO_ENGINE_GR 0x00000001 -#define NVE0_FIFO_ENGINE_VP 0x00000002 -#define NVE0_FIFO_ENGINE_PPP 0x00000004 -#define NVE0_FIFO_ENGINE_BSP 0x00000008 -#define NVE0_FIFO_ENGINE_CE0 0x00000010 -#define NVE0_FIFO_ENGINE_CE1 0x00000020 -#define NVE0_FIFO_ENGINE_ENC 0x00000040 +int nouveau_object_new(struct nouveau_object *parent, uint64_t handle, + uint32_t oclass, void *data, uint32_t length, + struct nouveau_object **); +void nouveau_object_del(struct nouveau_object **); +int nouveau_object_mthd(struct nouveau_object *, uint32_t mthd, + void *data, uint32_t size); +int nouveau_object_sclass_get(struct nouveau_object *, + struct nouveau_sclass **); +void nouveau_object_sclass_put(struct nouveau_sclass **); +int nouveau_object_mclass(struct nouveau_object *, + const struct nouveau_mclass *); -struct nve0_fifo { - struct { - struct nouveau_fifo base; - uint32_t notify; - }; - uint32_t engine; +struct nouveau_drm { + struct nouveau_object client; + int fd; + uint32_t version; + bool nvif; }; -struct nv04_notify { - struct nouveau_object *object; - uint32_t offset; - uint32_t length; -}; +static inline struct nouveau_drm * +nouveau_drm(struct nouveau_object *obj) +{ + while (obj && obj->parent) + obj = obj->parent; + return (struct nouveau_drm *)obj; +} -int nouveau_object_new(struct nouveau_object *parent, uint64_t handle, - uint32_t oclass, void *data, uint32_t length, - struct nouveau_object **); -void nouveau_object_del(struct nouveau_object **); -void *nouveau_object_find(struct nouveau_object *, uint32_t parent_class); +int nouveau_drm_new(int fd, struct nouveau_drm **); +void nouveau_drm_del(struct nouveau_drm **); struct nouveau_device { struct nouveau_object object; - int fd; - uint32_t lib_version; - uint32_t drm_version; + int fd; /* deprecated */ + uint32_t lib_version; /* deprecated */ + uint32_t drm_version; /* deprecated */ uint32_t chipset; uint64_t vram_size; uint64_t gart_size; @@ -81,18 +71,23 @@ struct nouveau_device { uint64_t gart_limit; }; -int nouveau_device_wrap(int fd, int close, struct nouveau_device **); -int nouveau_device_open(const char *busid, struct nouveau_device **); +int nouveau_device_new(struct nouveau_object *parent, int32_t oclass, + void *data, uint32_t size, struct nouveau_device **); void nouveau_device_del(struct nouveau_device **); -int nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t *value); -int nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value); + +int nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t *value); +int nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value); + +/* deprecated */ +int nouveau_device_wrap(int fd, int close, struct nouveau_device **); +int nouveau_device_open(const char *busid, struct nouveau_device **); struct nouveau_client { struct nouveau_device *device; int id; }; -int nouveau_client_new(struct nouveau_device *, struct nouveau_client **); +int nouveau_client_new(struct nouveau_device *, struct nouveau_client **); void nouveau_client_del(struct nouveau_client **); union nouveau_bo_config { @@ -139,22 +134,27 @@ struct nouveau_bo { union nouveau_bo_config config; }; -int nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align, - uint64_t size, union nouveau_bo_config *, +int nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align, + uint64_t size, union nouveau_bo_config *, + struct nouveau_bo **); +int nouveau_bo_wrap(struct nouveau_device *, uint32_t handle, struct nouveau_bo **); -int nouveau_bo_wrap(struct nouveau_device *, uint32_t handle, - struct nouveau_bo **); -int nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name, - struct nouveau_bo **); -int nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name); +int nouveau_bo_name_ref(struct nouveau_device *v, uint32_t name, + struct nouveau_bo **); +int nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name); void nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **); -int nouveau_bo_map(struct nouveau_bo *, uint32_t access, +int nouveau_bo_map(struct nouveau_bo *, uint32_t access, + struct nouveau_client *); +int nouveau_bo_wait(struct nouveau_bo *, uint32_t access, struct nouveau_client *); -int nouveau_bo_wait(struct nouveau_bo *, uint32_t access, - struct nouveau_client *); -int nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, - struct nouveau_bo **); -int nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd); +int nouveau_bo_prime_handle_ref(struct nouveau_device *, int prime_fd, + struct nouveau_bo **); +int nouveau_bo_set_prime(struct nouveau_bo *, int *prime_fd); + +struct nouveau_list { + struct nouveau_list *prev; + struct nouveau_list *next; +}; struct nouveau_bufref { struct nouveau_list thead; @@ -176,8 +176,8 @@ struct nouveau_bufctx { int relocs; }; -int nouveau_bufctx_new(struct nouveau_client *, int bins, - struct nouveau_bufctx **); +int nouveau_bufctx_new(struct nouveau_client *, int bins, + struct nouveau_bufctx **); void nouveau_bufctx_del(struct nouveau_bufctx **); struct nouveau_bufref * nouveau_bufctx_refn(struct nouveau_bufctx *, int bin, @@ -206,16 +206,16 @@ struct nouveau_pushbuf_refn { uint32_t flags; }; -int nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object *channel, - int nr, uint32_t size, bool immediate, - struct nouveau_pushbuf **); +int nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object *chan, + int nr, uint32_t size, bool immediate, + struct nouveau_pushbuf **); void nouveau_pushbuf_del(struct nouveau_pushbuf **); -int nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords, - uint32_t relocs, uint32_t pushes); +int nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords, + uint32_t relocs, uint32_t pushes); void nouveau_pushbuf_data(struct nouveau_pushbuf *, struct nouveau_bo *, uint64_t offset, uint64_t length); -int nouveau_pushbuf_refn(struct nouveau_pushbuf *, - struct nouveau_pushbuf_refn *, int nr); +int nouveau_pushbuf_refn(struct nouveau_pushbuf *, + struct nouveau_pushbuf_refn *, int nr); /* Emits a reloc into the push buffer at the current position, you *must* * have previously added the referenced buffer to a buffer context, and * validated it against the current push buffer. @@ -223,10 +223,54 @@ int nouveau_pushbuf_refn(struct nouveau_pushbuf *, void nouveau_pushbuf_reloc(struct nouveau_pushbuf *, struct nouveau_bo *, uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor); -int nouveau_pushbuf_validate(struct nouveau_pushbuf *); +int nouveau_pushbuf_validate(struct nouveau_pushbuf *); uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *, struct nouveau_bo *); -int nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object *channel); +int nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object *chan); struct nouveau_bufctx * nouveau_pushbuf_bufctx(struct nouveau_pushbuf *, struct nouveau_bufctx *); +#define NOUVEAU_DEVICE_CLASS 0x80000000 +#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001 +#define NOUVEAU_NOTIFIER_CLASS 0x80000002 + +struct nouveau_fifo { + struct nouveau_object *object; + uint32_t channel; + uint32_t pushbuf; + uint64_t unused1[3]; +}; + +struct nv04_fifo { + struct nouveau_fifo base; + uint32_t vram; + uint32_t gart; + uint32_t notify; +}; + +struct nvc0_fifo { + struct nouveau_fifo base; + uint32_t notify; +}; + +#define NVE0_FIFO_ENGINE_GR 0x00000001 +#define NVE0_FIFO_ENGINE_VP 0x00000002 +#define NVE0_FIFO_ENGINE_PPP 0x00000004 +#define NVE0_FIFO_ENGINE_BSP 0x00000008 +#define NVE0_FIFO_ENGINE_CE0 0x00000010 +#define NVE0_FIFO_ENGINE_CE1 0x00000020 +#define NVE0_FIFO_ENGINE_ENC 0x00000040 + +struct nve0_fifo { + struct { + struct nouveau_fifo base; + uint32_t notify; + }; + uint32_t engine; +}; + +struct nv04_notify { + struct nouveau_object *object; + uint32_t offset; + uint32_t length; +}; #endif diff --git a/lib/libdrm/nouveau/nvif/cl0080.h b/lib/libdrm/nouveau/nvif/cl0080.h new file mode 100644 index 000000000..331620a52 --- /dev/null +++ b/lib/libdrm/nouveau/nvif/cl0080.h @@ -0,0 +1,45 @@ +#ifndef __NVIF_CL0080_H__ +#define __NVIF_CL0080_H__ + +struct nv_device_v0 { + __u8 version; + __u8 pad01[7]; + __u64 device; /* device identifier, ~0 for client default */ +}; + +#define NV_DEVICE_V0_INFO 0x00 +#define NV_DEVICE_V0_TIME 0x01 + +struct nv_device_info_v0 { + __u8 version; +#define NV_DEVICE_INFO_V0_IGP 0x00 +#define NV_DEVICE_INFO_V0_PCI 0x01 +#define NV_DEVICE_INFO_V0_AGP 0x02 +#define NV_DEVICE_INFO_V0_PCIE 0x03 +#define NV_DEVICE_INFO_V0_SOC 0x04 + __u8 platform; + __u16 chipset; /* from NV_PMC_BOOT_0 */ + __u8 revision; /* from NV_PMC_BOOT_0 */ +#define NV_DEVICE_INFO_V0_TNT 0x01 +#define NV_DEVICE_INFO_V0_CELSIUS 0x02 +#define NV_DEVICE_INFO_V0_KELVIN 0x03 +#define NV_DEVICE_INFO_V0_RANKINE 0x04 +#define NV_DEVICE_INFO_V0_CURIE 0x05 +#define NV_DEVICE_INFO_V0_TESLA 0x06 +#define NV_DEVICE_INFO_V0_FERMI 0x07 +#define NV_DEVICE_INFO_V0_KEPLER 0x08 +#define NV_DEVICE_INFO_V0_MAXWELL 0x09 + __u8 family; + __u8 pad06[2]; + __u64 ram_size; + __u64 ram_user; + char chip[16]; + char name[64]; +}; + +struct nv_device_time_v0 { + __u8 version; + __u8 pad01[7]; + __u64 time; +}; +#endif diff --git a/lib/libdrm/nouveau/nvif/cl9097.h b/lib/libdrm/nouveau/nvif/cl9097.h new file mode 100644 index 000000000..4057676d2 --- /dev/null +++ b/lib/libdrm/nouveau/nvif/cl9097.h @@ -0,0 +1,44 @@ +#ifndef __NVIF_CL9097_H__ +#define __NVIF_CL9097_H__ + +#define FERMI_A_ZBC_COLOR 0x00 +#define FERMI_A_ZBC_DEPTH 0x01 + +struct fermi_a_zbc_color_v0 { + __u8 version; +#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO 0x01 +#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE 0x02 +#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32 0x04 +#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16 0x08 +#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16 0x0c +#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16 0x10 +#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16 0x14 +#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16 0x16 +#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8 0x18 +#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8 0x1c +#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10 0x20 +#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10 0x24 +#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8 0x28 +#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8 0x2c +#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8 0x30 +#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8 0x34 +#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8 0x38 +#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10 0x3c +#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11 0x40 + __u8 format; + __u8 index; + __u8 pad03[5]; + __u32 ds[4]; + __u32 l2[4]; +}; + +struct fermi_a_zbc_depth_v0 { + __u8 version; +#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32 0x01 + __u8 format; + __u8 index; + __u8 pad03[5]; + __u32 ds; + __u32 l2; +}; +#endif diff --git a/lib/libdrm/nouveau/nvif/class.h b/lib/libdrm/nouveau/nvif/class.h new file mode 100644 index 000000000..4179cd65a --- /dev/null +++ b/lib/libdrm/nouveau/nvif/class.h @@ -0,0 +1,141 @@ +#ifndef __NVIF_CLASS_H__ +#define __NVIF_CLASS_H__ + +/* these class numbers are made up by us, and not nvidia-assigned */ +#define NVIF_CLASS_CONTROL /* if0001.h */ -1 +#define NVIF_CLASS_PERFMON /* if0002.h */ -2 +#define NVIF_CLASS_PERFDOM /* if0003.h */ -3 +#define NVIF_CLASS_SW_NV04 /* if0004.h */ -4 +#define NVIF_CLASS_SW_NV10 /* if0005.h */ -5 +#define NVIF_CLASS_SW_NV50 /* if0005.h */ -6 +#define NVIF_CLASS_SW_GF100 /* if0005.h */ -7 + +/* the below match nvidia-assigned (either in hw, or sw) class numbers */ +#define NV_DEVICE /* cl0080.h */ 0x00000080 + +#define NV_DMA_FROM_MEMORY /* cl0002.h */ 0x00000002 +#define NV_DMA_TO_MEMORY /* cl0002.h */ 0x00000003 +#define NV_DMA_IN_MEMORY /* cl0002.h */ 0x0000003d + +#define FERMI_TWOD_A 0x0000902d + +#define FERMI_MEMORY_TO_MEMORY_FORMAT_A 0x00009039 + +#define KEPLER_INLINE_TO_MEMORY_A 0x0000a040 +#define KEPLER_INLINE_TO_MEMORY_B 0x0000a140 + +#define NV04_DISP /* cl0046.h */ 0x00000046 + +#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b +#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e +#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e +#define NV40_CHANNEL_DMA /* cl506b.h */ 0x0000406e +#define NV50_CHANNEL_DMA /* cl506e.h */ 0x0000506e +#define G82_CHANNEL_DMA /* cl826e.h */ 0x0000826e + +#define NV50_CHANNEL_GPFIFO /* cl506f.h */ 0x0000506f +#define G82_CHANNEL_GPFIFO /* cl826f.h */ 0x0000826f +#define FERMI_CHANNEL_GPFIFO /* cl906f.h */ 0x0000906f +#define KEPLER_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000a06f +#define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f + +#define NV50_DISP /* cl5070.h */ 0x00005070 +#define G82_DISP /* cl5070.h */ 0x00008270 +#define GT200_DISP /* cl5070.h */ 0x00008370 +#define GT214_DISP /* cl5070.h */ 0x00008570 +#define GT206_DISP /* cl5070.h */ 0x00008870 +#define GF110_DISP /* cl5070.h */ 0x00009070 +#define GK104_DISP /* cl5070.h */ 0x00009170 +#define GK110_DISP /* cl5070.h */ 0x00009270 +#define GM107_DISP /* cl5070.h */ 0x00009470 +#define GM204_DISP /* cl5070.h */ 0x00009570 + +#define NV31_MPEG 0x00003174 +#define G82_MPEG 0x00008274 + +#define NV74_VP2 0x00007476 + +#define NV50_DISP_CURSOR /* cl507a.h */ 0x0000507a +#define G82_DISP_CURSOR /* cl507a.h */ 0x0000827a +#define GT214_DISP_CURSOR /* cl507a.h */ 0x0000857a +#define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a +#define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a + +#define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b +#define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b +#define GT214_DISP_OVERLAY /* cl507b.h */ 0x0000857b +#define GF110_DISP_OVERLAY /* cl507b.h */ 0x0000907b +#define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b + +#define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c +#define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c +#define GT200_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000837c +#define GT214_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000857c +#define GF110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000907c +#define GK104_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000917c +#define GK110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000927c + +#define NV50_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000507d +#define G82_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000827d +#define GT200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000837d +#define GT214_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000857d +#define GT206_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000887d +#define GF110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000907d +#define GK104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000917d +#define GK110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000927d +#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d +#define GM204_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d + +#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e +#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e +#define GT200_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000837e +#define GT214_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000857e +#define GF110_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000907e +#define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e + +#define FERMI_A /* cl9097.h */ 0x00009097 +#define FERMI_B /* cl9097.h */ 0x00009197 +#define FERMI_C /* cl9097.h */ 0x00009297 + +#define KEPLER_A /* cl9097.h */ 0x0000a097 +#define KEPLER_B /* cl9097.h */ 0x0000a197 +#define KEPLER_C /* cl9097.h */ 0x0000a297 + +#define MAXWELL_A /* cl9097.h */ 0x0000b097 +#define MAXWELL_B /* cl9097.h */ 0x0000b197 + +#define NV74_BSP 0x000074b0 + +#define GT212_MSVLD 0x000085b1 +#define IGT21A_MSVLD 0x000086b1 +#define G98_MSVLD 0x000088b1 +#define GF100_MSVLD 0x000090b1 +#define GK104_MSVLD 0x000095b1 + +#define GT212_MSPDEC 0x000085b2 +#define G98_MSPDEC 0x000088b2 +#define GF100_MSPDEC 0x000090b2 +#define GK104_MSPDEC 0x000095b2 + +#define GT212_MSPPP 0x000085b3 +#define G98_MSPPP 0x000088b3 +#define GF100_MSPPP 0x000090b3 + +#define G98_SEC 0x000088b4 + +#define GT212_DMA 0x000085b5 +#define FERMI_DMA 0x000090b5 +#define KEPLER_DMA_COPY_A 0x0000a0b5 +#define MAXWELL_DMA_COPY_A 0x0000b0b5 + +#define FERMI_DECOMPRESS 0x000090b8 + +#define FERMI_COMPUTE_A 0x000090c0 +#define FERMI_COMPUTE_B 0x000091c0 +#define KEPLER_COMPUTE_A 0x0000a0c0 +#define KEPLER_COMPUTE_B 0x0000a1c0 +#define MAXWELL_COMPUTE_A 0x0000b0c0 +#define MAXWELL_COMPUTE_B 0x0000b1c0 + +#define NV74_CIPHER 0x000074c1 +#endif diff --git a/lib/libdrm/nouveau/nvif/if0002.h b/lib/libdrm/nouveau/nvif/if0002.h new file mode 100644 index 000000000..c04c91d0b --- /dev/null +++ b/lib/libdrm/nouveau/nvif/if0002.h @@ -0,0 +1,38 @@ +#ifndef __NVIF_IF0002_H__ +#define __NVIF_IF0002_H__ + +#define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00 +#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01 +#define NVIF_PERFMON_V0_QUERY_SOURCE 0x02 + +struct nvif_perfmon_query_domain_v0 { + __u8 version; + __u8 id; + __u8 counter_nr; + __u8 iter; + __u16 signal_nr; + __u8 pad05[2]; + char name[64]; +}; + +struct nvif_perfmon_query_signal_v0 { + __u8 version; + __u8 domain; + __u16 iter; + __u8 signal; + __u8 source_nr; + __u8 pad05[2]; + char name[64]; +}; + +struct nvif_perfmon_query_source_v0 { + __u8 version; + __u8 domain; + __u8 signal; + __u8 iter; + __u8 pad04[4]; + __u32 source; + __u32 mask; + char name[64]; +}; +#endif diff --git a/lib/libdrm/nouveau/nvif/if0003.h b/lib/libdrm/nouveau/nvif/if0003.h new file mode 100644 index 000000000..0cd03efb8 --- /dev/null +++ b/lib/libdrm/nouveau/nvif/if0003.h @@ -0,0 +1,33 @@ +#ifndef __NVIF_IF0003_H__ +#define __NVIF_IF0003_H__ + +struct nvif_perfdom_v0 { + __u8 version; + __u8 domain; + __u8 mode; + __u8 pad03[1]; + struct { + __u8 signal[4]; + __u64 source[4][8]; + __u16 logic_op; + } ctr[4]; +}; + +#define NVIF_PERFDOM_V0_INIT 0x00 +#define NVIF_PERFDOM_V0_SAMPLE 0x01 +#define NVIF_PERFDOM_V0_READ 0x02 + +struct nvif_perfdom_init { +}; + +struct nvif_perfdom_sample { +}; + +struct nvif_perfdom_read_v0 { + __u8 version; + __u8 pad01[7]; + __u32 ctr[4]; + __u32 clk; + __u8 pad04[4]; +}; +#endif diff --git a/lib/libdrm/nouveau/nvif/ioctl.h b/lib/libdrm/nouveau/nvif/ioctl.h new file mode 100644 index 000000000..c5f5eb83a --- /dev/null +++ b/lib/libdrm/nouveau/nvif/ioctl.h @@ -0,0 +1,132 @@ +#ifndef __NVIF_IOCTL_H__ +#define __NVIF_IOCTL_H__ + +#define NVIF_VERSION_LATEST 0x0000000000000000ULL + +struct nvif_ioctl_v0 { + __u8 version; +#define NVIF_IOCTL_V0_NOP 0x00 +#define NVIF_IOCTL_V0_SCLASS 0x01 +#define NVIF_IOCTL_V0_NEW 0x02 +#define NVIF_IOCTL_V0_DEL 0x03 +#define NVIF_IOCTL_V0_MTHD 0x04 +#define NVIF_IOCTL_V0_RD 0x05 +#define NVIF_IOCTL_V0_WR 0x06 +#define NVIF_IOCTL_V0_MAP 0x07 +#define NVIF_IOCTL_V0_UNMAP 0x08 +#define NVIF_IOCTL_V0_NTFY_NEW 0x09 +#define NVIF_IOCTL_V0_NTFY_DEL 0x0a +#define NVIF_IOCTL_V0_NTFY_GET 0x0b +#define NVIF_IOCTL_V0_NTFY_PUT 0x0c + __u8 type; + __u8 pad02[4]; +#define NVIF_IOCTL_V0_OWNER_NVIF 0x00 +#define NVIF_IOCTL_V0_OWNER_ANY 0xff + __u8 owner; +#define NVIF_IOCTL_V0_ROUTE_NVIF 0x00 +#define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff + __u8 route; + __u64 token; + __u64 object; + __u8 data[]; /* ioctl data (below) */ +}; + +struct nvif_ioctl_nop_v0 { + __u64 version; +}; + +struct nvif_ioctl_sclass_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 count; + __u8 pad02[6]; + struct nvif_ioctl_sclass_oclass_v0 { + __s32 oclass; + __s16 minver; + __s16 maxver; + } oclass[]; +}; + +struct nvif_ioctl_new_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 pad01[6]; + __u8 route; + __u64 token; + __u64 object; + __u32 handle; + __s32 oclass; + __u8 data[]; /* class data (class.h) */ +}; + +struct nvif_ioctl_del { +}; + +struct nvif_ioctl_rd_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 size; + __u8 pad02[2]; + __u32 data; + __u64 addr; +}; + +struct nvif_ioctl_wr_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 size; + __u8 pad02[2]; + __u32 data; + __u64 addr; +}; + +struct nvif_ioctl_map_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 pad01[3]; + __u32 length; + __u64 handle; +}; + +struct nvif_ioctl_unmap { +}; + +struct nvif_ioctl_ntfy_new_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 event; + __u8 index; + __u8 pad03[5]; + __u8 data[]; /* event request data (event.h) */ +}; + +struct nvif_ioctl_ntfy_del_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 index; + __u8 pad02[6]; +}; + +struct nvif_ioctl_ntfy_get_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 index; + __u8 pad02[6]; +}; + +struct nvif_ioctl_ntfy_put_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 index; + __u8 pad02[6]; +}; + +struct nvif_ioctl_mthd_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 method; + __u8 pad02[6]; + __u8 data[]; /* method data (class.h) */ +}; + +#endif diff --git a/lib/libdrm/nouveau/nvif/unpack.h b/lib/libdrm/nouveau/nvif/unpack.h new file mode 100644 index 000000000..751bcf493 --- /dev/null +++ b/lib/libdrm/nouveau/nvif/unpack.h @@ -0,0 +1,28 @@ +#ifndef __NVIF_UNPACK_H__ +#define __NVIF_UNPACK_H__ + +#define nvif_unvers(r,d,s,m) ({ \ + void **_data = (d); __u32 *_size = (s); int _ret = (r); \ + if (_ret == -ENOSYS && *_size == sizeof(m)) { \ + *_data = NULL; \ + *_size = _ret = 0; \ + } \ + _ret; \ +}) + +#define nvif_unpack(r,d,s,m,vl,vh,x) ({ \ + void **_data = (d); __u32 *_size = (s); \ + int _ret = (r), _vl = (vl), _vh = (vh); \ + if (_ret == -ENOSYS && *_size >= sizeof(m) && \ + (m).version >= _vl && (m).version <= _vh) { \ + *_data = (__u8 *)*_data + sizeof(m); \ + *_size = *_size - sizeof(m); \ + if (_ret = 0, !(x)) { \ + _ret = *_size ? -E2BIG : 0; \ + *_data = NULL; \ + *_size = 0; \ + } \ + } \ + _ret; \ +}) +#endif diff --git a/lib/libdrm/nouveau/private.h b/lib/libdrm/nouveau/private.h index e9439f308..83060f965 100644 --- a/lib/libdrm/nouveau/private.h +++ b/lib/libdrm/nouveau/private.h @@ -114,11 +114,9 @@ int nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t); /* abi16.c */ -drm_private int abi16_chan_nv04(struct nouveau_object *); -drm_private int abi16_chan_nvc0(struct nouveau_object *); -drm_private int abi16_chan_nve0(struct nouveau_object *); -drm_private int abi16_engobj(struct nouveau_object *); -drm_private int abi16_ntfy(struct nouveau_object *); +drm_private bool abi16_object(struct nouveau_object *, int (**)(struct nouveau_object *)); +drm_private void abi16_delete(struct nouveau_object *); +drm_private int abi16_sclass(struct nouveau_object *, struct nouveau_sclass **); drm_private void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *); drm_private int abi16_bo_init(struct nouveau_bo *, uint32_t alignment, union nouveau_bo_config *); diff --git a/lib/libdrm/nouveau/pushbuf.c b/lib/libdrm/nouveau/pushbuf.c index 8e7dcdfaa..035e3019f 100644 --- a/lib/libdrm/nouveau/pushbuf.c +++ b/lib/libdrm/nouveau/pushbuf.c @@ -312,6 +312,7 @@ pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push); struct nouveau_pushbuf_krec *krec = nvpb->list; struct nouveau_device *dev = push->client->device; + struct nouveau_drm *drm = nouveau_drm(&dev->object); struct drm_nouveau_gem_pushbuf_bo_presumed *info; struct drm_nouveau_gem_pushbuf_bo *kref; struct drm_nouveau_gem_pushbuf req; @@ -345,7 +346,7 @@ pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) pushbuf_dump(krec, krec_id++, fifo->channel); #ifndef SIMULATE - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req)); nvpb->suffix0 = req.suffix0; nvpb->suffix1 = req.suffix1; @@ -536,7 +537,7 @@ nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan, int nr, uint32_t size, bool immediate, struct nouveau_pushbuf **ppush) { - struct nouveau_device *dev = client->device; + struct nouveau_drm *drm = nouveau_drm(&client->device->object); struct nouveau_fifo *fifo = chan->data; struct nouveau_pushbuf_priv *nvpb; struct nouveau_pushbuf *push; @@ -551,7 +552,7 @@ nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan, */ req.channel = fifo->channel; req.nr_push = 0; - ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF, + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req)); if (ret) return ret; diff --git a/lib/libdrm/tests/Makefile.am b/lib/libdrm/tests/Makefile.am index a511d28ac..58feb1236 100644 --- a/lib/libdrm/tests/Makefile.am +++ b/lib/libdrm/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = modeprint proptest modetest vbltest +SUBDIRS = util kms modeprint proptest modetest vbltest if HAVE_LIBKMS SUBDIRS += kmstest @@ -31,6 +31,7 @@ LDADD = $(top_builddir)/libdrm.la check_PROGRAMS = \ dristat \ + drmdevice \ drmstat dristat_LDADD = -lm diff --git a/lib/libdrm/tests/amdgpu/basic_tests.c b/lib/libdrm/tests/amdgpu/basic_tests.c index e489e6e83..4ef6014e2 100644 --- a/lib/libdrm/tests/amdgpu/basic_tests.c +++ b/lib/libdrm/tests/amdgpu/basic_tests.c @@ -47,6 +47,11 @@ static void amdgpu_command_submission_gfx(void); static void amdgpu_command_submission_compute(void); static void amdgpu_command_submission_sdma(void); static void amdgpu_userptr_test(void); +static void amdgpu_semaphore_test(void); + +static void amdgpu_command_submission_write_linear_helper(unsigned ip_type); +static void amdgpu_command_submission_const_fill_helper(unsigned ip_type); +static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type); CU_TestInfo basic_tests[] = { { "Query Info Test", amdgpu_query_info_test }, @@ -55,6 +60,7 @@ CU_TestInfo basic_tests[] = { { "Command submission Test (GFX)", amdgpu_command_submission_gfx }, { "Command submission Test (Compute)", amdgpu_command_submission_compute }, { "Command submission Test (SDMA)", amdgpu_command_submission_sdma }, + { "SW semaphore Test", amdgpu_semaphore_test }, CU_TEST_INFO_NULL, }; #define BUFFER_SIZE (8 * 1024) @@ -77,6 +83,120 @@ CU_TestInfo basic_tests[] = { #define SDMA_OPCODE_COPY 1 # define SDMA_COPY_SUB_OPCODE_LINEAR 0 +#define GFX_COMPUTE_NOP 0xffff1000 +#define SDMA_NOP 0x0 + +/* PM4 */ +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 + +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) ((h) & 0xFFFF) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) +#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ + ((reg) & 0xFFFF) | \ + ((n) & 0x3FFF) << 16) +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) + +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) + +#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +/* Packet 3 types */ +#define PACKET3_NOP 0x10 + +#define PACKET3_WRITE_DATA 0x37 +#define WRITE_DATA_DST_SEL(x) ((x) << 8) + /* 0 - register + * 1 - memory (sync - via GRBM) + * 2 - gl2 + * 3 - gds + * 4 - reserved + * 5 - memory (async - direct) + */ +#define WR_ONE_ADDR (1 << 16) +#define WR_CONFIRM (1 << 20) +#define WRITE_DATA_CACHE_POLICY(x) ((x) << 25) + /* 0 - LRU + * 1 - Stream + */ +#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30) + /* 0 - me + * 1 - pfp + * 2 - ce + */ + +#define PACKET3_DMA_DATA 0x50 +/* 1. header + * 2. CONTROL + * 3. SRC_ADDR_LO or DATA [31:0] + * 4. SRC_ADDR_HI [31:0] + * 5. DST_ADDR_LO [31:0] + * 6. DST_ADDR_HI [7:0] + * 7. COMMAND [30:21] | BYTE_COUNT [20:0] + */ +/* CONTROL */ +# define PACKET3_DMA_DATA_ENGINE(x) ((x) << 0) + /* 0 - ME + * 1 - PFP + */ +# define PACKET3_DMA_DATA_SRC_CACHE_POLICY(x) ((x) << 13) + /* 0 - LRU + * 1 - Stream + * 2 - Bypass + */ +# define PACKET3_DMA_DATA_SRC_VOLATILE (1 << 15) +# define PACKET3_DMA_DATA_DST_SEL(x) ((x) << 20) + /* 0 - DST_ADDR using DAS + * 1 - GDS + * 3 - DST_ADDR using L2 + */ +# define PACKET3_DMA_DATA_DST_CACHE_POLICY(x) ((x) << 25) + /* 0 - LRU + * 1 - Stream + * 2 - Bypass + */ +# define PACKET3_DMA_DATA_DST_VOLATILE (1 << 27) +# define PACKET3_DMA_DATA_SRC_SEL(x) ((x) << 29) + /* 0 - SRC_ADDR using SAS + * 1 - GDS + * 2 - DATA + * 3 - SRC_ADDR using L2 + */ +# define PACKET3_DMA_DATA_CP_SYNC (1 << 31) +/* COMMAND */ +# define PACKET3_DMA_DATA_DIS_WC (1 << 21) +# define PACKET3_DMA_DATA_CMD_SRC_SWAP(x) ((x) << 22) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_DMA_DATA_CMD_DST_SWAP(x) ((x) << 24) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_DMA_DATA_CMD_SAS (1 << 26) + /* 0 - memory + * 1 - register + */ +# define PACKET3_DMA_DATA_CMD_DAS (1 << 27) + /* 0 - memory + * 1 - register + */ +# define PACKET3_DMA_DATA_CMD_SAIC (1 << 28) +# define PACKET3_DMA_DATA_CMD_DAIC (1 << 29) +# define PACKET3_DMA_DATA_CMD_RAW_WAIT (1 << 30) + int suite_basic_tests_init(void) { int r; @@ -325,14 +445,163 @@ static void amdgpu_command_submission_gfx_shared_ib(void) CU_ASSERT_EQUAL(r, 0); } +static void amdgpu_command_submission_cp_write_data(void) +{ + amdgpu_command_submission_write_linear_helper(AMDGPU_HW_IP_GFX); +} + +static void amdgpu_command_submission_cp_const_fill(void) +{ + amdgpu_command_submission_const_fill_helper(AMDGPU_HW_IP_GFX); +} + +static void amdgpu_command_submission_cp_copy_data(void) +{ + amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_GFX); +} + static void amdgpu_command_submission_gfx(void) { + /* write data using the CP */ + amdgpu_command_submission_cp_write_data(); + /* const fill using the CP */ + amdgpu_command_submission_cp_const_fill(); + /* copy data using the CP */ + amdgpu_command_submission_cp_copy_data(); /* separate IB buffers for multi-IB submission */ amdgpu_command_submission_gfx_separate_ibs(); /* shared IB buffer for multi-IB submission */ amdgpu_command_submission_gfx_shared_ib(); } +static void amdgpu_semaphore_test(void) +{ + amdgpu_context_handle context_handle[2]; + amdgpu_semaphore_handle sem; + amdgpu_bo_handle ib_result_handle[2]; + void *ib_result_cpu[2]; + uint64_t ib_result_mc_address[2]; + struct amdgpu_cs_request ibs_request[2] = {0}; + struct amdgpu_cs_ib_info ib_info[2] = {0}; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t *ptr; + uint32_t expired; + amdgpu_bo_list_handle bo_list[2]; + amdgpu_va_handle va_handle[2]; + int r, i; + + r = amdgpu_cs_create_semaphore(&sem); + CU_ASSERT_EQUAL(r, 0); + for (i = 0; i < 2; i++) { + r = amdgpu_cs_ctx_create(device_handle, &context_handle[i]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle[i], &ib_result_cpu[i], + &ib_result_mc_address[i], &va_handle[i]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle[i], + NULL, &bo_list[i]); + CU_ASSERT_EQUAL(r, 0); + } + + /* 1. same context different engine */ + ptr = ib_result_cpu[0]; + ptr[0] = SDMA_NOP; + ib_info[0].ib_mc_address = ib_result_mc_address[0]; + ib_info[0].size = 1; + + ibs_request[0].ip_type = AMDGPU_HW_IP_DMA; + ibs_request[0].number_of_ibs = 1; + ibs_request[0].ibs = &ib_info[0]; + ibs_request[0].resources = bo_list[0]; + ibs_request[0].fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[0], 1); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_signal_semaphore(context_handle[0], AMDGPU_HW_IP_DMA, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_wait_semaphore(context_handle[0], AMDGPU_HW_IP_GFX, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + ptr = ib_result_cpu[1]; + ptr[0] = GFX_COMPUTE_NOP; + ib_info[1].ib_mc_address = ib_result_mc_address[1]; + ib_info[1].size = 1; + + ibs_request[1].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[1].number_of_ibs = 1; + ibs_request[1].ibs = &ib_info[1]; + ibs_request[1].resources = bo_list[1]; + ibs_request[1].fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[1], 1); + CU_ASSERT_EQUAL(r, 0); + + fence_status.context = context_handle[0]; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.fence = ibs_request[1].seq_no; + r = amdgpu_cs_query_fence_status(&fence_status, + 500000000, 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* 2. same engine different context */ + ptr = ib_result_cpu[0]; + ptr[0] = GFX_COMPUTE_NOP; + ib_info[0].ib_mc_address = ib_result_mc_address[0]; + ib_info[0].size = 1; + + ibs_request[0].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[0].number_of_ibs = 1; + ibs_request[0].ibs = &ib_info[0]; + ibs_request[0].resources = bo_list[0]; + ibs_request[0].fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[0], 1); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_signal_semaphore(context_handle[0], AMDGPU_HW_IP_GFX, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_wait_semaphore(context_handle[1], AMDGPU_HW_IP_GFX, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + ptr = ib_result_cpu[1]; + ptr[0] = GFX_COMPUTE_NOP; + ib_info[1].ib_mc_address = ib_result_mc_address[1]; + ib_info[1].size = 1; + + ibs_request[1].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[1].number_of_ibs = 1; + ibs_request[1].ibs = &ib_info[1]; + ibs_request[1].resources = bo_list[1]; + ibs_request[1].fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle[1], 0,&ibs_request[1], 1); + + CU_ASSERT_EQUAL(r, 0); + + fence_status.context = context_handle[1]; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.fence = ibs_request[1].seq_no; + r = amdgpu_cs_query_fence_status(&fence_status, + 500000000, 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + for (i = 0; i < 2; i++) { + r = amdgpu_bo_unmap_and_free(ib_result_handle[i], va_handle[i], + ib_result_mc_address[i], 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_list_destroy(bo_list[i]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle[i]); + CU_ASSERT_EQUAL(r, 0); + } + + r = amdgpu_cs_destroy_semaphore(sem); + CU_ASSERT_EQUAL(r, 0); +} + static void amdgpu_command_submission_compute(void) { amdgpu_context_handle context_handle; @@ -409,11 +678,12 @@ static void amdgpu_command_submission_compute(void) * pm4_src, resources, ib_info, and ibs_request * submit command stream described in ibs_request and wait for this IB accomplished */ -static void amdgpu_sdma_test_exec_cs(amdgpu_context_handle context_handle, - int instance, int pm4_dw, uint32_t *pm4_src, - int res_cnt, amdgpu_bo_handle *resources, - struct amdgpu_cs_ib_info *ib_info, - struct amdgpu_cs_request *ibs_request) +static void amdgpu_test_exec_cs_helper(amdgpu_context_handle context_handle, + unsigned ip_type, + int instance, int pm4_dw, uint32_t *pm4_src, + int res_cnt, amdgpu_bo_handle *resources, + struct amdgpu_cs_ib_info *ib_info, + struct amdgpu_cs_request *ibs_request) { int r; uint32_t expired; @@ -446,7 +716,7 @@ static void amdgpu_sdma_test_exec_cs(amdgpu_context_handle context_handle, ib_info->ib_mc_address = ib_result_mc_address; ib_info->size = pm4_dw; - ibs_request->ip_type = AMDGPU_HW_IP_DMA; + ibs_request->ip_type = ip_type; ibs_request->ring = instance; ibs_request->number_of_ibs = 1; ibs_request->ibs = ib_info; @@ -468,7 +738,7 @@ static void amdgpu_sdma_test_exec_cs(amdgpu_context_handle context_handle, r = amdgpu_bo_list_destroy(ibs_request->resources); CU_ASSERT_EQUAL(r, 0); - fence_status.ip_type = AMDGPU_HW_IP_DMA; + fence_status.ip_type = ip_type; fence_status.ring = ibs_request->ring; fence_status.context = context_handle; fence_status.fence = ibs_request->seq_no; @@ -485,7 +755,7 @@ static void amdgpu_sdma_test_exec_cs(amdgpu_context_handle context_handle, CU_ASSERT_EQUAL(r, 0); } -static void amdgpu_command_submission_sdma_write_linear(void) +static void amdgpu_command_submission_write_linear_helper(unsigned ip_type) { const int sdma_write_length = 128; const int pm4_dw = 256; @@ -535,18 +805,28 @@ static void amdgpu_command_submission_sdma_write_linear(void) /* fullfill PM4: test DMA write-linear */ i = j = 0; - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE, - SDMA_WRITE_SUB_OPCODE_LINEAR, 0); - pm4[i++] = 0xffffffff & bo_mc; - pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - pm4[i++] = sdma_write_length; - while(j++ < sdma_write_length) - pm4[i++] = 0xdeadbeaf; + if (ip_type == AMDGPU_HW_IP_DMA) { + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE, + SDMA_WRITE_SUB_OPCODE_LINEAR, 0); + pm4[i++] = 0xffffffff & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + pm4[i++] = sdma_write_length; + while(j++ < sdma_write_length) + pm4[i++] = 0xdeadbeaf; + } else if (ip_type == AMDGPU_HW_IP_GFX) { + pm4[i++] = PACKET3(PACKET3_WRITE_DATA, 2 + sdma_write_length); + pm4[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM; + pm4[i++] = 0xfffffffc & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + while(j++ < sdma_write_length) + pm4[i++] = 0xdeadbeaf; + } - amdgpu_sdma_test_exec_cs(context_handle, 0, - i, pm4, - 1, resources, - ib_info, ibs_request); + amdgpu_test_exec_cs_helper(context_handle, + ip_type, 0, + i, pm4, + 1, resources, + ib_info, ibs_request); /* verify if SDMA test result meets with expected */ i = 0; @@ -570,7 +850,12 @@ static void amdgpu_command_submission_sdma_write_linear(void) CU_ASSERT_EQUAL(r, 0); } -static void amdgpu_command_submission_sdma_const_fill(void) +static void amdgpu_command_submission_sdma_write_linear(void) +{ + amdgpu_command_submission_write_linear_helper(AMDGPU_HW_IP_DMA); +} + +static void amdgpu_command_submission_const_fill_helper(unsigned ip_type) { const int sdma_write_length = 1024 * 1024; const int pm4_dw = 256; @@ -619,17 +904,31 @@ static void amdgpu_command_submission_sdma_const_fill(void) /* fullfill PM4: test DMA const fill */ i = j = 0; - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, - SDMA_CONSTANT_FILL_EXTRA_SIZE(2)); - pm4[i++] = 0xffffffff & bo_mc; - pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - pm4[i++] = 0xdeadbeaf; - pm4[i++] = sdma_write_length; + if (ip_type == AMDGPU_HW_IP_DMA) { + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, + SDMA_CONSTANT_FILL_EXTRA_SIZE(2)); + pm4[i++] = 0xffffffff & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + pm4[i++] = 0xdeadbeaf; + pm4[i++] = sdma_write_length; + } else if (ip_type == AMDGPU_HW_IP_GFX) { + pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5); + pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) | + PACKET3_DMA_DATA_DST_SEL(0) | + PACKET3_DMA_DATA_SRC_SEL(2) | + PACKET3_DMA_DATA_CP_SYNC; + pm4[i++] = 0xdeadbeaf; + pm4[i++] = 0; + pm4[i++] = 0xfffffffc & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + pm4[i++] = sdma_write_length; + } - amdgpu_sdma_test_exec_cs(context_handle, 0, - i, pm4, - 1, resources, - ib_info, ibs_request); + amdgpu_test_exec_cs_helper(context_handle, + ip_type, 0, + i, pm4, + 1, resources, + ib_info, ibs_request); /* verify if SDMA test result meets with expected */ i = 0; @@ -653,7 +952,12 @@ static void amdgpu_command_submission_sdma_const_fill(void) CU_ASSERT_EQUAL(r, 0); } -static void amdgpu_command_submission_sdma_copy_linear(void) +static void amdgpu_command_submission_sdma_const_fill(void) +{ + amdgpu_command_submission_const_fill_helper(AMDGPU_HW_IP_DMA); +} + +static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type) { const int sdma_write_length = 1024; const int pm4_dw = 256; @@ -718,19 +1022,32 @@ static void amdgpu_command_submission_sdma_copy_linear(void) /* fullfill PM4: test DMA copy linear */ i = j = 0; - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0); - pm4[i++] = sdma_write_length; - pm4[i++] = 0; - pm4[i++] = 0xffffffff & bo1_mc; - pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; - pm4[i++] = 0xffffffff & bo2_mc; - pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; - + if (ip_type == AMDGPU_HW_IP_DMA) { + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0); + pm4[i++] = sdma_write_length; + pm4[i++] = 0; + pm4[i++] = 0xffffffff & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + pm4[i++] = 0xffffffff & bo2_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + } else if (ip_type == AMDGPU_HW_IP_GFX) { + pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5); + pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) | + PACKET3_DMA_DATA_DST_SEL(0) | + PACKET3_DMA_DATA_SRC_SEL(0) | + PACKET3_DMA_DATA_CP_SYNC; + pm4[i++] = 0xfffffffc & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + pm4[i++] = 0xfffffffc & bo2_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + pm4[i++] = sdma_write_length; + } - amdgpu_sdma_test_exec_cs(context_handle, 0, - i, pm4, - 2, resources, - ib_info, ibs_request); + amdgpu_test_exec_cs_helper(context_handle, + ip_type, 0, + i, pm4, + 2, resources, + ib_info, ibs_request); /* verify if SDMA test result meets with expected */ i = 0; @@ -758,6 +1075,11 @@ static void amdgpu_command_submission_sdma_copy_linear(void) CU_ASSERT_EQUAL(r, 0); } +static void amdgpu_command_submission_sdma_copy_linear(void) +{ + amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_DMA); +} + static void amdgpu_command_submission_sdma(void) { amdgpu_command_submission_sdma_write_linear(); @@ -821,10 +1143,11 @@ static void amdgpu_userptr_test(void) while (j++ < sdma_write_length) pm4[i++] = 0xdeadbeaf; - amdgpu_sdma_test_exec_cs(context_handle, 0, - i, pm4, - 1, &handle, - ib_info, ibs_request); + amdgpu_test_exec_cs_helper(context_handle, + AMDGPU_HW_IP_DMA, 0, + i, pm4, + 1, &handle, + ib_info, ibs_request); i = 0; while (i < sdma_write_length) { CU_ASSERT_EQUAL(((int*)ptr)[i++], 0xdeadbeaf); diff --git a/lib/libdrm/tests/drmdevice.c b/lib/libdrm/tests/drmdevice.c new file mode 100644 index 000000000..c33632745 --- /dev/null +++ b/lib/libdrm/tests/drmdevice.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015 Emil Velikov <emil.l.velikov@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <xf86drm.h> + + +static void +print_device_info(drmDevicePtr device, int i) +{ + printf("device[%i]\n", i); + printf("\tavailable_nodes %04x\n", device->available_nodes); + printf("\tnodes\n"); + for (int j = 0; j < DRM_NODE_MAX; j++) + if (device->available_nodes & 1 << j) + printf("\t\tnodes[%d] %s\n", j, device->nodes[j]); + + printf("\tbustype %04x\n", device->bustype); + printf("\tbusinfo\n"); + if (device->bustype == DRM_BUS_PCI) { + printf("\t\tpci\n"); + printf("\t\t\tdomain\t%04x\n",device->businfo.pci->domain); + printf("\t\t\tbu\t%02x\n", device->businfo.pci->bus); + printf("\t\t\tde\t%02x\n", device->businfo.pci->dev); + printf("\t\t\tfunc\t%1u\n", device->businfo.pci->func); + + printf("\tdeviceinfo\n"); + printf("\t\tpci\n"); + printf("\t\t\tvendor_id\t%04x\n", device->deviceinfo.pci->vendor_id); + printf("\t\t\tdevice_id\t%04x\n", device->deviceinfo.pci->device_id); + printf("\t\t\tsubvendor_id\t%04x\n", device->deviceinfo.pci->subvendor_id); + printf("\t\t\tsubdevice_id\t%04x\n", device->deviceinfo.pci->subdevice_id); + printf("\t\t\trevision_id\t%02x\n", device->deviceinfo.pci->revision_id); + } else { + printf("Unknown/unhandled bustype\n"); + } + printf("\n"); +} + +int +main(void) +{ + drmDevicePtr *devices; + drmDevicePtr device; + int fd, ret, max_devices; + + max_devices = drmGetDevices(NULL, 0); + + if (max_devices <= 0) { + printf("drmGetDevices() has returned %d\n", max_devices); + return -1; + } + + devices = calloc(max_devices, sizeof(drmDevicePtr)); + if (devices == NULL) { + printf("Failed to allocate memory for the drmDevicePtr array\n"); + return -1; + } + + ret = drmGetDevices(devices, max_devices); + if (ret < 0) { + printf("drmGetDevices() returned an error %d\n", ret); + free(devices); + return -1; + } + + for (int i = 0; i < ret; i++) { + print_device_info(devices[i], i); + + for (int j = 0; j < DRM_NODE_MAX; j++) { + if (devices[i]->available_nodes & 1 << j) { + fd = open(devices[i]->nodes[j], O_RDONLY | O_CLOEXEC, 0); + if (fd < 0) + continue; + + if (drmGetDevice(fd, &device) == 0) { + print_device_info(device, -1); + drmFreeDevice(&device); + } + close(fd); + } + } + } + + drmFreeDevices(devices, ret); + free(devices); + return 0; +} diff --git a/lib/libdrm/tests/exynos/Makefile.am b/lib/libdrm/tests/exynos/Makefile.am index b21d01696..357d6b8c2 100644 --- a/lib/libdrm/tests/exynos/Makefile.am +++ b/lib/libdrm/tests/exynos/Makefile.am @@ -5,16 +5,38 @@ AM_CFLAGS = \ -I $(top_srcdir)/exynos \ -I $(top_srcdir) +bin_PROGRAMS = +noinst_PROGRAMS = + if HAVE_LIBKMS if HAVE_INSTALL_TESTS -bin_PROGRAMS = \ +bin_PROGRAMS += \ exynos_fimg2d_test else -noinst_PROGRAMS = \ +noinst_PROGRAMS += \ exynos_fimg2d_test endif endif +if HAVE_INSTALL_TESTS +bin_PROGRAMS += \ + exynos_fimg2d_perf \ + exynos_fimg2d_event +else +noinst_PROGRAMS += \ + exynos_fimg2d_perf \ + exynos_fimg2d_event +endif + +exynos_fimg2d_perf_LDADD = \ + $(top_builddir)/libdrm.la \ + $(top_builddir)/exynos/libdrm_exynos.la + +exynos_fimg2d_event_LDADD = \ + $(top_builddir)/libdrm.la \ + $(top_builddir)/exynos/libdrm_exynos.la \ + -lpthread + exynos_fimg2d_test_LDADD = \ $(top_builddir)/libdrm.la \ $(top_builddir)/libkms/libkms.la \ diff --git a/lib/libdrm/tests/exynos/exynos_fimg2d_event.c b/lib/libdrm/tests/exynos/exynos_fimg2d_event.c new file mode 100644 index 000000000..9ed5a307d --- /dev/null +++ b/lib/libdrm/tests/exynos/exynos_fimg2d_event.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2015 - Tobias Jakobi + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 2 of the License, + * or (at your option) any later version. + * + * It is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with it. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <unistd.h> +#include <poll.h> + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <getopt.h> + +#include <pthread.h> + +#include <xf86drm.h> + +#include "exynos_drm.h" +#include "exynos_drmif.h" +#include "exynos_fimg2d.h" + +struct g2d_job { + unsigned int id; + unsigned int busy; +}; + +struct exynos_evhandler { + struct pollfd fds; + struct exynos_event_context evctx; +}; + +struct threaddata { + unsigned int stop; + struct exynos_device *dev; + struct exynos_evhandler evhandler; +}; + +static void g2d_event_handler(int fd, unsigned int cmdlist_no, unsigned int tv_sec, + unsigned int tv_usec, void *user_data) +{ + struct g2d_job *job = user_data; + + fprintf(stderr, "info: g2d job (id = %u, cmdlist number = %u) finished!\n", + job->id, cmdlist_no); + + job->busy = 0; +} + +static void setup_g2d_event_handler(struct exynos_evhandler *evhandler, int fd) +{ + evhandler->fds.fd = fd; + evhandler->fds.events = POLLIN; + evhandler->evctx.base.version = 2; + evhandler->evctx.version = 1; + evhandler->evctx.g2d_event_handler = g2d_event_handler; +} + +static void* threadfunc(void *arg) { + const int timeout = 0; + struct threaddata *data; + + data = arg; + + while (1) { + if (data->stop) break; + + usleep(500); + + data->evhandler.fds.revents = 0; + + if (poll(&data->evhandler.fds, 1, timeout) < 0) + continue; + + if (data->evhandler.fds.revents & (POLLHUP | POLLERR)) + continue; + + if (data->evhandler.fds.revents & POLLIN) + exynos_handle_event(data->dev, &data->evhandler.evctx); + } + + pthread_exit(0); +} + +/* + * We need to wait until all G2D jobs are finished, otherwise we + * potentially remove a BO which the engine still operates on. + * This results in the following kernel message: + * [drm:exynos_drm_gem_put_dma_addr] *ERROR* failed to lookup gem object. + * Also any subsequent BO allocations fail then with: + * [drm:exynos_drm_alloc_buf] *ERROR* failed to allocate buffer. + */ +static void wait_all_jobs(struct g2d_job* jobs, unsigned num_jobs) +{ + unsigned i; + + for (i = 0; i < num_jobs; ++i) { + while (jobs[i].busy) + usleep(500); + } + +} + +static struct g2d_job* free_job(struct g2d_job* jobs, unsigned num_jobs) +{ + unsigned i; + + for (i = 0; i < num_jobs; ++i) { + if (jobs[i].busy == 0) + return &jobs[i]; + } + + return NULL; +} + +static int g2d_work(struct g2d_context *ctx, struct g2d_image *img, + unsigned num_jobs, unsigned iterations) +{ + struct g2d_job *jobs = calloc(num_jobs, sizeof(struct g2d_job)); + int ret; + unsigned i; + + /* setup job ids */ + for (i = 0; i < num_jobs; ++i) + jobs[i].id = i; + + for (i = 0; i < iterations; ++i) { + unsigned x, y, w, h; + + struct g2d_job *j = NULL; + + while (1) { + j = free_job(jobs, num_jobs); + + if (j) + break; + else + usleep(500); + } + + x = rand() % img->width; + y = rand() % img->height; + + if (x == (img->width - 1)) + x -= 1; + if (y == (img->height - 1)) + y -= 1; + + w = rand() % (img->width - x); + h = rand() % (img->height - y); + + if (w == 0) w = 1; + if (h == 0) h = 1; + + img->color = rand(); + + j->busy = 1; + g2d_config_event(ctx, j); + + ret = g2d_solid_fill(ctx, img, x, y, w, h); + + if (ret == 0) + g2d_exec(ctx); + + if (ret != 0) { + fprintf(stderr, "error: iteration %u (x = %u, x = %u, x = %u, x = %u) failed\n", + i, x, y, w, h); + break; + } + } + + wait_all_jobs(jobs, num_jobs); + free(jobs); + + return 0; +} + +static void usage(const char *name) +{ + fprintf(stderr, "usage: %s [-ijwh]\n\n", name); + + fprintf(stderr, "\t-i <number of iterations>\n"); + fprintf(stderr, "\t-j <number of G2D jobs> (default = 4)\n\n"); + + fprintf(stderr, "\t-w <buffer width> (default = 4096)\n"); + fprintf(stderr, "\t-h <buffer height> (default = 4096)\n"); + + exit(0); +} + +int main(int argc, char **argv) +{ + int fd, ret, c, parsefail; + + pthread_t event_thread; + struct threaddata event_data = {0}; + + struct exynos_device *dev; + struct g2d_context *ctx; + struct exynos_bo *bo; + + struct g2d_image img = {0}; + + unsigned int iters = 0, njobs = 4; + unsigned int bufw = 4096, bufh = 4096; + + ret = 0; + parsefail = 0; + + while ((c = getopt(argc, argv, "i:j:w:h:")) != -1) { + switch (c) { + case 'i': + if (sscanf(optarg, "%u", &iters) != 1) + parsefail = 1; + break; + case 'j': + if (sscanf(optarg, "%u", &njobs) != 1) + parsefail = 1; + break; + case 'w': + if (sscanf(optarg, "%u", &bufw) != 1) + parsefail = 1; + break; + case 'h': + if (sscanf(optarg, "%u", &bufh) != 1) + parsefail = 1; + break; + default: + parsefail = 1; + break; + } + } + + if (parsefail || (argc == 1) || (iters == 0)) + usage(argv[0]); + + if (bufw > 4096 || bufh > 4096) { + fprintf(stderr, "error: buffer width/height should be less than 4096.\n"); + ret = -1; + + goto out; + } + + if (bufw == 0 || bufh == 0) { + fprintf(stderr, "error: buffer width/height should be non-zero.\n"); + ret = -1; + + goto out; + } + + fd = drmOpen("exynos", NULL); + if (fd < 0) { + fprintf(stderr, "error: failed to open drm\n"); + ret = -1; + + goto out; + } + + dev = exynos_device_create(fd); + if (dev == NULL) { + fprintf(stderr, "error: failed to create device\n"); + ret = -2; + + goto fail; + } + + ctx = g2d_init(fd); + if (ctx == NULL) { + fprintf(stderr, "error: failed to init G2D\n"); + ret = -3; + + goto g2d_fail; + } + + bo = exynos_bo_create(dev, bufw * bufh * 4, 0); + if (bo == NULL) { + fprintf(stderr, "error: failed to create bo\n"); + ret = -4; + + goto bo_fail; + } + + /* setup g2d image object */ + img.width = bufw; + img.height = bufh; + img.stride = bufw * 4; + img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + img.buf_type = G2D_IMGBUF_GEM; + img.bo[0] = bo->handle; + + event_data.dev = dev; + setup_g2d_event_handler(&event_data.evhandler, fd); + + pthread_create(&event_thread, NULL, threadfunc, &event_data); + + ret = g2d_work(ctx, &img, njobs, iters); + if (ret != 0) + fprintf(stderr, "error: g2d_work failed\n"); + + event_data.stop = 1; + pthread_join(event_thread, NULL); + + exynos_bo_destroy(bo); + +bo_fail: + g2d_fini(ctx); + +g2d_fail: + exynos_device_destroy(dev); + +fail: + drmClose(fd); + +out: + return ret; +} diff --git a/lib/libdrm/tests/exynos/exynos_fimg2d_perf.c b/lib/libdrm/tests/exynos/exynos_fimg2d_perf.c new file mode 100644 index 000000000..1699bba7b --- /dev/null +++ b/lib/libdrm/tests/exynos/exynos_fimg2d_perf.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2015 - Tobias Jakobi + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 2 of the License, + * or (at your option) any later version. + * + * It is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with it. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <getopt.h> +#include <errno.h> + +#include <xf86drm.h> + +#include "exynos_drm.h" +#include "exynos_drmif.h" +#include "exynos_fimg2d.h" + +static int output_mathematica = 0; + +static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx, + unsigned buf_width, unsigned buf_height, unsigned iterations) +{ + struct timespec tspec = { 0 }; + struct g2d_image img = { 0 }; + + unsigned long long g2d_time; + unsigned i; + int ret = 0; + + img.width = buf_width; + img.height = buf_height; + img.stride = buf_width * 4; + img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + img.buf_type = G2D_IMGBUF_GEM; + img.bo[0] = bo->handle; + + srand(time(NULL)); + + printf("starting simple G2D performance test\n"); + printf("buffer width = %u, buffer height = %u, iterations = %u\n", + buf_width, buf_height, iterations); + + if (output_mathematica) + putchar('{'); + + for (i = 0; i < iterations; ++i) { + unsigned x, y, w, h; + + x = rand() % buf_width; + y = rand() % buf_height; + + if (x == (buf_width - 1)) + x -= 1; + if (y == (buf_height - 1)) + y -= 1; + + w = rand() % (buf_width - x); + h = rand() % (buf_height - y); + + if (w == 0) w = 1; + if (h == 0) h = 1; + + img.color = rand(); + + ret = g2d_solid_fill(ctx, &img, x, y, w, h); + + clock_gettime(CLOCK_MONOTONIC, &tspec); + + if (ret == 0) + ret = g2d_exec(ctx); + + if (ret != 0) { + fprintf(stderr, "error: iteration %u failed (x = %u, y = %u, w = %u, h = %u)\n", + i, x, y, w, h); + break; + } else { + struct timespec end = { 0 }; + clock_gettime(CLOCK_MONOTONIC, &end); + + g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL; + g2d_time += (end.tv_nsec - tspec.tv_nsec); + + if (output_mathematica) { + if (i != 0) putchar(','); + printf("{%u,%llu}", w * h, g2d_time); + } else { + printf("num_pixels = %u, usecs = %llu\n", w * h, g2d_time); + } + } + } + + if (output_mathematica) + printf("}\n"); + + return ret; +} + +static int fimg2d_perf_multi(struct exynos_bo *bo, struct g2d_context *ctx, + unsigned buf_width, unsigned buf_height, unsigned iterations, unsigned batch) +{ + struct timespec tspec = { 0 }; + struct g2d_image *images; + + unsigned long long g2d_time; + unsigned i, j; + int ret = 0; + + images = calloc(batch, sizeof(struct g2d_image)); + if (images == NULL) { + fprintf(stderr, "error: failed to allocate G2D images.\n"); + return -ENOMEM; + } + + for (i = 0; i < batch; ++i) { + images[i].width = buf_width; + images[i].height = buf_height; + images[i].stride = buf_width * 4; + images[i].color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + images[i].buf_type = G2D_IMGBUF_GEM; + images[i].bo[0] = bo->handle; + } + + srand(time(NULL)); + + printf("starting multi G2D performance test (batch size = %u)\n", batch); + printf("buffer width = %u, buffer height = %u, iterations = %u\n", + buf_width, buf_height, iterations); + + if (output_mathematica) + putchar('{'); + + for (i = 0; i < iterations; ++i) { + unsigned num_pixels = 0; + + for (j = 0; j < batch; ++j) { + unsigned x, y, w, h; + + x = rand() % buf_width; + y = rand() % buf_height; + + if (x == (buf_width - 1)) + x -= 1; + if (y == (buf_height - 1)) + y -= 1; + + w = rand() % (buf_width - x); + h = rand() % (buf_height - y); + + if (w == 0) w = 1; + if (h == 0) h = 1; + + images[j].color = rand(); + + num_pixels += w * h; + + ret = g2d_solid_fill(ctx, &images[j], x, y, w, h); + if (ret != 0) + break; + } + + clock_gettime(CLOCK_MONOTONIC, &tspec); + + if (ret == 0) + ret = g2d_exec(ctx); + + if (ret != 0) { + fprintf(stderr, "error: iteration %u failed (num_pixels = %u)\n", i, num_pixels); + break; + } else { + struct timespec end = { 0 }; + clock_gettime(CLOCK_MONOTONIC, &end); + + g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL; + g2d_time += (end.tv_nsec - tspec.tv_nsec); + + if (output_mathematica) { + if (i != 0) putchar(','); + printf("{%u,%llu}", num_pixels, g2d_time); + } else { + printf("num_pixels = %u, usecs = %llu\n", num_pixels, g2d_time); + } + } + } + + if (output_mathematica) + printf("}\n"); + + free(images); + + return ret; +} + +static void usage(const char *name) +{ + fprintf(stderr, "usage: %s [-ibwh]\n\n", name); + + fprintf(stderr, "\t-i <number of iterations>\n"); + fprintf(stderr, "\t-b <size of a batch> (default = 3)\n\n"); + + fprintf(stderr, "\t-w <buffer width> (default = 4096)\n"); + fprintf(stderr, "\t-h <buffer height> (default = 4096)\n\n"); + + fprintf(stderr, "\t-M <enable Mathematica styled output>\n"); + + exit(0); +} + +int main(int argc, char **argv) +{ + int fd, ret, c, parsefail; + + struct exynos_device *dev; + struct g2d_context *ctx; + struct exynos_bo *bo; + + unsigned int iters = 0, batch = 3; + unsigned int bufw = 4096, bufh = 4096; + + ret = 0; + parsefail = 0; + + while ((c = getopt(argc, argv, "i:b:w:h:M")) != -1) { + switch (c) { + case 'i': + if (sscanf(optarg, "%u", &iters) != 1) + parsefail = 1; + break; + case 'b': + if (sscanf(optarg, "%u", &batch) != 1) + parsefail = 1; + break; + case 'w': + if (sscanf(optarg, "%u", &bufw) != 1) + parsefail = 1; + break; + case 'h': + if (sscanf(optarg, "%u", &bufh) != 1) + parsefail = 1; + break; + case 'M': + output_mathematica = 1; + break; + default: + parsefail = 1; + break; + } + } + + if (parsefail || (argc == 1) || (iters == 0)) + usage(argv[0]); + + if (bufw < 2 || bufw > 4096 || bufh < 2 || bufh > 4096) { + fprintf(stderr, "error: buffer width/height should be in the range 2 to 4096.\n"); + ret = -1; + + goto out; + } + + if (bufw == 0 || bufh == 0) { + fprintf(stderr, "error: buffer width/height should be non-zero.\n"); + ret = -1; + + goto out; + } + + fd = drmOpen("exynos", NULL); + if (fd < 0) { + fprintf(stderr, "error: failed to open drm\n"); + ret = -1; + + goto out; + } + + dev = exynos_device_create(fd); + if (dev == NULL) { + fprintf(stderr, "error: failed to create device\n"); + ret = -2; + + goto fail; + } + + ctx = g2d_init(fd); + if (ctx == NULL) { + fprintf(stderr, "error: failed to init G2D\n"); + ret = -3; + + goto g2d_fail; + } + + bo = exynos_bo_create(dev, bufw * bufh * 4, 0); + if (bo == NULL) { + fprintf(stderr, "error: failed to create bo\n"); + ret = -4; + + goto bo_fail; + } + + ret = fimg2d_perf_simple(bo, ctx, bufw, bufh, iters); + + if (ret == 0) + ret = fimg2d_perf_multi(bo, ctx, bufw, bufh, iters, batch); + + exynos_bo_destroy(bo); + +bo_fail: + g2d_fini(ctx); + +g2d_fail: + exynos_device_destroy(dev); + +fail: + drmClose(fd); + +out: + return ret; +} diff --git a/lib/libdrm/tests/exynos/exynos_fimg2d_test.c b/lib/libdrm/tests/exynos/exynos_fimg2d_test.c index 8794dac39..797fb6eb2 100644 --- a/lib/libdrm/tests/exynos/exynos_fimg2d_test.c +++ b/lib/libdrm/tests/exynos/exynos_fimg2d_test.c @@ -313,6 +313,130 @@ fail: return ret; } +static int g2d_move_test(struct exynos_device *dev, + struct exynos_bo *tmp, + struct exynos_bo *buf, + enum e_g2d_buf_type type) +{ + struct g2d_context *ctx; + struct g2d_image img = {0}, tmp_img = {0}; + unsigned int img_w, img_h, count; + int cur_x, cur_y; + void *checkerboard; + int ret; + + static const struct g2d_step { + int x, y; + } steps[] = { + { 1, 0}, { 0, 1}, + {-1, 0}, { 0, -1}, + { 1, 1}, {-1, -1}, + { 1, -1}, {-1, 1}, + { 2, 1}, { 1, 2}, + {-2, -1}, {-1, -2}, + { 2, -1}, { 1, -2}, + {-2, 1}, {-1, 2} + }; + static const unsigned int num_steps = + sizeof(steps) / sizeof(struct g2d_step); + + ctx = g2d_init(dev->fd); + if (!ctx) + return -EFAULT; + + img.bo[0] = buf->handle; + + /* create pattern of half the screen size */ + checkerboard = create_checkerboard_pattern(screen_width / 64, screen_height / 64, 32); + if (!checkerboard) { + ret = -EFAULT; + goto fail; + } + + img_w = (screen_width / 64) * 32; + img_h = (screen_height / 64) * 32; + + switch (type) { + case G2D_IMGBUF_GEM: + memcpy(tmp->vaddr, checkerboard, img_w * img_h * 4); + tmp_img.bo[0] = tmp->handle; + break; + case G2D_IMGBUF_USERPTR: + tmp_img.user_ptr[0].userptr = (unsigned long)checkerboard; + tmp_img.user_ptr[0].size = img_w * img_h * 4; + break; + case G2D_IMGBUF_COLOR: + default: + ret = -EFAULT; + goto fail; + } + + /* solid fill framebuffer with white color */ + img.width = screen_width; + img.height = screen_height; + img.stride = screen_width * 4; + img.buf_type = G2D_IMGBUF_GEM; + img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + img.color = 0xffffffff; + + /* put checkerboard pattern in the center of the framebuffer */ + cur_x = (screen_width - img_w) / 2; + cur_y = (screen_height - img_h) / 2; + tmp_img.width = img_w; + tmp_img.height = img_h; + tmp_img.stride = img_w * 4; + tmp_img.buf_type = type; + tmp_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + + ret = g2d_solid_fill(ctx, &img, 0, 0, screen_width, screen_height) || + g2d_copy(ctx, &tmp_img, &img, 0, 0, cur_x, cur_y, img_w, img_h); + + if (!ret) + ret = g2d_exec(ctx); + if (ret < 0) + goto fail; + + printf("move test with %s.\n", + type == G2D_IMGBUF_GEM ? "gem" : "userptr"); + + srand(time(NULL)); + for (count = 0; count < 256; ++count) { + const struct g2d_step *s; + + /* select step and validate it */ + while (1) { + s = &steps[random() % num_steps]; + + if (cur_x + s->x < 0 || cur_y + s->y < 0 || + cur_x + img_w + s->x >= screen_width || + cur_y + img_h + s->y >= screen_height) + continue; + else + break; + } + + ret = g2d_move(ctx, &img, cur_x, cur_y, cur_x + s->x, cur_y + s->y, + img_w, img_h); + if (!ret) + ret = g2d_exec(ctx); + + if (ret < 0) + goto fail; + + cur_x += s->x; + cur_y += s->y; + + usleep(100000); + } + +fail: + g2d_fini(ctx); + + free(checkerboard); + + return ret; +} + static int g2d_copy_with_scale_test(struct exynos_device *dev, struct exynos_bo *src, struct exynos_bo *dst, @@ -675,7 +799,7 @@ int main(int argc, char **argv) offsets[0] = 0; ret = drmModeAddFB2(dev->fd, screen_width, screen_height, - DRM_FORMAT_RGBA8888, handles, + DRM_FORMAT_XRGB8888, handles, pitches, offsets, &fb_id, 0); if (ret < 0) goto err_destroy_buffer; @@ -708,6 +832,14 @@ int main(int argc, char **argv) wait_for_user_input(0); + ret = g2d_move_test(dev, src, bo, G2D_IMGBUF_GEM); + if (ret < 0) { + fprintf(stderr, "failed to test move operation.\n"); + goto err_free_src; + } + + wait_for_user_input(0); + ret = g2d_copy_with_scale_test(dev, src, bo, G2D_IMGBUF_GEM); if (ret < 0) { fprintf(stderr, "failed to test copy and scale operation.\n"); diff --git a/lib/libdrm/tests/kms/Makefile.am b/lib/libdrm/tests/kms/Makefile.am new file mode 100644 index 000000000..6645af7ac --- /dev/null +++ b/lib/libdrm/tests/kms/Makefile.am @@ -0,0 +1,36 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ + -I$(top_srcdir) + +AM_CFLAGS = \ + $(WARN_CFLAGS) + +noinst_LTLIBRARIES = libkms-test.la + +libkms_test_la_SOURCES = \ + libkms-test.h \ + libkms-test-crtc.c \ + libkms-test-device.c \ + libkms-test-framebuffer.c \ + libkms-test-plane.c \ + libkms-test-screen.c + +libkms_test_la_LIBADD = \ + $(top_builddir)/libdrm.la + +if HAVE_INSTALL_TESTS +bin_PROGRAMS = \ + kms-steal-crtc \ + kms-universal-planes +else +noinst_PROGRAMS = \ + kms-steal-crtc \ + kms-universal-planes +endif + +kms_steal_crtc_SOURCES = kms-steal-crtc.c +kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS) + +kms_universal_planes_SOURCES = kms-universal-planes.c +kms_universal_planes_LDADD = libkms-test.la $(CAIRO_LIBS) diff --git a/lib/libdrm/tests/kms/Makefile.in b/lib/libdrm/tests/kms/Makefile.in new file mode 100644 index 000000000..2a6f2868f --- /dev/null +++ b/lib/libdrm/tests/kms/Makefile.in @@ -0,0 +1,737 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_INSTALL_TESTS_TRUE@bin_PROGRAMS = kms-steal-crtc$(EXEEXT) \ +@HAVE_INSTALL_TESTS_TRUE@ kms-universal-planes$(EXEEXT) +@HAVE_INSTALL_TESTS_FALSE@noinst_PROGRAMS = kms-steal-crtc$(EXEEXT) \ +@HAVE_INSTALL_TESTS_FALSE@ kms-universal-planes$(EXEEXT) +subdir = tests/kms +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libkms_test_la_DEPENDENCIES = $(top_builddir)/libdrm.la +am_libkms_test_la_OBJECTS = libkms-test-crtc.lo libkms-test-device.lo \ + libkms-test-framebuffer.lo libkms-test-plane.lo \ + libkms-test-screen.lo +libkms_test_la_OBJECTS = $(am_libkms_test_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am_kms_steal_crtc_OBJECTS = kms-steal-crtc.$(OBJEXT) +kms_steal_crtc_OBJECTS = $(am_kms_steal_crtc_OBJECTS) +am__DEPENDENCIES_1 = +kms_steal_crtc_DEPENDENCIES = libkms-test.la ../util/libutil.la \ + $(am__DEPENDENCIES_1) +am_kms_universal_planes_OBJECTS = kms-universal-planes.$(OBJEXT) +kms_universal_planes_OBJECTS = $(am_kms_universal_planes_OBJECTS) +kms_universal_planes_DEPENDENCIES = libkms-test.la \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libkms_test_la_SOURCES) $(kms_steal_crtc_SOURCES) \ + $(kms_universal_planes_SOURCES) +DIST_SOURCES = $(libkms_test_la_SOURCES) $(kms_steal_crtc_SOURCES) \ + $(kms_universal_planes_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLOCK_LIB = @CLOCK_LIB@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CUNIT_CFLAGS = @CUNIT_CFLAGS@ +CUNIT_LIBS = @CUNIT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ +LIBUDEV_LIBS = @LIBUDEV_LIBS@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANPAGES_STYLESHEET = @MANPAGES_STYLESHEET@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +XSLTPROC = @XSLTPROC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +kernel_source = @kernel_source@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ + -I$(top_srcdir) + +AM_CFLAGS = \ + $(WARN_CFLAGS) + +noinst_LTLIBRARIES = libkms-test.la +libkms_test_la_SOURCES = \ + libkms-test.h \ + libkms-test-crtc.c \ + libkms-test-device.c \ + libkms-test-framebuffer.c \ + libkms-test-plane.c \ + libkms-test-screen.c + +libkms_test_la_LIBADD = \ + $(top_builddir)/libdrm.la + +kms_steal_crtc_SOURCES = kms-steal-crtc.c +kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS) +kms_universal_planes_SOURCES = kms-universal-planes.c +kms_universal_planes_LDADD = libkms-test.la $(CAIRO_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/kms/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/kms/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libkms-test.la: $(libkms_test_la_OBJECTS) $(libkms_test_la_DEPENDENCIES) $(EXTRA_libkms_test_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libkms_test_la_OBJECTS) $(libkms_test_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +kms-steal-crtc$(EXEEXT): $(kms_steal_crtc_OBJECTS) $(kms_steal_crtc_DEPENDENCIES) $(EXTRA_kms_steal_crtc_DEPENDENCIES) + @rm -f kms-steal-crtc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_steal_crtc_OBJECTS) $(kms_steal_crtc_LDADD) $(LIBS) + +kms-universal-planes$(EXEEXT): $(kms_universal_planes_OBJECTS) $(kms_universal_planes_DEPENDENCIES) $(EXTRA_kms_universal_planes_DEPENDENCIES) + @rm -f kms-universal-planes$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_universal_planes_OBJECTS) $(kms_universal_planes_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms-steal-crtc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms-universal-planes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkms-test-crtc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkms-test-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkms-test-framebuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkms-test-plane.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkms-test-screen.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/libdrm/tests/kms/kms-steal-crtc.c b/lib/libdrm/tests/kms/kms-steal-crtc.c new file mode 100644 index 000000000..497772e23 --- /dev/null +++ b/lib/libdrm/tests/kms/kms-steal-crtc.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#include <drm_fourcc.h> + +#include "util/pattern.h" +#include "libkms-test.h" + +static void signal_handler(int signum) +{ +} + +int main(int argc, char *argv[]) +{ + struct kms_framebuffer *fb; + struct kms_screen *screen; + struct kms_device *device; + unsigned int index = 0; + struct sigaction sa; + int fd, err; + void *ptr; + + if (argc < 2) { + fprintf(stderr, "usage: %s DEVICE\n", argv[0]); + return 1; + } + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + + err = sigaction(SIGINT, &sa, NULL); + if (err < 0) { + fprintf(stderr, "sigaction() failed: %m\n"); + return 1; + } + + fd = open(argv[1], O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %m\n"); + return 1; + } + + device = kms_device_open(fd); + if (!device) { + fprintf(stderr, "kms_device_open() failed: %m\n"); + return 1; + } + + if (device->num_screens < 1) { + fprintf(stderr, "no screens found\n"); + kms_device_close(device); + close(fd); + return 1; + } + + /* TODO: allow command-line to override */ + screen = device->screens[0]; + + printf("Using screen %s, resolution %ux%u\n", screen->name, + screen->width, screen->height); + + fb = kms_framebuffer_create(device, screen->width, screen->height, + DRM_FORMAT_XRGB8888); + if (!fb) { + fprintf(stderr, "kms_framebuffer_create() failed\n"); + return 1; + } + + err = kms_framebuffer_map(fb, &ptr); + if (err < 0) { + fprintf(stderr, "kms_framebuffer_map() failed: %d\n", err); + return 1; + } + + util_fill_pattern(fb->format, UTIL_PATTERN_SMPTE, &ptr, fb->width, + fb->height, fb->pitch); + + kms_framebuffer_unmap(fb); + + err = kms_screen_set(screen, device->crtcs[index++], fb); + if (err < 0) { + fprintf(stderr, "kms_screen_set() failed: %d\n", err); + return 1; + } + + while (true) { + int nfds = STDIN_FILENO + 1; + struct timeval timeout; + fd_set fds; + + memset(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + + err = select(nfds, &fds, NULL, NULL, &timeout); + if (err < 0) { + if (errno == EINTR) + break; + + fprintf(stderr, "select() failed: %d\n", errno); + break; + } + + if (err > 0) { + if (FD_ISSET(STDIN_FILENO, &fds)) + break; + } + + /* switch CRTC */ + if (index >= device->num_crtcs) + index = 0; + + err = kms_screen_set(screen, device->crtcs[index], fb); + if (err < 0) { + fprintf(stderr, "kms_screen_set() failed: %d\n", err); + break; + } + + index++; + } + + kms_framebuffer_free(fb); + kms_device_close(device); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/kms/kms-universal-planes.c b/lib/libdrm/tests/kms/kms-universal-planes.c new file mode 100644 index 000000000..d8e5fc48f --- /dev/null +++ b/lib/libdrm/tests/kms/kms-universal-planes.c @@ -0,0 +1,361 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <fcntl.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#include <drm_fourcc.h> +#include "xf86drm.h" + +#include "util/common.h" +#include "libkms-test.h" + +static const uint32_t formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBA8888, +}; + +static uint32_t choose_format(struct kms_plane *plane) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (kms_plane_supports_format(plane, formats[i])) + return formats[i]; + + return 0; +} + +static void prepare_framebuffer(struct kms_framebuffer *fb, bool invert) +{ + const unsigned int block_size = 16; + uint32_t colors[2]; + unsigned int i, j; + uint32_t *buf; + void *ptr; + int err; + + switch (fb->format) { + case DRM_FORMAT_XRGB8888: + printf("using XRGB8888 format\n"); + /* XXRRGGBB */ + colors[0] = 0xffff0000; + colors[1] = 0xff0000ff; + break; + + case DRM_FORMAT_XBGR8888: + printf("using XBGR8888 format\n"); + /* XXBBGGRR */ + colors[0] = 0xff0000ff; + colors[1] = 0xffff0000; + break; + + case DRM_FORMAT_RGBA8888: + printf("using RGBA8888 format\n"); + /* RRGGBBAA */ + colors[0] = 0xff0000ff; + colors[1] = 0x0000ffff; + break; + + default: + colors[0] = 0xffffffff; + colors[1] = 0xffffffff; + break; + } + + err = kms_framebuffer_map(fb, &ptr); + if (err < 0) { + fprintf(stderr, "kms_framebuffer_map() failed: %s\n", + strerror(-err)); + return; + } + + buf = ptr; + + for (j = 0; j < fb->height; j++) { + for (i = 0; i < fb->width; i++) { + unsigned int color = (j / block_size) ^ + (i / block_size); + + if (invert) + color ^= color; + + *buf++ = colors[color & 1]; + } + } + + kms_framebuffer_unmap(fb); +} + +int main(int argc, char *argv[]) +{ + static const char opts[] = "chopv"; + static struct option options[] = { + { "cursor", 0, 0, 'c' }, + { "help", 0, 0, 'h' }, + { "overlay", 0, 0, 'o' }, + { "primary", 0, 0, 'p' }, + { "verbose", 0, 0, 'v' }, + { 0, 0, 0, 0 }, + }; + struct kms_framebuffer *cursor = NULL; + struct kms_framebuffer *root = NULL; + struct kms_framebuffer *fb = NULL; + struct kms_device *device; + bool use_overlay = false; + bool use_primary = false; + struct kms_plane *plane; + bool use_cursor = false; + bool verbose = false; + unsigned int i; + int opt, idx; + int fd, err; + + while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) { + switch (opt) { + case 'c': + use_cursor = true; + break; + + case 'h': + break; + + case 'o': + use_overlay = true; + break; + + case 'p': + use_primary = true; + break; + + case 'v': + verbose = true; + break; + + default: + printf("unknown option \"%c\"\n", opt); + return 1; + } + } + + if (optind >= argc) { + fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]); + return 1; + } + + fd = open(argv[optind], O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %m\n"); + return 1; + } + + err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + if (err < 0) { + fprintf(stderr, "drmSetClientCap() failed: %d\n", err); + return 1; + } + + device = kms_device_open(fd); + if (!device) + return 1; + + if (verbose) { + printf("Screens: %u\n", device->num_screens); + + for (i = 0; i < device->num_screens; i++) { + struct kms_screen *screen = device->screens[i]; + const char *status = "disconnected"; + + if (screen->connected) + status = "connected"; + + printf(" %u: %x\n", i, screen->id); + printf(" Status: %s\n", status); + printf(" Name: %s\n", screen->name); + printf(" Resolution: %ux%u\n", screen->width, + screen->height); + } + + printf("Planes: %u\n", device->num_planes); + + for (i = 0; i < device->num_planes; i++) { + struct kms_plane *plane = device->planes[i]; + const char *type = NULL; + + switch (plane->type) { + case DRM_PLANE_TYPE_OVERLAY: + type = "overlay"; + break; + + case DRM_PLANE_TYPE_PRIMARY: + type = "primary"; + break; + + case DRM_PLANE_TYPE_CURSOR: + type = "cursor"; + break; + } + + printf(" %u: %p\n", i, plane); + printf(" ID: %x\n", plane->id); + printf(" CRTC: %x\n", plane->crtc->id); + printf(" Type: %x (%s)\n", plane->type, type); + } + } + + if (use_cursor) { + unsigned int x, y; + uint32_t format; + + plane = kms_device_find_plane_by_type(device, + DRM_PLANE_TYPE_CURSOR, + 0); + if (!plane) { + fprintf(stderr, "no cursor plane found\n"); + return 1; + } + + format = choose_format(plane); + if (!format) { + fprintf(stderr, "no matching format found\n"); + return 1; + } + + cursor = kms_framebuffer_create(device, 32, 32, format); + if (!cursor) { + fprintf(stderr, "failed to create cursor buffer\n"); + return 1; + } + + prepare_framebuffer(cursor, false); + + x = (device->screens[0]->width - cursor->width) / 2; + y = (device->screens[0]->height - cursor->height) / 2; + + kms_plane_set(plane, cursor, x, y); + } + + if (use_overlay) { + uint32_t format; + + plane = kms_device_find_plane_by_type(device, + DRM_PLANE_TYPE_OVERLAY, + 0); + if (!plane) { + fprintf(stderr, "no overlay plane found\n"); + return 1; + } + + format = choose_format(plane); + if (!format) { + fprintf(stderr, "no matching format found\n"); + return 1; + } + + fb = kms_framebuffer_create(device, 320, 240, format); + if (!fb) + return 1; + + prepare_framebuffer(fb, false); + + kms_plane_set(plane, fb, 0, 0); + } + + if (use_primary) { + unsigned int x, y; + uint32_t format; + + plane = kms_device_find_plane_by_type(device, + DRM_PLANE_TYPE_PRIMARY, + 0); + if (!plane) { + fprintf(stderr, "no primary plane found\n"); + return 1; + } + + format = choose_format(plane); + if (!format) { + fprintf(stderr, "no matching format found\n"); + return 1; + } + + root = kms_framebuffer_create(device, 640, 480, format); + if (!root) + return 1; + + prepare_framebuffer(root, true); + + x = (device->screens[0]->width - root->width) / 2; + y = (device->screens[0]->height - root->height) / 2; + + kms_plane_set(plane, root, x, y); + } + + while (1) { + struct timeval timeout = { 1, 0 }; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + + err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout); + if (err < 0) { + fprintf(stderr, "select() failed: %m\n"); + break; + } + + /* timeout */ + if (err == 0) + continue; + + if (FD_ISSET(STDIN_FILENO, &fds)) + break; + } + + if (cursor) + kms_framebuffer_free(cursor); + + if (root) + kms_framebuffer_free(root); + + if (fb) + kms_framebuffer_free(fb); + + kms_device_close(device); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/kms/libkms-test-crtc.c b/lib/libdrm/tests/kms/libkms-test-crtc.c new file mode 100644 index 000000000..3adb49039 --- /dev/null +++ b/lib/libdrm/tests/kms/libkms-test-crtc.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "libkms-test.h" + +struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id) +{ + struct kms_crtc *crtc; + + crtc = calloc(1, sizeof(*crtc)); + if (!crtc) + return NULL; + + crtc->device = device; + crtc->id = id; + + return crtc; +} + +void kms_crtc_free(struct kms_crtc *crtc) +{ + free(crtc); +} diff --git a/lib/libdrm/tests/kms/libkms-test-device.c b/lib/libdrm/tests/kms/libkms-test-device.c new file mode 100644 index 000000000..53c7349b8 --- /dev/null +++ b/lib/libdrm/tests/kms/libkms-test-device.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "util/common.h" +#include "libkms-test.h" + +static const char *const connector_names[] = { + "Unknown", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "Composite", + "SVIDEO", + "LVDS", + "Component", + "9PinDIN", + "DisplayPort", + "HDMI-A", + "HDMI-B", + "TV", + "eDP", + "Virtual", + "DSI", +}; + +static void kms_device_probe_screens(struct kms_device *device) +{ + unsigned int counts[ARRAY_SIZE(connector_names)]; + struct kms_screen *screen; + drmModeRes *res; + int i; + + memset(counts, 0, sizeof(counts)); + + res = drmModeGetResources(device->fd); + if (!res) + return; + + device->screens = calloc(res->count_connectors, sizeof(screen)); + if (!device->screens) + return; + + for (i = 0; i < res->count_connectors; i++) { + unsigned int *count; + const char *type; + int len; + + screen = kms_screen_create(device, res->connectors[i]); + if (!screen) + continue; + + /* assign a unique name to this screen */ + type = connector_names[screen->type]; + count = &counts[screen->type]; + + len = snprintf(NULL, 0, "%s-%u", type, *count); + + screen->name = malloc(len + 1); + if (!screen->name) { + free(screen); + continue; + } + + snprintf(screen->name, len + 1, "%s-%u", type, *count); + (*count)++; + + device->screens[i] = screen; + device->num_screens++; + } + + drmModeFreeResources(res); +} + +static void kms_device_probe_crtcs(struct kms_device *device) +{ + struct kms_crtc *crtc; + drmModeRes *res; + int i; + + res = drmModeGetResources(device->fd); + if (!res) + return; + + device->crtcs = calloc(res->count_crtcs, sizeof(crtc)); + if (!device->crtcs) + return; + + for (i = 0; i < res->count_crtcs; i++) { + crtc = kms_crtc_create(device, res->crtcs[i]); + if (!crtc) + continue; + + device->crtcs[i] = crtc; + device->num_crtcs++; + } + + drmModeFreeResources(res); +} + +static void kms_device_probe_planes(struct kms_device *device) +{ + struct kms_plane *plane; + drmModePlaneRes *res; + unsigned int i; + + res = drmModeGetPlaneResources(device->fd); + if (!res) + return; + + device->planes = calloc(res->count_planes, sizeof(plane)); + if (!device->planes) + return; + + for (i = 0; i < res->count_planes; i++) { + plane = kms_plane_create(device, res->planes[i]); + if (!plane) + continue; + + device->planes[i] = plane; + device->num_planes++; + } + + drmModeFreePlaneResources(res); +} + +static void kms_device_probe(struct kms_device *device) +{ + kms_device_probe_screens(device); + kms_device_probe_crtcs(device); + kms_device_probe_planes(device); +} + +struct kms_device *kms_device_open(int fd) +{ + struct kms_device *device; + + device = calloc(1, sizeof(*device)); + if (!device) + return NULL; + + device->fd = fd; + + kms_device_probe(device); + + return device; +} + +void kms_device_close(struct kms_device *device) +{ + unsigned int i; + + for (i = 0; i < device->num_planes; i++) + kms_plane_free(device->planes[i]); + + free(device->planes); + + for (i = 0; i < device->num_crtcs; i++) + kms_crtc_free(device->crtcs[i]); + + free(device->crtcs); + + for (i = 0; i < device->num_screens; i++) + kms_screen_free(device->screens[i]); + + free(device->screens); + + if (device->fd >= 0) + close(device->fd); + + free(device); +} + +struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device, + uint32_t type, + unsigned int index) +{ + unsigned int i; + + for (i = 0; i < device->num_planes; i++) { + if (device->planes[i]->type == type) { + if (index == 0) + return device->planes[i]; + + index--; + } + } + + return NULL; +} diff --git a/lib/libdrm/tests/kms/libkms-test-framebuffer.c b/lib/libdrm/tests/kms/libkms-test-framebuffer.c new file mode 100644 index 000000000..c9e5ad3c2 --- /dev/null +++ b/lib/libdrm/tests/kms/libkms-test-framebuffer.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include <sys/mman.h> + +#include <drm_fourcc.h> + +#include "xf86drm.h" + +#include "libkms-test.h" + +struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device, + unsigned int width, + unsigned int height, + uint32_t format) +{ + uint32_t handles[4], pitches[4], offsets[4]; + struct drm_mode_create_dumb args; + struct kms_framebuffer *fb; + int err; + + fb = calloc(1, sizeof(*fb)); + if (!fb) + return NULL; + + fb->device = device; + fb->width = width; + fb->height = height; + fb->format = format; + + memset(&args, 0, sizeof(args)); + args.width = width; + args.height = height; + + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + args.bpp = 32; + break; + + default: + free(fb); + return NULL; + } + + err = drmIoctl(device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &args); + if (err < 0) { + free(fb); + return NULL; + } + + fb->handle = args.handle; + fb->pitch = args.pitch; + fb->size = args.size; + + handles[0] = fb->handle; + pitches[0] = fb->pitch; + offsets[0] = 0; + + err = drmModeAddFB2(device->fd, width, height, format, handles, + pitches, offsets, &fb->id, 0); + if (err < 0) { + kms_framebuffer_free(fb); + return NULL; + } + + return fb; +} + +void kms_framebuffer_free(struct kms_framebuffer *fb) +{ + struct kms_device *device = fb->device; + struct drm_mode_destroy_dumb args; + int err; + + if (fb->id) { + err = drmModeRmFB(device->fd, fb->id); + if (err < 0) { + /* not much we can do now */ + } + } + + memset(&args, 0, sizeof(args)); + args.handle = fb->handle; + + err = drmIoctl(device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args); + if (err < 0) { + /* not much we can do now */ + } + + free(fb); +} + +int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp) +{ + struct kms_device *device = fb->device; + struct drm_mode_map_dumb args; + void *ptr; + int err; + + if (fb->ptr) { + *ptrp = fb->ptr; + return 0; + } + + memset(&args, 0, sizeof(args)); + args.handle = fb->handle; + + err = drmIoctl(device->fd, DRM_IOCTL_MODE_MAP_DUMB, &args); + if (err < 0) + return -errno; + + ptr = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED, + device->fd, args.offset); + if (ptr == MAP_FAILED) + return -errno; + + *ptrp = fb->ptr = ptr; + + return 0; +} + +void kms_framebuffer_unmap(struct kms_framebuffer *fb) +{ + if (fb->ptr) { + munmap(fb->ptr, fb->size); + fb->ptr = NULL; + } +} diff --git a/lib/libdrm/tests/kms/libkms-test-plane.c b/lib/libdrm/tests/kms/libkms-test-plane.c new file mode 100644 index 000000000..8eb78af1d --- /dev/null +++ b/lib/libdrm/tests/kms/libkms-test-plane.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include "libkms-test.h" + +static int kms_plane_probe(struct kms_plane *plane) +{ + struct kms_device *device = plane->device; + drmModeObjectPropertiesPtr props; + drmModePlane *p; + unsigned int i; + + p = drmModeGetPlane(device->fd, plane->id); + if (!p) + return -ENODEV; + + /* TODO: allow dynamic assignment to CRTCs */ + if (p->crtc_id == 0) { + for (i = 0; i < device->num_crtcs; i++) { + if (p->possible_crtcs & (1 << i)) { + p->crtc_id = device->crtcs[i]->id; + break; + } + } + } + + for (i = 0; i < device->num_crtcs; i++) { + if (device->crtcs[i]->id == p->crtc_id) { + plane->crtc = device->crtcs[i]; + break; + } + } + + plane->formats = calloc(p->count_formats, sizeof(uint32_t)); + if (!plane->formats) + return -ENOMEM; + + for (i = 0; i < p->count_formats; i++) + plane->formats[i] = p->formats[i]; + + plane->num_formats = p->count_formats; + + drmModeFreePlane(p); + + props = drmModeObjectGetProperties(device->fd, plane->id, + DRM_MODE_OBJECT_PLANE); + if (!props) + return -ENODEV; + + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop; + + prop = drmModeGetProperty(device->fd, props->props[i]); + if (prop) { + if (strcmp(prop->name, "type") == 0) + plane->type = props->prop_values[i]; + + drmModeFreeProperty(prop); + } + } + + drmModeFreeObjectProperties(props); + + return 0; +} + +struct kms_plane *kms_plane_create(struct kms_device *device, uint32_t id) +{ + struct kms_plane *plane; + + plane = calloc(1, sizeof(*plane)); + if (!plane) + return NULL; + + plane->device = device; + plane->id = id; + + kms_plane_probe(plane); + + return plane; +} + +void kms_plane_free(struct kms_plane *plane) +{ + free(plane); +} + +int kms_plane_set(struct kms_plane *plane, struct kms_framebuffer *fb, + unsigned int x, unsigned int y) +{ + struct kms_device *device = plane->device; + int err; + + err = drmModeSetPlane(device->fd, plane->id, plane->crtc->id, fb->id, + 0, x, y, fb->width, fb->height, 0 << 16, + 0 << 16, fb->width << 16, fb->height << 16); + if (err < 0) + return -errno; + + return 0; +} + +bool kms_plane_supports_format(struct kms_plane *plane, uint32_t format) +{ + unsigned int i; + + for (i = 0; i < plane->num_formats; i++) + if (plane->formats[i] == format) + return true; + + return false; +} diff --git a/lib/libdrm/tests/kms/libkms-test-screen.c b/lib/libdrm/tests/kms/libkms-test-screen.c new file mode 100644 index 000000000..336902228 --- /dev/null +++ b/lib/libdrm/tests/kms/libkms-test-screen.c @@ -0,0 +1,92 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include "libkms-test.h" + +static void kms_screen_probe(struct kms_screen *screen) +{ + struct kms_device *device = screen->device; + drmModeConnector *con; + + con = drmModeGetConnector(device->fd, screen->id); + if (!con) + return; + + screen->type = con->connector_type; + + if (con->connection == DRM_MODE_CONNECTED) + screen->connected = true; + else + screen->connected = false; + + memcpy(&screen->mode, &con->modes[0], sizeof(drmModeModeInfo)); + screen->width = screen->mode.hdisplay; + screen->height = screen->mode.vdisplay; + + drmModeFreeConnector(con); +} + +struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id) +{ + struct kms_screen *screen; + + screen = calloc(1, sizeof(*screen)); + if (!screen) + return NULL; + + screen->device = device; + screen->id = id; + + kms_screen_probe(screen); + + return screen; +} + +void kms_screen_free(struct kms_screen *screen) +{ + if (screen) + free(screen->name); + + free(screen); +} + +int kms_screen_set(struct kms_screen *screen, struct kms_crtc *crtc, + struct kms_framebuffer *fb) +{ + struct kms_device *device = screen->device; + int err; + + err = drmModeSetCrtc(device->fd, crtc->id, fb->id, 0, 0, &screen->id, + 1, &screen->mode); + if (err < 0) + return -errno; + + return 0; +} diff --git a/lib/libdrm/tests/kms/libkms-test.h b/lib/libdrm/tests/kms/libkms-test.h new file mode 100644 index 000000000..7b1d02e9a --- /dev/null +++ b/lib/libdrm/tests/kms/libkms-test.h @@ -0,0 +1,120 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef LIBKMS_TEST_H +#define LIBKMS_TEST_H + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#include <xf86drmMode.h> + +struct kms_device { + int fd; + + struct kms_screen **screens; + unsigned int num_screens; + + struct kms_crtc **crtcs; + unsigned int num_crtcs; + + struct kms_plane **planes; + unsigned int num_planes; +}; + +struct kms_device *kms_device_open(int fd); +void kms_device_close(struct kms_device *device); + +struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device, + uint32_t type, + unsigned int index); + +struct kms_crtc { + struct kms_device *device; + uint32_t id; +}; + +struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id); +void kms_crtc_free(struct kms_crtc *crtc); + +struct kms_framebuffer { + struct kms_device *device; + + unsigned int width; + unsigned int height; + unsigned int pitch; + uint32_t format; + size_t size; + + uint32_t handle; + uint32_t id; + + void *ptr; +}; + +struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device, + unsigned int width, + unsigned int height, + uint32_t format); +void kms_framebuffer_free(struct kms_framebuffer *fb); +int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp); +void kms_framebuffer_unmap(struct kms_framebuffer *fb); + +struct kms_screen { + struct kms_device *device; + bool connected; + uint32_t type; + uint32_t id; + + unsigned int width; + unsigned int height; + char *name; + + drmModeModeInfo mode; +}; + +struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id); +void kms_screen_free(struct kms_screen *screen); + +int kms_screen_set(struct kms_screen *screen, struct kms_crtc *crtc, + struct kms_framebuffer *fb); + +struct kms_plane { + struct kms_device *device; + struct kms_crtc *crtc; + unsigned int type; + uint32_t id; + + uint32_t *formats; + unsigned int num_formats; +}; + +struct kms_plane *kms_plane_create(struct kms_device *device, uint32_t id); +void kms_plane_free(struct kms_plane *plane); + +int kms_plane_set(struct kms_plane *plane, struct kms_framebuffer *fb, + unsigned int x, unsigned int y); +bool kms_plane_supports_format(struct kms_plane *plane, uint32_t format); + +#endif diff --git a/lib/libdrm/tests/kmstest/Makefile.am b/lib/libdrm/tests/kmstest/Makefile.am index fd21e612b..ced541b74 100644 --- a/lib/libdrm/tests/kmstest/Makefile.am +++ b/lib/libdrm/tests/kmstest/Makefile.am @@ -2,6 +2,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/libkms/ \ + -I$(top_srcdir)/tests/ \ -I$(top_srcdir) if HAVE_INSTALL_TESTS @@ -16,8 +17,9 @@ kmstest_SOURCES = \ main.c kmstest_LDADD = \ - $(top_builddir)/libdrm.la \ - $(top_builddir)/libkms/libkms.la + $(top_builddir)/tests/util/libutil.la \ + $(top_builddir)/libkms/libkms.la \ + $(top_builddir)/libdrm.la run: kmstest ./kmstest diff --git a/lib/libdrm/tests/kmstest/main.c b/lib/libdrm/tests/kmstest/main.c index 120bc0fa8..a0e4ebbd0 100644 --- a/lib/libdrm/tests/kmstest/main.c +++ b/lib/libdrm/tests/kmstest/main.c @@ -25,12 +25,14 @@ * **************************************************************************/ - +#include <getopt.h> #include <stdio.h> #include <string.h> #include "xf86drm.h" #include "libkms.h" +#include "util/kms.h" + #define CHECK_RET_RETURN(ret, str) \ if (ret < 0) { \ printf("%s: %s (%s)\n", __func__, str, strerror(-ret)); \ @@ -56,26 +58,37 @@ static int test_bo(struct kms_driver *kms) return 0; } -static const char *drivers[] = { - "i915", - "radeon", - "nouveau", - "vmwgfx", - "exynos", - "amdgpu", - "imx-drm", - "rockchip", - "atmel-hlcdc", - NULL -}; +static void usage(const char *program) +{ + fprintf(stderr, "Usage: %s [options]\n", program); + fprintf(stderr, "\n"); + fprintf(stderr, " -D DEVICE open the given device\n"); + fprintf(stderr, " -M MODULE open the given module\n"); +} int main(int argc, char** argv) { + static const char optstr[] = "D:M:"; struct kms_driver *kms; - int ret, fd, i; + int c, fd, ret; + char *device = NULL; + char *module = NULL; + + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 'D': + device = optarg; + break; + case 'M': + module = optarg; + break; + default: + usage(argv[0]); + return 0; + } + } - for (i = 0, fd = -1; fd < 0 && drivers[i]; i++) - fd = drmOpen(drivers[i], NULL); + fd = util_open(device, module); CHECK_RET_RETURN(fd, "Could not open device"); ret = kms_create(fd, &kms); diff --git a/lib/libdrm/tests/modeprint/Makefile.am b/lib/libdrm/tests/modeprint/Makefile.am index 895805fd3..601dbc964 100644 --- a/lib/libdrm/tests/modeprint/Makefile.am +++ b/lib/libdrm/tests/modeprint/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir) if HAVE_INSTALL_TESTS diff --git a/lib/libdrm/tests/modeprint/modeprint.c b/lib/libdrm/tests/modeprint/modeprint.c index 5e953f71f..0d854103c 100644 --- a/lib/libdrm/tests/modeprint/modeprint.c +++ b/lib/libdrm/tests/modeprint/modeprint.c @@ -41,7 +41,7 @@ #include "xf86drm.h" #include "xf86drmMode.h" -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +#include "util/common.h" int current; int connectors; diff --git a/lib/libdrm/tests/modetest/Android.mk b/lib/libdrm/tests/modetest/Android.mk index 0fdfe6856..e616558fd 100644 --- a/lib/libdrm/tests/modetest/Android.mk +++ b/lib/libdrm/tests/modetest/Android.mk @@ -8,5 +8,6 @@ LOCAL_SRC_FILES := $(MODETEST_FILES) LOCAL_MODULE := modetest LOCAL_SHARED_LIBRARIES := libdrm +LOCAL_STATIC_LIBRARIES := libdrm_util include $(BUILD_EXECUTABLE) diff --git a/lib/libdrm/tests/modetest/Makefile.am b/lib/libdrm/tests/modetest/Makefile.am index 93820fac7..25ce372fc 100644 --- a/lib/libdrm/tests/modetest/Makefile.am +++ b/lib/libdrm/tests/modetest/Makefile.am @@ -4,6 +4,7 @@ AM_CFLAGS = $(filter-out -Wpointer-arith, $(WARN_CFLAGS)) AM_CFLAGS += \ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir) if HAVE_INSTALL_TESTS @@ -18,11 +19,8 @@ modetest_SOURCES = $(MODETEST_FILES) modetest_LDADD = \ $(top_builddir)/libdrm.la \ + $(top_builddir)/tests/util/libutil.la \ + $(CAIRO_LIBS) \ -lpthread -if HAVE_CAIRO -AM_CFLAGS += $(CAIRO_CFLAGS) -modetest_LDADD += $(CAIRO_LIBS) -endif - EXTRA_DIST = Android.mk diff --git a/lib/libdrm/tests/modetest/buffers.c b/lib/libdrm/tests/modetest/buffers.c index ebb14ef8b..4fd310b9b 100644 --- a/lib/libdrm/tests/modetest/buffers.c +++ b/lib/libdrm/tests/modetest/buffers.c @@ -44,13 +44,6 @@ #include "buffers.h" -#ifdef HAVE_CAIRO -#include <math.h> -#include <cairo.h> -#endif - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - struct bo { int fd; @@ -62,956 +55,6 @@ struct bo }; /* ----------------------------------------------------------------------------- - * Formats - */ - -struct color_component { - unsigned int length; - unsigned int offset; -}; - -struct rgb_info { - struct color_component red; - struct color_component green; - struct color_component blue; - struct color_component alpha; -}; - -enum yuv_order { - YUV_YCbCr = 1, - YUV_YCrCb = 2, - YUV_YC = 4, - YUV_CY = 8, -}; - -struct yuv_info { - enum yuv_order order; - unsigned int xsub; - unsigned int ysub; - unsigned int chroma_stride; -}; - -struct format_info { - unsigned int format; - const char *name; - const struct rgb_info rgb; - const struct yuv_info yuv; -}; - -#define MAKE_RGB_INFO(rl, ro, gl, go, bl, bo, al, ao) \ - .rgb = { { (rl), (ro) }, { (gl), (go) }, { (bl), (bo) }, { (al), (ao) } } - -#define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \ - .yuv = { (order), (xsub), (ysub), (chroma_stride) } - -static const struct format_info format_info[] = { - /* YUV packed */ - { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) }, - { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) }, - { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) }, - { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) }, - /* YUV semi-planar */ - { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) }, - { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) }, - { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) }, - { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) }, - /* YUV planar */ - { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) }, - { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, - /* RGB16 */ - { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, - { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) }, - { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) }, - { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) }, - { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) }, - { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) }, - { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) }, - { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) }, - { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) }, - { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) }, - { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) }, - { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) }, - { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) }, - { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) }, - { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) }, - { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) }, - { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) }, - { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) }, - /* RGB24 */ - { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, - { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, - /* RGB32 */ - { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) }, - { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, - { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) }, - { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, - { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) }, - { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) }, - { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, - { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) }, - { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) }, - { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) }, - { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) }, - { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) }, - { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) }, - { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) }, - { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) }, - { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) }, -}; - -unsigned int format_fourcc(const char *name) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(format_info); i++) { - if (!strcmp(format_info[i].name, name)) - return format_info[i].format; - } - return 0; -} - -/* ----------------------------------------------------------------------------- - * Test patterns - */ - -struct color_rgb24 { - unsigned int value:24; -} __attribute__((__packed__)); - -struct color_yuv { - unsigned char y; - unsigned char u; - unsigned char v; -}; - -#define MAKE_YUV_601_Y(r, g, b) \ - ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) -#define MAKE_YUV_601_U(r, g, b) \ - (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) -#define MAKE_YUV_601_V(r, g, b) \ - (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) - -#define MAKE_YUV_601(r, g, b) \ - { .y = MAKE_YUV_601_Y(r, g, b), \ - .u = MAKE_YUV_601_U(r, g, b), \ - .v = MAKE_YUV_601_V(r, g, b) } - -#define MAKE_RGBA(rgb, r, g, b, a) \ - ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \ - (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \ - (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \ - (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset)) - -#define MAKE_RGB24(rgb, r, g, b) \ - { .value = MAKE_RGBA(rgb, r, g, b, 0) } - -static void -fill_smpte_yuv_planar(const struct yuv_info *yuv, - unsigned char *y_mem, unsigned char *u_mem, - unsigned char *v_mem, unsigned int width, - unsigned int height, unsigned int stride) -{ - const struct color_yuv colors_top[] = { - MAKE_YUV_601(191, 192, 192), /* grey */ - MAKE_YUV_601(192, 192, 0), /* yellow */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(0, 192, 0), /* green */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(192, 0, 0), /* red */ - MAKE_YUV_601(0, 0, 192), /* blue */ - }; - const struct color_yuv colors_middle[] = { - MAKE_YUV_601(0, 0, 192), /* blue */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 192, 192), /* grey */ - }; - const struct color_yuv colors_bottom[] = { - MAKE_YUV_601(0, 33, 76), /* in-phase */ - MAKE_YUV_601(255, 255, 255), /* super white */ - MAKE_YUV_601(50, 0, 106), /* quadrature */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(9, 9, 9), /* 3.5% */ - MAKE_YUV_601(19, 19, 19), /* 7.5% */ - MAKE_YUV_601(29, 29, 29), /* 11.5% */ - MAKE_YUV_601(19, 19, 19), /* black */ - }; - unsigned int cs = yuv->chroma_stride; - unsigned int xsub = yuv->xsub; - unsigned int ysub = yuv->ysub; - unsigned int x; - unsigned int y; - - /* Luma */ - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[x] = colors_top[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[x] = colors_middle[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; - for (; x < width * 6 / 7; ++x) - y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4].y; - for (; x < width; ++x) - y_mem[x] = colors_bottom[7].y; - y_mem += stride; - } - - /* Chroma */ - for (y = 0; y < height / ysub * 6 / 9; ++y) { - for (x = 0; x < width; x += xsub) { - u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; - v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; - } - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } - - for (; y < height / ysub * 7 / 9; ++y) { - for (x = 0; x < width; x += xsub) { - u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; - v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; - } - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } - - for (; y < height / ysub; ++y) { - for (x = 0; x < width * 5 / 7; x += xsub) { - u_mem[x*cs/xsub] = - colors_bottom[x * 4 / (width * 5 / 7)].u; - v_mem[x*cs/xsub] = - colors_bottom[x * 4 / (width * 5 / 7)].v; - } - for (; x < width * 6 / 7; x += xsub) { - u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].u; - v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].v; - } - for (; x < width; x += xsub) { - u_mem[x*cs/xsub] = colors_bottom[7].u; - v_mem[x*cs/xsub] = colors_bottom[7].v; - } - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } -} - -static void -fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem, - unsigned int width, unsigned int height, - unsigned int stride) -{ - const struct color_yuv colors_top[] = { - MAKE_YUV_601(191, 192, 192), /* grey */ - MAKE_YUV_601(192, 192, 0), /* yellow */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(0, 192, 0), /* green */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(192, 0, 0), /* red */ - MAKE_YUV_601(0, 0, 192), /* blue */ - }; - const struct color_yuv colors_middle[] = { - MAKE_YUV_601(0, 0, 192), /* blue */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 0, 192), /* magenta */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(0, 192, 192), /* cyan */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(192, 192, 192), /* grey */ - }; - const struct color_yuv colors_bottom[] = { - MAKE_YUV_601(0, 33, 76), /* in-phase */ - MAKE_YUV_601(255, 255, 255), /* super white */ - MAKE_YUV_601(50, 0, 106), /* quadrature */ - MAKE_YUV_601(19, 19, 19), /* black */ - MAKE_YUV_601(9, 9, 9), /* 3.5% */ - MAKE_YUV_601(19, 19, 19), /* 7.5% */ - MAKE_YUV_601(29, 29, 29), /* 11.5% */ - MAKE_YUV_601(19, 19, 19), /* black */ - }; - unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; - unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; - unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; - unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; - unsigned int x; - unsigned int y; - - /* Luma */ - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[2*x] = colors_top[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - y_mem[2*x] = colors_middle[x * 7 / width].y; - y_mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; - for (; x < width * 6 / 7; ++x) - y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4].y; - for (; x < width; ++x) - y_mem[2*x] = colors_bottom[7].y; - y_mem += stride; - } - - /* Chroma */ - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; x += 2) { - c_mem[2*x+u] = colors_top[x * 7 / width].u; - c_mem[2*x+v] = colors_top[x * 7 / width].v; - } - c_mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; x += 2) { - c_mem[2*x+u] = colors_middle[x * 7 / width].u; - c_mem[2*x+v] = colors_middle[x * 7 / width].v; - } - c_mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; x += 2) { - c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; - c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; - } - for (; x < width * 6 / 7; x += 2) { - c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].u; - c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * - 3 / (width / 7) + 4].v; - } - for (; x < width; x += 2) { - c_mem[2*x+u] = colors_bottom[7].u; - c_mem[2*x+v] = colors_bottom[7].v; - } - c_mem += stride; - } -} - -static void -fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const uint16_t colors_top[] = { - MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ - MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ - MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ - MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ - MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ - MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ - MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ - }; - const uint16_t colors_middle[] = { - MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ - }; - const uint16_t colors_bottom[] = { - MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ - MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ - MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ - MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - }; - unsigned int x; - unsigned int y; - - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint16_t *)mem)[x] = colors_top[x * 7 / width]; - mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint16_t *)mem)[x] = colors_middle[x * 7 / width]; - mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - ((uint16_t *)mem)[x] = - colors_bottom[x * 4 / (width * 5 / 7)]; - for (; x < width * 6 / 7; ++x) - ((uint16_t *)mem)[x] = - colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4]; - for (; x < width; ++x) - ((uint16_t *)mem)[x] = colors_bottom[7]; - mem += stride; - } -} - -static void -fill_smpte_rgb24(const struct rgb_info *rgb, void *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct color_rgb24 colors_top[] = { - MAKE_RGB24(rgb, 192, 192, 192), /* grey */ - MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ - MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ - MAKE_RGB24(rgb, 0, 192, 0), /* green */ - MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ - MAKE_RGB24(rgb, 192, 0, 0), /* red */ - MAKE_RGB24(rgb, 0, 0, 192), /* blue */ - }; - const struct color_rgb24 colors_middle[] = { - MAKE_RGB24(rgb, 0, 0, 192), /* blue */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 192, 192, 192), /* grey */ - }; - const struct color_rgb24 colors_bottom[] = { - MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ - MAKE_RGB24(rgb, 255, 255, 255), /* super white */ - MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ - MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ - MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ - MAKE_RGB24(rgb, 19, 19, 19), /* black */ - }; - unsigned int x; - unsigned int y; - - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_top[x * 7 / width]; - mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_middle[x * 7 / width]; - mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_bottom[x * 4 / (width * 5 / 7)]; - for (; x < width * 6 / 7; ++x) - ((struct color_rgb24 *)mem)[x] = - colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4]; - for (; x < width; ++x) - ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; - mem += stride; - } -} - -static void -fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const uint32_t colors_top[] = { - MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ - MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ - MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ - MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ - MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ - MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ - MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ - }; - const uint32_t colors_middle[] = { - MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ - MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ - MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ - }; - const uint32_t colors_bottom[] = { - MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ - MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ - MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ - MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ - MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ - }; - unsigned int x; - unsigned int y; - - for (y = 0; y < height * 6 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint32_t *)mem)[x] = colors_top[x * 7 / width]; - mem += stride; - } - - for (; y < height * 7 / 9; ++y) { - for (x = 0; x < width; ++x) - ((uint32_t *)mem)[x] = colors_middle[x * 7 / width]; - mem += stride; - } - - for (; y < height; ++y) { - for (x = 0; x < width * 5 / 7; ++x) - ((uint32_t *)mem)[x] = - colors_bottom[x * 4 / (width * 5 / 7)]; - for (; x < width * 6 / 7; ++x) - ((uint32_t *)mem)[x] = - colors_bottom[(x - width * 5 / 7) * 3 - / (width / 7) + 4]; - for (; x < width; ++x) - ((uint32_t *)mem)[x] = colors_bottom[7]; - mem += stride; - } -} - -static void -fill_smpte(const struct format_info *info, void *planes[3], unsigned int width, - unsigned int height, unsigned int stride) -{ - unsigned char *u, *v; - - switch (info->format) { - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - return fill_smpte_yuv_packed(&info->yuv, planes[0], width, - height, stride); - - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; - v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; - return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, - width, height, stride); - - case DRM_FORMAT_YUV420: - return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], - planes[2], width, height, stride); - - case DRM_FORMAT_YVU420: - return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], - planes[1], width, height, stride); - - 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_RGB565: - case DRM_FORMAT_BGR565: - 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: - return fill_smpte_rgb16(&info->rgb, planes[0], - width, height, stride); - - case DRM_FORMAT_BGR888: - case DRM_FORMAT_RGB888: - return fill_smpte_rgb24(&info->rgb, planes[0], - width, height, stride); - 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: - return fill_smpte_rgb32(&info->rgb, planes[0], - width, height, stride); - } -} - -/* swap these for big endian.. */ -#define RED 2 -#define GREEN 1 -#define BLUE 0 - -static void -make_pwetty(void *data, int width, int height, int stride, uint32_t format) -{ -#ifdef HAVE_CAIRO - cairo_surface_t *surface; - cairo_t *cr; - int x, y; - cairo_format_t cairo_format; - - /* we can ignore the order of R,G,B channels */ - switch (format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ABGR8888: - cairo_format = CAIRO_FORMAT_ARGB32; - break; - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - cairo_format = CAIRO_FORMAT_RGB16_565; - break; - default: - return; - } - - surface = cairo_image_surface_create_for_data(data, - cairo_format, - width, height, - stride); - cr = cairo_create(surface); - cairo_surface_destroy(surface); - - cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); - for (x = 0; x < width; x += 250) - for (y = 0; y < height; y += 250) { - char buf[64]; - - cairo_move_to(cr, x, y - 20); - cairo_line_to(cr, x, y + 20); - cairo_move_to(cr, x - 20, y); - cairo_line_to(cr, x + 20, y); - cairo_new_sub_path(cr); - cairo_arc(cr, x, y, 10, 0, M_PI * 2); - cairo_set_line_width(cr, 4); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_set_line_width(cr, 2); - cairo_stroke(cr); - - snprintf(buf, sizeof buf, "%d, %d", x, y); - cairo_move_to(cr, x + 20, y + 20); - cairo_text_path(cr, buf); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); - } - - cairo_destroy(cr); -#endif -} - -static void -fill_tiles_yuv_planar(const struct format_info *info, - unsigned char *y_mem, unsigned char *u_mem, - unsigned char *v_mem, unsigned int width, - unsigned int height, unsigned int stride) -{ - const struct yuv_info *yuv = &info->yuv; - unsigned int cs = yuv->chroma_stride; - unsigned int xsub = yuv->xsub; - unsigned int ysub = yuv->ysub; - unsigned int x; - unsigned int y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - struct color_yuv color = - MAKE_YUV_601((rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff); - - y_mem[x] = color.y; - u_mem[x/xsub*cs] = color.u; - v_mem[x/xsub*cs] = color.v; - } - - y_mem += stride; - if ((y + 1) % ysub == 0) { - u_mem += stride * cs / xsub; - v_mem += stride * cs / xsub; - } - } -} - -static void -fill_tiles_yuv_packed(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, - unsigned int stride) -{ - const struct yuv_info *yuv = &info->yuv; - unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; - unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; - unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; - unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; - unsigned int x; - unsigned int y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; x += 2) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - struct color_yuv color = - MAKE_YUV_601((rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff); - - y_mem[2*x] = color.y; - c_mem[2*x+u] = color.u; - y_mem[2*x+2] = color.y; - c_mem[2*x+v] = color.v; - } - - y_mem += stride; - c_mem += stride; - } -} - -static void -fill_tiles_rgb16(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct rgb_info *rgb = &info->rgb; - unsigned char *mem_base = mem; - unsigned int x, y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - uint16_t color = - MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff, - 255); - - ((uint16_t *)mem)[x] = color; - } - mem += stride; - } - - make_pwetty(mem_base, width, height, stride, info->format); -} - -static void -fill_tiles_rgb24(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct rgb_info *rgb = &info->rgb; - unsigned int x, y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - struct color_rgb24 color = - MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff); - - ((struct color_rgb24 *)mem)[x] = color; - } - mem += stride; - } -} - -static void -fill_tiles_rgb32(const struct format_info *info, unsigned char *mem, - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct rgb_info *rgb = &info->rgb; - unsigned char *mem_base = mem; - unsigned int x, y; - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - div_t d = div(x+y, width); - uint32_t rgb32 = 0x00130502 * (d.quot >> 6) - + 0x000a1120 * (d.rem >> 6); - uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; - uint32_t color = - MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, - (rgb32 >> 8) & 0xff, rgb32 & 0xff, - alpha); - - ((uint32_t *)mem)[x] = color; - } - mem += stride; - } - - make_pwetty(mem_base, width, height, stride, info->format); -} - -static void -fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, - unsigned int height, unsigned int stride) -{ - unsigned char *u, *v; - - switch (info->format) { - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - return fill_tiles_yuv_packed(info, planes[0], - width, height, stride); - - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; - v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; - return fill_tiles_yuv_planar(info, planes[0], u, v, - width, height, stride); - - case DRM_FORMAT_YUV420: - return fill_tiles_yuv_planar(info, planes[0], planes[1], - planes[2], width, height, stride); - - case DRM_FORMAT_YVU420: - return fill_tiles_yuv_planar(info, planes[0], planes[2], - planes[1], width, height, stride); - - 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_RGB565: - case DRM_FORMAT_BGR565: - 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: - return fill_tiles_rgb16(info, planes[0], - width, height, stride); - - case DRM_FORMAT_BGR888: - case DRM_FORMAT_RGB888: - return fill_tiles_rgb24(info, planes[0], - width, height, stride); - 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: - return fill_tiles_rgb32(info, planes[0], - width, height, stride); - } -} - -static void -fill_plain(const struct format_info *info, void *planes[3], unsigned int width, - unsigned int height, unsigned int stride) -{ - memset(planes[0], 0x77, stride * height); -} - -/* - * fill_pattern - Fill a buffer with a test pattern - * @format: Pixel format - * @pattern: Test pattern - * @buffer: Buffer memory - * @width: Width in pixels - * @height: Height in pixels - * @stride: Line stride (pitch) in bytes - * - * Fill the buffer with the test pattern specified by the pattern parameter. - * Supported formats vary depending on the selected pattern. - */ -static void -fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3], - unsigned int width, unsigned int height, unsigned int stride) -{ - const struct format_info *info = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format_info); ++i) { - if (format_info[i].format == format) { - info = &format_info[i]; - break; - } - } - - if (info == NULL) - return; - - switch (pattern) { - case PATTERN_TILES: - return fill_tiles(info, planes, width, height, stride); - - case PATTERN_SMPTE: - return fill_smpte(info, planes, width, height, stride); - - case PATTERN_PLAIN: - return fill_plain(info, planes, width, height, stride); - - default: - printf("Error: unsupported test pattern %u.\n", pattern); - break; - } -} - -/* ----------------------------------------------------------------------------- * Buffers management */ @@ -1086,7 +129,7 @@ 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 offsets[4], enum util_fill_pattern pattern) { unsigned int virtual_height; struct bo *bo; @@ -1280,7 +323,7 @@ bo_create(int fd, unsigned int format, break; } - fill_pattern(format, pattern, planes, width, height, pitches[0]); + util_fill_pattern(format, pattern, planes, width, height, pitches[0]); bo_unmap(bo); return bo; diff --git a/lib/libdrm/tests/modetest/buffers.h b/lib/libdrm/tests/modetest/buffers.h index ad73d0e4b..7f95396b4 100644 --- a/lib/libdrm/tests/modetest/buffers.h +++ b/lib/libdrm/tests/modetest/buffers.h @@ -27,20 +27,14 @@ #ifndef __BUFFERS_H__ #define __BUFFERS_H__ -struct bo; +#include "util/pattern.h" -enum fill_pattern { - PATTERN_TILES = 0, - PATTERN_PLAIN = 1, - PATTERN_SMPTE = 2, -}; +struct bo; 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 offsets[4], enum util_fill_pattern pattern); void bo_destroy(struct bo *bo); -unsigned int format_fourcc(const char *name); - #endif diff --git a/lib/libdrm/tests/modetest/cursor.c b/lib/libdrm/tests/modetest/cursor.c index d8a19bd22..6de82a4a7 100644 --- a/lib/libdrm/tests/modetest/cursor.c +++ b/lib/libdrm/tests/modetest/cursor.c @@ -40,11 +40,11 @@ #include "xf86drm.h" #include "xf86drmMode.h" +#include "util/common.h" + #include "buffers.h" #include "cursor.h" -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - struct cursor { int fd; uint32_t bo_handle; diff --git a/lib/libdrm/tests/modetest/modetest.c b/lib/libdrm/tests/modetest/modetest.c index 3b01918d1..a5ac5bd5e 100644 --- a/lib/libdrm/tests/modetest/modetest.c +++ b/lib/libdrm/tests/modetest/modetest.c @@ -37,6 +37,7 @@ * TODO: use cairo to write the mode info on the selected output once * the mode has been programmed, along with possible test patterns. */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -52,13 +53,21 @@ #include <string.h> #include <strings.h> #include <errno.h> -#include <sys/poll.h> +#include <poll.h> #include <sys/time.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include "xf86drm.h" #include "xf86drmMode.h" #include "drm_fourcc.h" +#include "util/common.h" +#include "util/format.h" +#include "util/kms.h" +#include "util/pattern.h" + #include "buffers.h" #include "cursor.h" @@ -116,70 +125,11 @@ struct device { } mode; }; -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) static inline int64_t U642I64(uint64_t val) { return (int64_t)*((int64_t *)&val); } -struct type_name { - int type; - const char *name; -}; - -#define type_name_fn(res) \ -const char * res##_str(int type) { \ - unsigned int i; \ - for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \ - if (res##_names[i].type == type) \ - return res##_names[i].name; \ - } \ - return "(invalid)"; \ -} - -struct type_name encoder_type_names[] = { - { DRM_MODE_ENCODER_NONE, "none" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, - { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, - { DRM_MODE_ENCODER_DSI, "DSI" }, - { DRM_MODE_ENCODER_DPMST, "DPMST" }, -}; - -static type_name_fn(encoder_type) - -struct type_name connector_status_names[] = { - { DRM_MODE_CONNECTED, "connected" }, - { DRM_MODE_DISCONNECTED, "disconnected" }, - { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, -}; - -static type_name_fn(connector_status) - -struct type_name connector_type_names[] = { - { DRM_MODE_CONNECTOR_Unknown, "unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, - { DRM_MODE_CONNECTOR_TV, "TV" }, - { DRM_MODE_CONNECTOR_eDP, "eDP" }, - { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, - { DRM_MODE_CONNECTOR_DSI, "DSI" }, -}; - -static type_name_fn(connector_type) - #define bit_name_fn(res) \ const char * res##_str(int type) { \ unsigned int i; \ @@ -239,7 +189,7 @@ static void dump_encoders(struct device *dev) printf("%d\t%d\t%s\t0x%08x\t0x%08x\n", encoder->encoder_id, encoder->crtc_id, - encoder_type_str(encoder->encoder_type), + util_lookup_encoder_type_name(encoder->encoder_type), encoder->possible_crtcs, encoder->possible_clones); } @@ -383,7 +333,7 @@ static void dump_connectors(struct device *dev) printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t", connector->connector_id, connector->encoder_id, - connector_status_str(connector->connection), + util_lookup_connector_status_name(connector->connection), _connector->name, connector->mmWidth, connector->mmHeight, connector->count_modes); @@ -607,10 +557,11 @@ static struct resources *get_resources(struct device *dev) /* Set the name of all connectors based on the type name and the per-type ID. */ for (i = 0; i < res->res->count_connectors; i++) { struct connector *connector = &res->connectors[i]; + drmModeConnector *conn = connector->connector; asprintf(&connector->name, "%s-%u", - connector_type_str(connector->connector->connector_type), - connector->connector->connector_type_id); + util_lookup_connector_type_name(conn->connector_type), + conn->connector_type_id); } #define get_properties(_res, __res, type, Type) \ @@ -1047,7 +998,7 @@ static int set_plane(struct device *dev, struct plane_arg *p) p->w, p->h, p->format_str, plane_id); plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h, handles, - pitches, offsets, PATTERN_TILES); + pitches, offsets, UTIL_PATTERN_TILES); if (plane_bo == NULL) return -1; @@ -1123,8 +1074,9 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co dev->mode.height = pipe->mode->vdisplay; } - bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height, - handles, pitches, offsets, PATTERN_SMPTE); + bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width, + dev->mode.height, handles, pitches, offsets, + UTIL_PATTERN_SMPTE); if (bo == NULL) return; @@ -1202,7 +1154,7 @@ static void set_cursors(struct device *dev, struct pipe_arg *pipes, unsigned int * translucent alpha */ bo = bo_create(dev->fd, DRM_FORMAT_ARGB8888, cw, ch, handles, pitches, - offsets, PATTERN_PLAIN); + offsets, UTIL_PATTERN_PLAIN); if (bo == NULL) return; @@ -1241,9 +1193,9 @@ static void test_page_flip(struct device *dev, struct pipe_arg *pipes, unsigned unsigned int i; int ret; - other_bo = bo_create(dev->fd, pipes[0].fourcc, - dev->mode.width, dev->mode.height, - handles, pitches, offsets, PATTERN_PLAIN); + other_bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width, + dev->mode.height, handles, pitches, offsets, + UTIL_PATTERN_PLAIN); if (other_bo == NULL) return; @@ -1391,7 +1343,7 @@ static int parse_connector(struct pipe_arg *pipe, const char *arg) pipe->format_str[4] = '\0'; } - pipe->fourcc = format_fourcc(pipe->format_str); + pipe->fourcc = util_format_fourcc(pipe->format_str); if (pipe->fourcc == 0) { fprintf(stderr, "unknown format %s\n", pipe->format_str); return -1; @@ -1444,7 +1396,7 @@ static int parse_plane(struct plane_arg *plane, const char *p) strcpy(plane->format_str, "XR24"); } - plane->fourcc = format_fourcc(plane->format_str); + plane->fourcc = util_format_fourcc(plane->format_str); if (plane->fourcc == 0) { fprintf(stderr, "unknown format %s\n", plane->format_str); return -EINVAL; @@ -1554,7 +1506,6 @@ int main(int argc, char **argv) int drop_master = 0; int test_vsync = 0; int test_cursor = 0; - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "sti", "tegra", "imx-drm", "rockchip", "atmel-hlcdc" }; char *device = NULL; char *module = NULL; unsigned int i; @@ -1655,29 +1606,9 @@ int main(int argc, char **argv) if (!args) encoders = connectors = crtcs = planes = framebuffers = 1; - if (module) { - dev.fd = drmOpen(module, device); - if (dev.fd < 0) { - fprintf(stderr, "failed to open device '%s'.\n", module); - return 1; - } - } else { - for (i = 0; i < ARRAY_SIZE(modules); i++) { - printf("trying to open device '%s'...", modules[i]); - dev.fd = drmOpen(modules[i], device); - if (dev.fd < 0) { - printf("failed.\n"); - } else { - printf("success.\n"); - break; - } - } - - if (dev.fd < 0) { - fprintf(stderr, "no device found.\n"); - return 1; - } - } + dev.fd = util_open(device, module); + if (dev.fd < 0) + return -1; if (test_vsync && !page_flipping_supported()) { fprintf(stderr, "page flipping not supported by drm.\n"); diff --git a/lib/libdrm/tests/proptest/Makefile.am b/lib/libdrm/tests/proptest/Makefile.am index 0594e02e9..3fde46bec 100644 --- a/lib/libdrm/tests/proptest/Makefile.am +++ b/lib/libdrm/tests/proptest/Makefile.am @@ -1,6 +1,9 @@ +include Makefile.sources + AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir) if HAVE_INSTALL_TESTS @@ -11,7 +14,8 @@ noinst_PROGRAMS = \ proptest endif -proptest_SOURCES = \ - proptest.c +proptest_SOURCES = $(PROPTEST_FILES) + proptest_LDADD = \ - $(top_builddir)/libdrm.la + $(top_builddir)/libdrm.la \ + $(top_builddir)/tests/util/libutil.la diff --git a/lib/libdrm/tests/proptest/Makefile.sources b/lib/libdrm/tests/proptest/Makefile.sources new file mode 100644 index 000000000..446110d68 --- /dev/null +++ b/lib/libdrm/tests/proptest/Makefile.sources @@ -0,0 +1,2 @@ +PROPTEST_FILES := \ + proptest.c diff --git a/lib/libdrm/tests/proptest/proptest.c b/lib/libdrm/tests/proptest/proptest.c index b9296bdb6..4bd086654 100644 --- a/lib/libdrm/tests/proptest/proptest.c +++ b/lib/libdrm/tests/proptest/proptest.c @@ -27,6 +27,7 @@ #include <assert.h> #include <errno.h> +#include <getopt.h> #include <inttypes.h> #include <stdlib.h> #include <stdio.h> @@ -35,7 +36,9 @@ #include "xf86drm.h" #include "xf86drmMode.h" -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#include "util/common.h" +#include "util/kms.h" + static inline int64_t U642I64(uint64_t val) { return (int64_t)*((int64_t *)&val); @@ -44,44 +47,6 @@ static inline int64_t U642I64(uint64_t val) int fd; drmModeResPtr res = NULL; -static const char *connector_type_str(uint32_t type) -{ - switch (type) { - case DRM_MODE_CONNECTOR_Unknown: - return "Unknown"; - case DRM_MODE_CONNECTOR_VGA: - return "VGA"; - case DRM_MODE_CONNECTOR_DVII: - return "DVI-I"; - case DRM_MODE_CONNECTOR_DVID: - return "DVI-D"; - case DRM_MODE_CONNECTOR_DVIA: - return "DVI-A"; - case DRM_MODE_CONNECTOR_Composite: - return "Composite"; - case DRM_MODE_CONNECTOR_SVIDEO: - return "SVIDEO"; - case DRM_MODE_CONNECTOR_LVDS: - return "LVDS"; - case DRM_MODE_CONNECTOR_Component: - return "Component"; - case DRM_MODE_CONNECTOR_9PinDIN: - return "9PinDin"; - case DRM_MODE_CONNECTOR_DisplayPort: - return "DisplayPort"; - case DRM_MODE_CONNECTOR_HDMIA: - return "HDMI-A"; - case DRM_MODE_CONNECTOR_HDMIB: - return "HDMI-B"; - case DRM_MODE_CONNECTOR_TV: - return "TV"; - case DRM_MODE_CONNECTOR_eDP: - return "eDP"; - default: - return "Invalid"; - } -} - /* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */ static void dump_blob(uint32_t blob_id) @@ -225,7 +190,7 @@ static void listConnectorProperties(void) } printf("Connector %u (%s-%u)\n", c->connector_id, - connector_type_str(c->connector_type), + util_lookup_connector_type_name(c->connector_type), c->connector_type_id); listObjectProperties(c->connector_id, @@ -268,28 +233,32 @@ static int setProperty(char *argv[]) uint32_t obj_id, obj_type, prop_id; uint64_t value; - obj_id = atoi(argv[1]); + obj_id = atoi(argv[0]); - if (!strcmp(argv[2], "connector")) { + if (!strcmp(argv[1], "connector")) { obj_type = DRM_MODE_OBJECT_CONNECTOR; - } else if (!strcmp(argv[2], "crtc")) { + } else if (!strcmp(argv[1], "crtc")) { obj_type = DRM_MODE_OBJECT_CRTC; } else { fprintf(stderr, "Invalid object type.\n"); return 1; } - prop_id = atoi(argv[3]); - value = atoll(argv[4]); + prop_id = atoi(argv[2]); + value = atoll(argv[3]); return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value); } -static void printUsage(void) +static void usage(const char *program) { printf("Usage:\n" -" proptest\n" -" proptest [obj id] [obj type] [prop id] [value]\n" +" %s [options]\n" +" %s [options] [obj id] [obj type] [prop id] [value]\n" +"\n" +"options:\n" +" -D DEVICE use the given device\n" +" -M MODULE use the given driver\n" "\n" "The first form just prints all the existing properties. The second one is\n" "used to set the value of a specified property. The object type can be one of\n" @@ -298,26 +267,37 @@ static void printUsage(void) "\n" "Example:\n" " proptest 7 connector 2 1\n" -"will set property 2 of connector 7 to 1\n"); +"will set property 2 of connector 7 to 1\n", program, program); } int main(int argc, char *argv[]) { - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "msm", "rockchip" }; - unsigned int i, ret = 0; + static const char optstr[] = "D:M:"; + int c, args, ret = 0; + char *device = NULL; + char *module = NULL; + + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 'D': + device = optarg; + break; + + case 'M': + module = optarg; + break; - for (i = 0; i < ARRAY_SIZE(modules); i++){ - fd = drmOpen(modules[i], NULL); - if (fd >= 0) { - printf("Module %s loaded.\n", modules[i]); + default: + usage(argv[0]); break; } } - if (i == ARRAY_SIZE(modules)) { - fprintf(stderr, "Failed to load drm modules.\n"); + args = argc - optind; + + fd = util_open(device, module); + if (fd < 0) return 1; - } res = drmModeGetResources(fd); if (!res) { @@ -327,12 +307,12 @@ int main(int argc, char *argv[]) goto done; } - if (argc < 2) { + if (args < 1) { listAllProperties(); - } else if (argc == 5) { - ret = setProperty(argv); + } else if (args == 4) { + ret = setProperty(&argv[optind]); } else { - printUsage(); + usage(argv[0]); ret = 1; } diff --git a/lib/libdrm/tests/util/Makefile.am b/lib/libdrm/tests/util/Makefile.am new file mode 100644 index 000000000..f8e0b1712 --- /dev/null +++ b/lib/libdrm/tests/util/Makefile.am @@ -0,0 +1,13 @@ +include Makefile.sources + +noinst_LTLIBRARIES = \ + libutil.la + +libutil_la_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir) + +libutil_la_CFLAGS = \ + $(CAIRO_CFLAGS) + +libutil_la_SOURCES = $(UTIL_FILES) diff --git a/lib/libdrm/tests/util/Makefile.in b/lib/libdrm/tests/util/Makefile.in new file mode 100644 index 000000000..0855b1c5b --- /dev/null +++ b/lib/libdrm/tests/util/Makefile.in @@ -0,0 +1,666 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = tests/util +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libutil_la_LIBADD = +am__objects_1 = libutil_la-format.lo libutil_la-kms.lo \ + libutil_la-pattern.lo +am_libutil_la_OBJECTS = $(am__objects_1) +libutil_la_OBJECTS = $(am_libutil_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libutil_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libutil_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libutil_la_SOURCES) +DIST_SOURCES = $(libutil_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.sources \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLOCK_LIB = @CLOCK_LIB@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CUNIT_CFLAGS = @CUNIT_CFLAGS@ +CUNIT_LIBS = @CUNIT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ +LIBUDEV_LIBS = @LIBUDEV_LIBS@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANPAGES_STYLESHEET = @MANPAGES_STYLESHEET@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +XSLTPROC = @XSLTPROC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +kernel_source = @kernel_source@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +UTIL_FILES := \ + common.h \ + format.c \ + format.h \ + kms.c \ + kms.h \ + pattern.c \ + pattern.h + +noinst_LTLIBRARIES = \ + libutil.la + +libutil_la_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir) + +libutil_la_CFLAGS = \ + $(CAIRO_CFLAGS) + +libutil_la_SOURCES = $(UTIL_FILES) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/util/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/util/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/Makefile.sources $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libutil.la: $(libutil_la_OBJECTS) $(libutil_la_DEPENDENCIES) $(EXTRA_libutil_la_DEPENDENCIES) + $(AM_V_CCLD)$(libutil_la_LINK) $(libutil_la_OBJECTS) $(libutil_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-format.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-kms.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-pattern.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libutil_la-format.lo: format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libutil_la_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-format.lo -MD -MP -MF $(DEPDIR)/libutil_la-format.Tpo -c -o libutil_la-format.lo `test -f 'format.c' || echo '$(srcdir)/'`format.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-format.Tpo $(DEPDIR)/libutil_la-format.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='format.c' object='libutil_la-format.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libutil_la_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-format.lo `test -f 'format.c' || echo '$(srcdir)/'`format.c + +libutil_la-kms.lo: kms.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libutil_la_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-kms.lo -MD -MP -MF $(DEPDIR)/libutil_la-kms.Tpo -c -o libutil_la-kms.lo `test -f 'kms.c' || echo '$(srcdir)/'`kms.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-kms.Tpo $(DEPDIR)/libutil_la-kms.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kms.c' object='libutil_la-kms.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libutil_la_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-kms.lo `test -f 'kms.c' || echo '$(srcdir)/'`kms.c + +libutil_la-pattern.lo: pattern.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libutil_la_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-pattern.lo -MD -MP -MF $(DEPDIR)/libutil_la-pattern.Tpo -c -o libutil_la-pattern.lo `test -f 'pattern.c' || echo '$(srcdir)/'`pattern.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-pattern.Tpo $(DEPDIR)/libutil_la-pattern.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pattern.c' object='libutil_la-pattern.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libutil_la_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-pattern.lo `test -f 'pattern.c' || echo '$(srcdir)/'`pattern.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/libdrm/tests/util/Makefile.sources b/lib/libdrm/tests/util/Makefile.sources new file mode 100644 index 000000000..e5f851136 --- /dev/null +++ b/lib/libdrm/tests/util/Makefile.sources @@ -0,0 +1,8 @@ +UTIL_FILES := \ + common.h \ + format.c \ + format.h \ + kms.c \ + kms.h \ + pattern.c \ + pattern.h diff --git a/lib/libdrm/tests/util/common.h b/lib/libdrm/tests/util/common.h new file mode 100644 index 000000000..5d572c2dd --- /dev/null +++ b/lib/libdrm/tests/util/common.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_COMMON_H +#define UTIL_COMMON_H + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#endif /* UTIL_COMMON_H */ diff --git a/lib/libdrm/tests/util/format.c b/lib/libdrm/tests/util/format.c new file mode 100644 index 000000000..043cfe7f1 --- /dev/null +++ b/lib/libdrm/tests/util/format.c @@ -0,0 +1,120 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <drm_fourcc.h> + +#include "common.h" +#include "format.h" + +#define MAKE_RGB_INFO(rl, ro, gl, go, bl, bo, al, ao) \ + .rgb = { { (rl), (ro) }, { (gl), (go) }, { (bl), (bo) }, { (al), (ao) } } + +#define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \ + .yuv = { (order), (xsub), (ysub), (chroma_stride) } + +static const struct util_format_info format_info[] = { + /* YUV packed */ + { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) }, + { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) }, + { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) }, + { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) }, + /* YUV semi-planar */ + { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) }, + { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) }, + { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) }, + { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) }, + /* YUV planar */ + { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) }, + { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, + /* RGB16 */ + { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, + { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) }, + { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) }, + { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) }, + { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) }, + { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) }, + { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) }, + { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) }, + { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) }, + { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) }, + { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) }, + { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) }, + { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) }, + { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) }, + { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) }, + { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) }, + { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) }, + { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) }, + /* RGB24 */ + { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, + { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, + /* RGB32 */ + { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) }, + { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, + { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) }, + { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, + { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) }, + { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) }, + { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, + { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) }, + { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) }, + { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) }, + { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) }, + { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) }, + { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) }, + { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) }, + { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) }, + { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) }, +}; + +uint32_t util_format_fourcc(const char *name) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format_info); i++) + if (!strcmp(format_info[i].name, name)) + return format_info[i].format; + + return 0; +} + +const struct util_format_info *util_format_info_find(uint32_t format) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format_info); i++) + if (format_info[i].format == format) + return &format_info[i]; + + return NULL; +} diff --git a/lib/libdrm/tests/util/format.h b/lib/libdrm/tests/util/format.h new file mode 100644 index 000000000..2ce1c021f --- /dev/null +++ b/lib/libdrm/tests/util/format.h @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_FORMAT_H +#define UTIL_FORMAT_H + +struct util_color_component { + unsigned int length; + unsigned int offset; +}; + +struct util_rgb_info { + struct util_color_component red; + struct util_color_component green; + struct util_color_component blue; + struct util_color_component alpha; +}; + +enum util_yuv_order { + YUV_YCbCr = 1, + YUV_YCrCb = 2, + YUV_YC = 4, + YUV_CY = 8, +}; + +struct util_yuv_info { + enum util_yuv_order order; + unsigned int xsub; + unsigned int ysub; + unsigned int chroma_stride; +}; + +struct util_format_info { + uint32_t format; + const char *name; + const struct util_rgb_info rgb; + const struct util_yuv_info yuv; +}; + +uint32_t util_format_fourcc(const char *name); +const struct util_format_info *util_format_info_find(uint32_t format); + +#endif /* UTIL_FORMAT_H */ diff --git a/lib/libdrm/tests/util/kms.c b/lib/libdrm/tests/util/kms.c new file mode 100644 index 000000000..ce8aaabf4 --- /dev/null +++ b/lib/libdrm/tests/util/kms.c @@ -0,0 +1,179 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * This fairly simple test program dumps output in a similar format to the + * "xrandr" tool everyone knows & loves. It's necessarily slightly different + * since the kernel separates outputs into encoder and connector structures, + * each with their own unique ID. The program also allows test testing of the + * memory management and mode setting APIs by allowing the user to specify a + * connector and mode to use for mode setting. If all works as expected, a + * blue background should be painted on the monitor attached to the specified + * connector after the selected mode is set. + * + * TODO: use cairo to write the mode info on the selected output once + * the mode has been programmed, along with possible test patterns. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "xf86drm.h" +#include "xf86drmMode.h" + +#include "common.h" + +struct type_name { + unsigned int type; + const char *name; +}; + +static const char *util_lookup_type_name(unsigned int type, + const struct type_name *table, + unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + if (table[i].type == type) + return table[i].name; + + return NULL; +} + +static const struct type_name encoder_type_names[] = { + { DRM_MODE_ENCODER_NONE, "none" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, + { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, + { DRM_MODE_ENCODER_DSI, "DSI" }, + { DRM_MODE_ENCODER_DPMST, "DPMST" }, +}; + +const char *util_lookup_encoder_type_name(unsigned int type) +{ + return util_lookup_type_name(type, encoder_type_names, + ARRAY_SIZE(encoder_type_names)); +} + +static const struct type_name connector_status_names[] = { + { DRM_MODE_CONNECTED, "connected" }, + { DRM_MODE_DISCONNECTED, "disconnected" }, + { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, +}; + +const char *util_lookup_connector_status_name(unsigned int status) +{ + return util_lookup_type_name(status, connector_status_names, + ARRAY_SIZE(connector_status_names)); +} + +static const struct type_name connector_type_names[] = { + { DRM_MODE_CONNECTOR_Unknown, "unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, + { DRM_MODE_CONNECTOR_TV, "TV" }, + { DRM_MODE_CONNECTOR_eDP, "eDP" }, + { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, + { DRM_MODE_CONNECTOR_DSI, "DSI" }, +}; + +const char *util_lookup_connector_type_name(unsigned int type) +{ + return util_lookup_type_name(type, connector_type_names, + ARRAY_SIZE(connector_type_names)); +} + +static const char * const modules[] = { + "i915", + "radeon", + "nouveau", + "vmwgfx", + "omapdrm", + "exynos", + "tilcdc", + "msm", + "sti", + "tegra", + "imx-drm", + "rockchip", + "atmel-hlcdc", + "fsl-dcu-drm", + "vc4", +}; + +int util_open(const char *device, const char *module) +{ + int fd; + + if (module) { + fd = drmOpen(module, device); + if (fd < 0) { + fprintf(stderr, "failed to open device '%s': %s\n", + module, strerror(errno)); + return -errno; + } + } else { + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(modules); i++) { + printf("trying to open device '%s'...", modules[i]); + + fd = drmOpen(modules[i], device); + if (fd < 0) { + printf("failed\n"); + } else { + printf("done\n"); + break; + } + } + + if (fd < 0) { + fprintf(stderr, "no device found\n"); + return -ENODEV; + } + } + + return fd; +} diff --git a/lib/libdrm/tests/util/kms.h b/lib/libdrm/tests/util/kms.h new file mode 100644 index 000000000..dde2ed2c5 --- /dev/null +++ b/lib/libdrm/tests/util/kms.h @@ -0,0 +1,35 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_KMS_H +#define UTIL_KMS_H + +const char *util_lookup_encoder_type_name(unsigned int type); +const char *util_lookup_connector_status_name(unsigned int type); +const char *util_lookup_connector_type_name(unsigned int type); + +int util_open(const char *device, const char *module); + +#endif /* UTIL_KMS_H */ diff --git a/lib/libdrm/tests/util/pattern.c b/lib/libdrm/tests/util/pattern.c new file mode 100644 index 000000000..00b08a8cb --- /dev/null +++ b/lib/libdrm/tests/util/pattern.c @@ -0,0 +1,870 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <drm_fourcc.h> + +#ifdef HAVE_CAIRO +#include <cairo.h> +#include <math.h> +#endif + +#include "format.h" +#include "pattern.h" + +struct color_rgb24 { + unsigned int value:24; +} __attribute__((__packed__)); + +struct color_yuv { + unsigned char y; + unsigned char u; + unsigned char v; +}; + +#define MAKE_YUV_601_Y(r, g, b) \ + ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) +#define MAKE_YUV_601_U(r, g, b) \ + (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) +#define MAKE_YUV_601_V(r, g, b) \ + (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) + +#define MAKE_YUV_601(r, g, b) \ + { .y = MAKE_YUV_601_Y(r, g, b), \ + .u = MAKE_YUV_601_U(r, g, b), \ + .v = MAKE_YUV_601_V(r, g, b) } + +#define MAKE_RGBA(rgb, r, g, b, a) \ + ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \ + (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \ + (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \ + (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset)) + +#define MAKE_RGB24(rgb, r, g, b) \ + { .value = MAKE_RGBA(rgb, r, g, b, 0) } + +static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv, + unsigned char *y_mem, unsigned char *u_mem, + unsigned char *v_mem, unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct color_yuv colors_top[] = { + MAKE_YUV_601(191, 192, 192), /* grey */ + MAKE_YUV_601(192, 192, 0), /* yellow */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(0, 192, 0), /* green */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(192, 0, 0), /* red */ + MAKE_YUV_601(0, 0, 192), /* blue */ + }; + const struct color_yuv colors_middle[] = { + MAKE_YUV_601(0, 0, 192), /* blue */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 192, 192), /* grey */ + }; + const struct color_yuv colors_bottom[] = { + MAKE_YUV_601(0, 33, 76), /* in-phase */ + MAKE_YUV_601(255, 255, 255), /* super white */ + MAKE_YUV_601(50, 0, 106), /* quadrature */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(9, 9, 9), /* 3.5% */ + MAKE_YUV_601(19, 19, 19), /* 7.5% */ + MAKE_YUV_601(29, 29, 29), /* 11.5% */ + MAKE_YUV_601(19, 19, 19), /* black */ + }; + unsigned int cs = yuv->chroma_stride; + unsigned int xsub = yuv->xsub; + unsigned int ysub = yuv->ysub; + unsigned int x; + unsigned int y; + + /* Luma */ + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[x] = colors_top[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[x] = colors_middle[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; + for (; x < width * 6 / 7; ++x) + y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4].y; + for (; x < width; ++x) + y_mem[x] = colors_bottom[7].y; + y_mem += stride; + } + + /* Chroma */ + for (y = 0; y < height / ysub * 6 / 9; ++y) { + for (x = 0; x < width; x += xsub) { + u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; + v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; + } + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } + + for (; y < height / ysub * 7 / 9; ++y) { + for (x = 0; x < width; x += xsub) { + u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; + v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; + } + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } + + for (; y < height / ysub; ++y) { + for (x = 0; x < width * 5 / 7; x += xsub) { + u_mem[x*cs/xsub] = + colors_bottom[x * 4 / (width * 5 / 7)].u; + v_mem[x*cs/xsub] = + colors_bottom[x * 4 / (width * 5 / 7)].v; + } + for (; x < width * 6 / 7; x += xsub) { + u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].u; + v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].v; + } + for (; x < width; x += xsub) { + u_mem[x*cs/xsub] = colors_bottom[7].u; + v_mem[x*cs/xsub] = colors_bottom[7].v; + } + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } +} + +static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct color_yuv colors_top[] = { + MAKE_YUV_601(191, 192, 192), /* grey */ + MAKE_YUV_601(192, 192, 0), /* yellow */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(0, 192, 0), /* green */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(192, 0, 0), /* red */ + MAKE_YUV_601(0, 0, 192), /* blue */ + }; + const struct color_yuv colors_middle[] = { + MAKE_YUV_601(0, 0, 192), /* blue */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 0, 192), /* magenta */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(0, 192, 192), /* cyan */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(192, 192, 192), /* grey */ + }; + const struct color_yuv colors_bottom[] = { + MAKE_YUV_601(0, 33, 76), /* in-phase */ + MAKE_YUV_601(255, 255, 255), /* super white */ + MAKE_YUV_601(50, 0, 106), /* quadrature */ + MAKE_YUV_601(19, 19, 19), /* black */ + MAKE_YUV_601(9, 9, 9), /* 3.5% */ + MAKE_YUV_601(19, 19, 19), /* 7.5% */ + MAKE_YUV_601(29, 29, 29), /* 11.5% */ + MAKE_YUV_601(19, 19, 19), /* black */ + }; + unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; + unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; + unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; + unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; + unsigned int x; + unsigned int y; + + /* Luma */ + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[2*x] = colors_top[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + y_mem[2*x] = colors_middle[x * 7 / width].y; + y_mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; + for (; x < width * 6 / 7; ++x) + y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4].y; + for (; x < width; ++x) + y_mem[2*x] = colors_bottom[7].y; + y_mem += stride; + } + + /* Chroma */ + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; x += 2) { + c_mem[2*x+u] = colors_top[x * 7 / width].u; + c_mem[2*x+v] = colors_top[x * 7 / width].v; + } + c_mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; x += 2) { + c_mem[2*x+u] = colors_middle[x * 7 / width].u; + c_mem[2*x+v] = colors_middle[x * 7 / width].v; + } + c_mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; x += 2) { + c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; + c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; + } + for (; x < width * 6 / 7; x += 2) { + c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].u; + c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * + 3 / (width / 7) + 4].v; + } + for (; x < width; x += 2) { + c_mem[2*x+u] = colors_bottom[7].u; + c_mem[2*x+v] = colors_bottom[7].v; + } + c_mem += stride; + } +} + +static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const uint16_t colors_top[] = { + MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ + MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ + MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ + MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ + MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ + MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ + MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ + }; + const uint16_t colors_middle[] = { + MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ + }; + const uint16_t colors_bottom[] = { + MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ + MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ + MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ + MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + }; + unsigned int x; + unsigned int y; + + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint16_t *)mem)[x] = colors_top[x * 7 / width]; + mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint16_t *)mem)[x] = colors_middle[x * 7 / width]; + mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + ((uint16_t *)mem)[x] = + colors_bottom[x * 4 / (width * 5 / 7)]; + for (; x < width * 6 / 7; ++x) + ((uint16_t *)mem)[x] = + colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4]; + for (; x < width; ++x) + ((uint16_t *)mem)[x] = colors_bottom[7]; + mem += stride; + } +} + +static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct color_rgb24 colors_top[] = { + MAKE_RGB24(rgb, 192, 192, 192), /* grey */ + MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ + MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ + MAKE_RGB24(rgb, 0, 192, 0), /* green */ + MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ + MAKE_RGB24(rgb, 192, 0, 0), /* red */ + MAKE_RGB24(rgb, 0, 0, 192), /* blue */ + }; + const struct color_rgb24 colors_middle[] = { + MAKE_RGB24(rgb, 0, 0, 192), /* blue */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 192, 192, 192), /* grey */ + }; + const struct color_rgb24 colors_bottom[] = { + MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ + MAKE_RGB24(rgb, 255, 255, 255), /* super white */ + MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ + MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ + MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ + MAKE_RGB24(rgb, 19, 19, 19), /* black */ + }; + unsigned int x; + unsigned int y; + + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_top[x * 7 / width]; + mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_middle[x * 7 / width]; + mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_bottom[x * 4 / (width * 5 / 7)]; + for (; x < width * 6 / 7; ++x) + ((struct color_rgb24 *)mem)[x] = + colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4]; + for (; x < width; ++x) + ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; + mem += stride; + } +} + +static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const uint32_t colors_top[] = { + MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ + MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ + MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ + MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ + MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ + MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ + MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ + }; + const uint32_t colors_middle[] = { + MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ + MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ + MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ + }; + const uint32_t colors_bottom[] = { + MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ + MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ + MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ + MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ + MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ + }; + unsigned int x; + unsigned int y; + + for (y = 0; y < height * 6 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint32_t *)mem)[x] = colors_top[x * 7 / width]; + mem += stride; + } + + for (; y < height * 7 / 9; ++y) { + for (x = 0; x < width; ++x) + ((uint32_t *)mem)[x] = colors_middle[x * 7 / width]; + mem += stride; + } + + for (; y < height; ++y) { + for (x = 0; x < width * 5 / 7; ++x) + ((uint32_t *)mem)[x] = + colors_bottom[x * 4 / (width * 5 / 7)]; + for (; x < width * 6 / 7; ++x) + ((uint32_t *)mem)[x] = + colors_bottom[(x - width * 5 / 7) * 3 + / (width / 7) + 4]; + for (; x < width; ++x) + ((uint32_t *)mem)[x] = colors_bottom[7]; + mem += stride; + } +} + +static void fill_smpte(const struct util_format_info *info, void *planes[3], + unsigned int width, unsigned int height, + unsigned int stride) +{ + unsigned char *u, *v; + + switch (info->format) { + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + return fill_smpte_yuv_packed(&info->yuv, planes[0], width, + height, stride); + + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; + v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; + return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, + width, height, stride); + + case DRM_FORMAT_YUV420: + return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], + planes[2], width, height, stride); + + case DRM_FORMAT_YVU420: + return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], + planes[1], width, height, stride); + + 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_RGB565: + case DRM_FORMAT_BGR565: + 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: + return fill_smpte_rgb16(&info->rgb, planes[0], + width, height, stride); + + case DRM_FORMAT_BGR888: + case DRM_FORMAT_RGB888: + return fill_smpte_rgb24(&info->rgb, planes[0], + width, height, stride); + 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: + return fill_smpte_rgb32(&info->rgb, planes[0], + width, height, stride); + } +} + +/* swap these for big endian.. */ +#define RED 2 +#define GREEN 1 +#define BLUE 0 + +static void make_pwetty(void *data, unsigned int width, unsigned int height, + unsigned int stride, uint32_t format) +{ +#ifdef HAVE_CAIRO + cairo_surface_t *surface; + cairo_t *cr; + int x, y; + cairo_format_t cairo_format; + + /* we can ignore the order of R,G,B channels */ + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + cairo_format = CAIRO_FORMAT_ARGB32; + break; + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + cairo_format = CAIRO_FORMAT_RGB16_565; + break; + default: + return; + } + + surface = cairo_image_surface_create_for_data(data, + cairo_format, + width, height, + stride); + cr = cairo_create(surface); + cairo_surface_destroy(surface); + + cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); + for (x = 0; x < width; x += 250) + for (y = 0; y < height; y += 250) { + char buf[64]; + + cairo_move_to(cr, x, y - 20); + cairo_line_to(cr, x, y + 20); + cairo_move_to(cr, x - 20, y); + cairo_line_to(cr, x + 20, y); + cairo_new_sub_path(cr); + cairo_arc(cr, x, y, 10, 0, M_PI * 2); + cairo_set_line_width(cr, 4); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_set_line_width(cr, 2); + cairo_stroke(cr); + + snprintf(buf, sizeof buf, "%d, %d", x, y); + cairo_move_to(cr, x + 20, y + 20); + cairo_text_path(cr, buf); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_fill(cr); + } + + cairo_destroy(cr); +#endif +} + +static void fill_tiles_yuv_planar(const struct util_format_info *info, + unsigned char *y_mem, unsigned char *u_mem, + unsigned char *v_mem, unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct util_yuv_info *yuv = &info->yuv; + unsigned int cs = yuv->chroma_stride; + unsigned int xsub = yuv->xsub; + unsigned int ysub = yuv->ysub; + unsigned int x; + unsigned int y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + struct color_yuv color = + MAKE_YUV_601((rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff); + + y_mem[x] = color.y; + u_mem[x/xsub*cs] = color.u; + v_mem[x/xsub*cs] = color.v; + } + + y_mem += stride; + if ((y + 1) % ysub == 0) { + u_mem += stride * cs / xsub; + v_mem += stride * cs / xsub; + } + } +} + +static void fill_tiles_yuv_packed(const struct util_format_info *info, + void *mem, unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct util_yuv_info *yuv = &info->yuv; + unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; + unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; + unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; + unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; + unsigned int x; + unsigned int y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; x += 2) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + struct color_yuv color = + MAKE_YUV_601((rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff); + + y_mem[2*x] = color.y; + c_mem[2*x+u] = color.u; + y_mem[2*x+2] = color.y; + c_mem[2*x+v] = color.v; + } + + y_mem += stride; + c_mem += stride; + } +} + +static void fill_tiles_rgb16(const struct util_format_info *info, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct util_rgb_info *rgb = &info->rgb; + void *mem_base = mem; + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + uint16_t color = + MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff, + 255); + + ((uint16_t *)mem)[x] = color; + } + mem += stride; + } + + make_pwetty(mem_base, width, height, stride, info->format); +} + +static void fill_tiles_rgb24(const struct util_format_info *info, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct util_rgb_info *rgb = &info->rgb; + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + struct color_rgb24 color = + MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff); + + ((struct color_rgb24 *)mem)[x] = color; + } + mem += stride; + } +} + +static void fill_tiles_rgb32(const struct util_format_info *info, void *mem, + unsigned int width, unsigned int height, + unsigned int stride) +{ + const struct util_rgb_info *rgb = &info->rgb; + void *mem_base = mem; + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + div_t d = div(x+y, width); + uint32_t rgb32 = 0x00130502 * (d.quot >> 6) + + 0x000a1120 * (d.rem >> 6); + uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; + uint32_t color = + MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, + (rgb32 >> 8) & 0xff, rgb32 & 0xff, + alpha); + + ((uint32_t *)mem)[x] = color; + } + mem += stride; + } + + make_pwetty(mem_base, width, height, stride, info->format); +} + +static void fill_tiles(const struct util_format_info *info, void *planes[3], + unsigned int width, unsigned int height, + unsigned int stride) +{ + unsigned char *u, *v; + + switch (info->format) { + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + return fill_tiles_yuv_packed(info, planes[0], + width, height, stride); + + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; + v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; + return fill_tiles_yuv_planar(info, planes[0], u, v, + width, height, stride); + + case DRM_FORMAT_YUV420: + return fill_tiles_yuv_planar(info, planes[0], planes[1], + planes[2], width, height, stride); + + case DRM_FORMAT_YVU420: + return fill_tiles_yuv_planar(info, planes[0], planes[2], + planes[1], width, height, stride); + + 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_RGB565: + case DRM_FORMAT_BGR565: + 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: + return fill_tiles_rgb16(info, planes[0], + width, height, stride); + + case DRM_FORMAT_BGR888: + case DRM_FORMAT_RGB888: + return fill_tiles_rgb24(info, planes[0], + width, height, stride); + 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: + return fill_tiles_rgb32(info, planes[0], + width, height, stride); + } +} + +static void fill_plain(const struct util_format_info *info, void *planes[3], + unsigned int width, unsigned int height, + unsigned int stride) +{ + memset(planes[0], 0x77, stride * height); +} + +/* + * util_fill_pattern - Fill a buffer with a test pattern + * @format: Pixel format + * @pattern: Test pattern + * @planes: Array of buffers + * @width: Width in pixels + * @height: Height in pixels + * @stride: Line stride (pitch) in bytes + * + * Fill the buffers with the test pattern specified by the pattern parameter. + * Supported formats vary depending on the selected pattern. + */ +void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, + void *planes[3], unsigned int width, + unsigned int height, unsigned int stride) +{ + const struct util_format_info *info; + + info = util_format_info_find(format); + if (info == NULL) + return; + + switch (pattern) { + case UTIL_PATTERN_TILES: + return fill_tiles(info, planes, width, height, stride); + + case UTIL_PATTERN_SMPTE: + return fill_smpte(info, planes, width, height, stride); + + case UTIL_PATTERN_PLAIN: + return fill_plain(info, planes, width, height, stride); + + default: + printf("Error: unsupported test pattern %u.\n", pattern); + break; + } +} diff --git a/lib/libdrm/tests/util/pattern.h b/lib/libdrm/tests/util/pattern.h new file mode 100644 index 000000000..d5c4260cc --- /dev/null +++ b/lib/libdrm/tests/util/pattern.h @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_PATTERN_H +#define UTIL_PATTERN_H + +enum util_fill_pattern { + UTIL_PATTERN_TILES, + UTIL_PATTERN_PLAIN, + UTIL_PATTERN_SMPTE, +}; + +void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, + void *planes[3], unsigned int width, + unsigned int height, unsigned int stride); + +#endif /* UTIL_PATTERN_H */ diff --git a/lib/libdrm/tests/vbltest/Makefile.am b/lib/libdrm/tests/vbltest/Makefile.am index 4d87887a5..276afad55 100644 --- a/lib/libdrm/tests/vbltest/Makefile.am +++ b/lib/libdrm/tests/vbltest/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tests \ -I$(top_srcdir) if HAVE_INSTALL_TESTS @@ -14,4 +15,5 @@ endif vbltest_SOURCES = \ vbltest.c vbltest_LDADD = \ - $(top_builddir)/libdrm.la + $(top_builddir)/libdrm.la \ + $(top_builddir)/tests/util/libutil.la diff --git a/lib/libdrm/tests/vbltest/vbltest.c b/lib/libdrm/tests/vbltest/vbltest.c index e27f45c1b..3f6b803a7 100644 --- a/lib/libdrm/tests/vbltest/vbltest.c +++ b/lib/libdrm/tests/vbltest/vbltest.c @@ -1,5 +1,5 @@ /* - * DRM based mode setting test program + * DRM based vblank test program * Copyright 2008 Tungsten Graphics * Jakob Bornecrantz <jakob@tungstengraphics.com> * Copyright 2008 Intel Corporation @@ -24,19 +24,6 @@ * IN THE SOFTWARE. */ -/* - * This fairly simple test program dumps output in a similar format to the - * "xrandr" tool everyone knows & loves. It's necessarily slightly different - * since the kernel separates outputs into encoder and connector structures, - * each with their own unique ID. The program also allows test testing of the - * memory management and mode setting APIs by allowing the user to specify a - * connector and mode to use for mode setting. If all works as expected, a - * blue background should be painted on the monitor attached to the specified - * connector after the selected mode is set. - * - * TODO: use cairo to write the mode info on the selected output once - * the mode has been programmed, along with possible test patterns. - */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -48,17 +35,21 @@ #include <unistd.h> #include <string.h> #include <errno.h> -#include <sys/poll.h> +#include <poll.h> #include <sys/time.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include "xf86drm.h" #include "xf86drmMode.h" -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#include "util/common.h" +#include "util/kms.h" extern char *optarg; extern int optind, opterr, optopt; -static char optstr[] = "s"; +static char optstr[] = "D:M:s"; int secondary = 0; @@ -97,16 +88,19 @@ static void vblank_handler(int fd, unsigned int frame, unsigned int sec, static void usage(char *name) { - fprintf(stderr, "usage: %s [-s]\n", name); - fprintf(stderr, "\t-s\tuse secondary pipe\n"); + fprintf(stderr, "usage: %s [-DMs]\n", name); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -D DEVICE open the given device\n"); + fprintf(stderr, " -M MODULE open the given module\n"); + fprintf(stderr, " -s use secondary pipe\n"); exit(0); } int main(int argc, char **argv) { - unsigned i; + const char *device = NULL, *module = NULL; int c, fd, ret; - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm", "tegra", "imx-drm" , "rockchip" }; drmVBlank vbl; drmEventContext evctx; struct vbl_info handler_info; @@ -114,6 +108,12 @@ int main(int argc, char **argv) opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { + case 'D': + device = optarg; + break; + case 'M': + module = optarg; + break; case 's': secondary = 1; break; @@ -123,21 +123,9 @@ int main(int argc, char **argv) } } - for (i = 0; i < ARRAY_SIZE(modules); i++) { - printf("trying to load module %s...", modules[i]); - fd = drmOpen(modules[i], NULL); - if (fd < 0) { - printf("failed.\n"); - } else { - printf("success.\n"); - break; - } - } - - if (i == ARRAY_SIZE(modules)) { - fprintf(stderr, "failed to load any modules, aborting.\n"); - return -1; - } + fd = util_open(device, module); + if (fd < 0) + return 1; /* Get current count first */ vbl.request.type = DRM_VBLANK_RELATIVE; diff --git a/lib/libdrm/util_math.h b/lib/libdrm/util_math.h index 3bc5f644e..02b15a8e5 100644 --- a/lib/libdrm/util_math.h +++ b/lib/libdrm/util_math.h @@ -26,6 +26,7 @@ #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) +#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) #define __align_mask(value, mask) (((value) + (mask)) & ~(mask)) #define ALIGN(value, alignment) __align_mask(value, (typeof(value))((alignment) - 1)) diff --git a/lib/libdrm/vc4/Makefile.am b/lib/libdrm/vc4/Makefile.am new file mode 100644 index 000000000..7e486b4d8 --- /dev/null +++ b/lib/libdrm/vc4/Makefile.am @@ -0,0 +1,34 @@ +# Copyright © 2016 Broadcom +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +include Makefile.sources + +AM_CFLAGS = \ + $(WARN_CFLAGS) \ + -I$(top_srcdir) \ + $(PTHREADSTUBS_CFLAGS) \ + $(VALGRIND_CFLAGS) \ + -I$(top_srcdir)/include/drm + +libdrm_vc4includedir = ${includedir}/libdrm +libdrm_vc4include_HEADERS = $(LIBDRM_VC4_H_FILES) + +pkgconfig_DATA = libdrm_vc4.pc diff --git a/lib/libdrm/vc4/Makefile.in b/lib/libdrm/vc4/Makefile.in new file mode 100644 index 000000000..0c1238e77 --- /dev/null +++ b/lib/libdrm/vc4/Makefile.in @@ -0,0 +1,657 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright © 2016 Broadcom +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = vc4 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(libdrm_vc4include_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = libdrm_vc4.pc +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(libdrm_vc4includedir)" +DATA = $(pkgconfig_DATA) +HEADERS = $(libdrm_vc4include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.sources \ + $(srcdir)/libdrm_vc4.pc.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLOCK_LIB = @CLOCK_LIB@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CUNIT_CFLAGS = @CUNIT_CFLAGS@ +CUNIT_LIBS = @CUNIT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ +LIBUDEV_LIBS = @LIBUDEV_LIBS@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANPAGES_STYLESHEET = @MANPAGES_STYLESHEET@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +XSLTPROC = @XSLTPROC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +kernel_source = @kernel_source@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +LIBDRM_VC4_H_FILES := \ + vc4_packet.h \ + vc4_qpu_defines.h + +AM_CFLAGS = \ + $(WARN_CFLAGS) \ + -I$(top_srcdir) \ + $(PTHREADSTUBS_CFLAGS) \ + $(VALGRIND_CFLAGS) \ + -I$(top_srcdir)/include/drm + +libdrm_vc4includedir = ${includedir}/libdrm +libdrm_vc4include_HEADERS = $(LIBDRM_VC4_H_FILES) +pkgconfig_DATA = libdrm_vc4.pc +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign vc4/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign vc4/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/Makefile.sources $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +libdrm_vc4.pc: $(top_builddir)/config.status $(srcdir)/libdrm_vc4.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-libdrm_vc4includeHEADERS: $(libdrm_vc4include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libdrm_vc4include_HEADERS)'; test -n "$(libdrm_vc4includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdrm_vc4includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdrm_vc4includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libdrm_vc4includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libdrm_vc4includedir)" || exit $$?; \ + done + +uninstall-libdrm_vc4includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libdrm_vc4include_HEADERS)'; test -n "$(libdrm_vc4includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libdrm_vc4includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libdrm_vc4includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-libdrm_vc4includeHEADERS \ + install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libdrm_vc4includeHEADERS \ + uninstall-pkgconfigDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libdrm_vc4includeHEADERS \ + install-man install-pdf install-pdf-am install-pkgconfigDATA \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libdrm_vc4includeHEADERS \ + uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/libdrm/vc4/Makefile.sources b/lib/libdrm/vc4/Makefile.sources new file mode 100644 index 000000000..8bf97ff1e --- /dev/null +++ b/lib/libdrm/vc4/Makefile.sources @@ -0,0 +1,3 @@ +LIBDRM_VC4_H_FILES := \ + vc4_packet.h \ + vc4_qpu_defines.h diff --git a/lib/libdrm/vc4/libdrm_vc4.pc.in b/lib/libdrm/vc4/libdrm_vc4.pc.in new file mode 100644 index 000000000..a92678ed6 --- /dev/null +++ b/lib/libdrm/vc4/libdrm_vc4.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdrm_vc4 +Description: Userspace interface to vc4 kernel DRM services +Version: @PACKAGE_VERSION@ +Requires.private: libdrm diff --git a/lib/libdrm/vc4/vc4_packet.h b/lib/libdrm/vc4/vc4_packet.h new file mode 100644 index 000000000..e18e0bdf6 --- /dev/null +++ b/lib/libdrm/vc4/vc4_packet.h @@ -0,0 +1,397 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef VC4_PACKET_H +#define VC4_PACKET_H + +enum vc4_packet { + VC4_PACKET_HALT = 0, + VC4_PACKET_NOP = 1, + + VC4_PACKET_FLUSH = 4, + VC4_PACKET_FLUSH_ALL = 5, + VC4_PACKET_START_TILE_BINNING = 6, + VC4_PACKET_INCREMENT_SEMAPHORE = 7, + VC4_PACKET_WAIT_ON_SEMAPHORE = 8, + + VC4_PACKET_BRANCH = 16, + VC4_PACKET_BRANCH_TO_SUB_LIST = 17, + VC4_PACKET_RETURN_FROM_SUB_LIST = 18, + + VC4_PACKET_STORE_MS_TILE_BUFFER = 24, + VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF = 25, + VC4_PACKET_STORE_FULL_RES_TILE_BUFFER = 26, + VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER = 27, + VC4_PACKET_STORE_TILE_BUFFER_GENERAL = 28, + VC4_PACKET_LOAD_TILE_BUFFER_GENERAL = 29, + + VC4_PACKET_GL_INDEXED_PRIMITIVE = 32, + VC4_PACKET_GL_ARRAY_PRIMITIVE = 33, + + VC4_PACKET_COMPRESSED_PRIMITIVE = 48, + VC4_PACKET_CLIPPED_COMPRESSED_PRIMITIVE = 49, + + VC4_PACKET_PRIMITIVE_LIST_FORMAT = 56, + + VC4_PACKET_GL_SHADER_STATE = 64, + VC4_PACKET_NV_SHADER_STATE = 65, + VC4_PACKET_VG_SHADER_STATE = 66, + + VC4_PACKET_CONFIGURATION_BITS = 96, + VC4_PACKET_FLAT_SHADE_FLAGS = 97, + VC4_PACKET_POINT_SIZE = 98, + VC4_PACKET_LINE_WIDTH = 99, + VC4_PACKET_RHT_X_BOUNDARY = 100, + VC4_PACKET_DEPTH_OFFSET = 101, + VC4_PACKET_CLIP_WINDOW = 102, + VC4_PACKET_VIEWPORT_OFFSET = 103, + VC4_PACKET_Z_CLIPPING = 104, + VC4_PACKET_CLIPPER_XY_SCALING = 105, + VC4_PACKET_CLIPPER_Z_SCALING = 106, + + VC4_PACKET_TILE_BINNING_MODE_CONFIG = 112, + VC4_PACKET_TILE_RENDERING_MODE_CONFIG = 113, + VC4_PACKET_CLEAR_COLORS = 114, + VC4_PACKET_TILE_COORDINATES = 115, + + /* Not an actual hardware packet -- this is what we use to put + * references to GEM bos in the command stream, since we need the u32 + * int the actual address packet in order to store the offset from the + * start of the BO. + */ + VC4_PACKET_GEM_HANDLES = 254, +} __attribute__ ((__packed__)); + +#define VC4_PACKET_HALT_SIZE 1 +#define VC4_PACKET_NOP_SIZE 1 +#define VC4_PACKET_FLUSH_SIZE 1 +#define VC4_PACKET_FLUSH_ALL_SIZE 1 +#define VC4_PACKET_START_TILE_BINNING_SIZE 1 +#define VC4_PACKET_INCREMENT_SEMAPHORE_SIZE 1 +#define VC4_PACKET_WAIT_ON_SEMAPHORE_SIZE 1 +#define VC4_PACKET_BRANCH_SIZE 5 +#define VC4_PACKET_BRANCH_TO_SUB_LIST_SIZE 5 +#define VC4_PACKET_RETURN_FROM_SUB_LIST_SIZE 1 +#define VC4_PACKET_STORE_MS_TILE_BUFFER_SIZE 1 +#define VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF_SIZE 1 +#define VC4_PACKET_STORE_FULL_RES_TILE_BUFFER_SIZE 5 +#define VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER_SIZE 5 +#define VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE 7 +#define VC4_PACKET_LOAD_TILE_BUFFER_GENERAL_SIZE 7 +#define VC4_PACKET_GL_INDEXED_PRIMITIVE_SIZE 14 +#define VC4_PACKET_GL_ARRAY_PRIMITIVE_SIZE 10 +#define VC4_PACKET_COMPRESSED_PRIMITIVE_SIZE 1 +#define VC4_PACKET_CLIPPED_COMPRESSED_PRIMITIVE_SIZE 1 +#define VC4_PACKET_PRIMITIVE_LIST_FORMAT_SIZE 2 +#define VC4_PACKET_GL_SHADER_STATE_SIZE 5 +#define VC4_PACKET_NV_SHADER_STATE_SIZE 5 +#define VC4_PACKET_VG_SHADER_STATE_SIZE 5 +#define VC4_PACKET_CONFIGURATION_BITS_SIZE 4 +#define VC4_PACKET_FLAT_SHADE_FLAGS_SIZE 5 +#define VC4_PACKET_POINT_SIZE_SIZE 5 +#define VC4_PACKET_LINE_WIDTH_SIZE 5 +#define VC4_PACKET_RHT_X_BOUNDARY_SIZE 3 +#define VC4_PACKET_DEPTH_OFFSET_SIZE 5 +#define VC4_PACKET_CLIP_WINDOW_SIZE 9 +#define VC4_PACKET_VIEWPORT_OFFSET_SIZE 5 +#define VC4_PACKET_Z_CLIPPING_SIZE 9 +#define VC4_PACKET_CLIPPER_XY_SCALING_SIZE 9 +#define VC4_PACKET_CLIPPER_Z_SCALING_SIZE 9 +#define VC4_PACKET_TILE_BINNING_MODE_CONFIG_SIZE 16 +#define VC4_PACKET_TILE_RENDERING_MODE_CONFIG_SIZE 11 +#define VC4_PACKET_CLEAR_COLORS_SIZE 14 +#define VC4_PACKET_TILE_COORDINATES_SIZE 3 +#define VC4_PACKET_GEM_HANDLES_SIZE 9 + +#define VC4_MASK(high, low) (((1 << ((high) - (low) + 1)) - 1) << (low)) +/* Using the GNU statement expression extension */ +#define VC4_SET_FIELD(value, field) \ + ({ \ + uint32_t fieldval = (value) << field ## _SHIFT; \ + assert((fieldval & ~ field ## _MASK) == 0); \ + fieldval & field ## _MASK; \ + }) + +#define VC4_GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) + +/** @{ + * Bits used by packets like VC4_PACKET_STORE_TILE_BUFFER_GENERAL and + * VC4_PACKET_TILE_RENDERING_MODE_CONFIG. +*/ +#define VC4_TILING_FORMAT_LINEAR 0 +#define VC4_TILING_FORMAT_T 1 +#define VC4_TILING_FORMAT_LT 2 +/** @} */ + +/** @{ + * + * low bits of VC4_PACKET_STORE_FULL_RES_TILE_BUFFER and + * VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER. + */ +#define VC4_LOADSTORE_FULL_RES_EOF (1 << 3) +#define VC4_LOADSTORE_FULL_RES_DISABLE_CLEAR_ALL (1 << 2) +#define VC4_LOADSTORE_FULL_RES_DISABLE_ZS (1 << 1) +#define VC4_LOADSTORE_FULL_RES_DISABLE_COLOR (1 << 0) + +/** @{ + * + * byte 2 of VC4_PACKET_STORE_TILE_BUFFER_GENERAL and + * VC4_PACKET_LOAD_TILE_BUFFER_GENERAL (low bits of the address) + */ + +#define VC4_LOADSTORE_TILE_BUFFER_EOF (1 << 3) +#define VC4_LOADSTORE_TILE_BUFFER_DISABLE_FULL_VG_MASK (1 << 2) +#define VC4_LOADSTORE_TILE_BUFFER_DISABLE_FULL_ZS (1 << 1) +#define VC4_LOADSTORE_TILE_BUFFER_DISABLE_FULL_COLOR (1 << 0) + +/** @} */ + +/** @{ + * + * byte 0-1 of VC4_PACKET_STORE_TILE_BUFFER_GENERAL and + * VC4_PACKET_LOAD_TILE_BUFFER_GENERAL + */ +#define VC4_STORE_TILE_BUFFER_DISABLE_VG_MASK_CLEAR (1 << 15) +#define VC4_STORE_TILE_BUFFER_DISABLE_ZS_CLEAR (1 << 14) +#define VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR (1 << 13) +#define VC4_STORE_TILE_BUFFER_DISABLE_SWAP (1 << 12) + +#define VC4_LOADSTORE_TILE_BUFFER_FORMAT_MASK VC4_MASK(9, 8) +#define VC4_LOADSTORE_TILE_BUFFER_FORMAT_SHIFT 8 +#define VC4_LOADSTORE_TILE_BUFFER_RGBA8888 0 +#define VC4_LOADSTORE_TILE_BUFFER_BGR565_DITHER 1 +#define VC4_LOADSTORE_TILE_BUFFER_BGR565 2 +/** @} */ + +/** @{ + * + * byte 0 of VC4_PACKET_STORE_TILE_BUFFER_GENERAL and + * VC4_PACKET_LOAD_TILE_BUFFER_GENERAL + */ +#define VC4_STORE_TILE_BUFFER_MODE_MASK VC4_MASK(7, 6) +#define VC4_STORE_TILE_BUFFER_MODE_SHIFT 6 +#define VC4_STORE_TILE_BUFFER_MODE_SAMPLE0 (0 << 6) +#define VC4_STORE_TILE_BUFFER_MODE_DECIMATE_X4 (1 << 6) +#define VC4_STORE_TILE_BUFFER_MODE_DECIMATE_X16 (2 << 6) + +/** The values of the field are VC4_TILING_FORMAT_* */ +#define VC4_LOADSTORE_TILE_BUFFER_TILING_MASK VC4_MASK(5, 4) +#define VC4_LOADSTORE_TILE_BUFFER_TILING_SHIFT 4 + +#define VC4_LOADSTORE_TILE_BUFFER_BUFFER_MASK VC4_MASK(2, 0) +#define VC4_LOADSTORE_TILE_BUFFER_BUFFER_SHIFT 0 +#define VC4_LOADSTORE_TILE_BUFFER_NONE 0 +#define VC4_LOADSTORE_TILE_BUFFER_COLOR 1 +#define VC4_LOADSTORE_TILE_BUFFER_ZS 2 +#define VC4_LOADSTORE_TILE_BUFFER_Z 3 +#define VC4_LOADSTORE_TILE_BUFFER_VG_MASK 4 +#define VC4_LOADSTORE_TILE_BUFFER_FULL 5 +/** @} */ + +#define VC4_INDEX_BUFFER_U8 (0 << 4) +#define VC4_INDEX_BUFFER_U16 (1 << 4) + +/* This flag is only present in NV shader state. */ +#define VC4_SHADER_FLAG_SHADED_CLIP_COORDS (1 << 3) +#define VC4_SHADER_FLAG_ENABLE_CLIPPING (1 << 2) +#define VC4_SHADER_FLAG_VS_POINT_SIZE (1 << 1) +#define VC4_SHADER_FLAG_FS_SINGLE_THREAD (1 << 0) + +/** @{ byte 2 of config bits. */ +#define VC4_CONFIG_BITS_EARLY_Z_UPDATE (1 << 1) +#define VC4_CONFIG_BITS_EARLY_Z (1 << 0) +/** @} */ + +/** @{ byte 1 of config bits. */ +#define VC4_CONFIG_BITS_Z_UPDATE (1 << 7) +/** same values in this 3-bit field as PIPE_FUNC_* */ +#define VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT 4 +#define VC4_CONFIG_BITS_COVERAGE_READ_LEAVE (1 << 3) + +#define VC4_CONFIG_BITS_COVERAGE_UPDATE_NONZERO (0 << 1) +#define VC4_CONFIG_BITS_COVERAGE_UPDATE_ODD (1 << 1) +#define VC4_CONFIG_BITS_COVERAGE_UPDATE_OR (2 << 1) +#define VC4_CONFIG_BITS_COVERAGE_UPDATE_ZERO (3 << 1) + +#define VC4_CONFIG_BITS_COVERAGE_PIPE_SELECT (1 << 0) +/** @} */ + +/** @{ byte 0 of config bits. */ +#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_NONE (0 << 6) +#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_4X (1 << 6) +#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_16X (2 << 6) +#define VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_MASK (3 << 6) + +#define VC4_CONFIG_BITS_AA_POINTS_AND_LINES (1 << 4) +#define VC4_CONFIG_BITS_ENABLE_DEPTH_OFFSET (1 << 3) +#define VC4_CONFIG_BITS_CW_PRIMITIVES (1 << 2) +#define VC4_CONFIG_BITS_ENABLE_PRIM_BACK (1 << 1) +#define VC4_CONFIG_BITS_ENABLE_PRIM_FRONT (1 << 0) +/** @} */ + +/** @{ bits in the last u8 of VC4_PACKET_TILE_BINNING_MODE_CONFIG */ +#define VC4_BIN_CONFIG_DB_NON_MS (1 << 7) + +#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_MASK VC4_MASK(6, 5) +#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_SHIFT 5 +#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_32 0 +#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_64 1 +#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_128 2 +#define VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_256 3 + +#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK VC4_MASK(4, 3) +#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_SHIFT 3 +#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32 0 +#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_64 1 +#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_128 2 +#define VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_256 3 + +#define VC4_BIN_CONFIG_AUTO_INIT_TSDA (1 << 2) +#define VC4_BIN_CONFIG_TILE_BUFFER_64BIT (1 << 1) +#define VC4_BIN_CONFIG_MS_MODE_4X (1 << 0) +/** @} */ + +/** @{ bits in the last u16 of VC4_PACKET_TILE_RENDERING_MODE_CONFIG */ +#define VC4_RENDER_CONFIG_DB_NON_MS (1 << 12) +#define VC4_RENDER_CONFIG_EARLY_Z_COVERAGE_DISABLE (1 << 11) +#define VC4_RENDER_CONFIG_EARLY_Z_DIRECTION_G (1 << 10) +#define VC4_RENDER_CONFIG_COVERAGE_MODE (1 << 9) +#define VC4_RENDER_CONFIG_ENABLE_VG_MASK (1 << 8) + +/** The values of the field are VC4_TILING_FORMAT_* */ +#define VC4_RENDER_CONFIG_MEMORY_FORMAT_MASK VC4_MASK(7, 6) +#define VC4_RENDER_CONFIG_MEMORY_FORMAT_SHIFT 6 + +#define VC4_RENDER_CONFIG_DECIMATE_MODE_1X (0 << 4) +#define VC4_RENDER_CONFIG_DECIMATE_MODE_4X (1 << 4) +#define VC4_RENDER_CONFIG_DECIMATE_MODE_16X (2 << 4) +#define VC4_RENDER_CONFIG_DECIMATE_MODE_MASK (3 << 4) + +#define VC4_RENDER_CONFIG_FORMAT_MASK VC4_MASK(3, 2) +#define VC4_RENDER_CONFIG_FORMAT_SHIFT 2 +#define VC4_RENDER_CONFIG_FORMAT_BGR565_DITHERED 0 +#define VC4_RENDER_CONFIG_FORMAT_RGBA8888 1 +#define VC4_RENDER_CONFIG_FORMAT_BGR565 2 + +#define VC4_RENDER_CONFIG_TILE_BUFFER_64BIT (1 << 1) +#define VC4_RENDER_CONFIG_MS_MODE_4X (1 << 0) + +#define VC4_PRIMITIVE_LIST_FORMAT_16_INDEX (1 << 4) +#define VC4_PRIMITIVE_LIST_FORMAT_32_XY (3 << 4) +#define VC4_PRIMITIVE_LIST_FORMAT_TYPE_POINTS (0 << 0) +#define VC4_PRIMITIVE_LIST_FORMAT_TYPE_LINES (1 << 0) +#define VC4_PRIMITIVE_LIST_FORMAT_TYPE_TRIANGLES (2 << 0) +#define VC4_PRIMITIVE_LIST_FORMAT_TYPE_RHT (3 << 0) + +enum vc4_texture_data_type { + VC4_TEXTURE_TYPE_RGBA8888 = 0, + VC4_TEXTURE_TYPE_RGBX8888 = 1, + VC4_TEXTURE_TYPE_RGBA4444 = 2, + VC4_TEXTURE_TYPE_RGBA5551 = 3, + VC4_TEXTURE_TYPE_RGB565 = 4, + VC4_TEXTURE_TYPE_LUMINANCE = 5, + VC4_TEXTURE_TYPE_ALPHA = 6, + VC4_TEXTURE_TYPE_LUMALPHA = 7, + VC4_TEXTURE_TYPE_ETC1 = 8, + VC4_TEXTURE_TYPE_S16F = 9, + VC4_TEXTURE_TYPE_S8 = 10, + VC4_TEXTURE_TYPE_S16 = 11, + VC4_TEXTURE_TYPE_BW1 = 12, + VC4_TEXTURE_TYPE_A4 = 13, + VC4_TEXTURE_TYPE_A1 = 14, + VC4_TEXTURE_TYPE_RGBA64 = 15, + VC4_TEXTURE_TYPE_RGBA32R = 16, + VC4_TEXTURE_TYPE_YUV422R = 17, +}; + +#define VC4_TEX_P0_OFFSET_MASK VC4_MASK(31, 12) +#define VC4_TEX_P0_OFFSET_SHIFT 12 +#define VC4_TEX_P0_CSWIZ_MASK VC4_MASK(11, 10) +#define VC4_TEX_P0_CSWIZ_SHIFT 10 +#define VC4_TEX_P0_CMMODE_MASK VC4_MASK(9, 9) +#define VC4_TEX_P0_CMMODE_SHIFT 9 +#define VC4_TEX_P0_FLIPY_MASK VC4_MASK(8, 8) +#define VC4_TEX_P0_FLIPY_SHIFT 8 +#define VC4_TEX_P0_TYPE_MASK VC4_MASK(7, 4) +#define VC4_TEX_P0_TYPE_SHIFT 4 +#define VC4_TEX_P0_MIPLVLS_MASK VC4_MASK(3, 0) +#define VC4_TEX_P0_MIPLVLS_SHIFT 0 + +#define VC4_TEX_P1_TYPE4_MASK VC4_MASK(31, 31) +#define VC4_TEX_P1_TYPE4_SHIFT 31 +#define VC4_TEX_P1_HEIGHT_MASK VC4_MASK(30, 20) +#define VC4_TEX_P1_HEIGHT_SHIFT 20 +#define VC4_TEX_P1_ETCFLIP_MASK VC4_MASK(19, 19) +#define VC4_TEX_P1_ETCFLIP_SHIFT 19 +#define VC4_TEX_P1_WIDTH_MASK VC4_MASK(18, 8) +#define VC4_TEX_P1_WIDTH_SHIFT 8 + +#define VC4_TEX_P1_MAGFILT_MASK VC4_MASK(7, 7) +#define VC4_TEX_P1_MAGFILT_SHIFT 7 +# define VC4_TEX_P1_MAGFILT_LINEAR 0 +# define VC4_TEX_P1_MAGFILT_NEAREST 1 + +#define VC4_TEX_P1_MINFILT_MASK VC4_MASK(6, 4) +#define VC4_TEX_P1_MINFILT_SHIFT 4 +# define VC4_TEX_P1_MINFILT_LINEAR 0 +# define VC4_TEX_P1_MINFILT_NEAREST 1 +# define VC4_TEX_P1_MINFILT_NEAR_MIP_NEAR 2 +# define VC4_TEX_P1_MINFILT_NEAR_MIP_LIN 3 +# define VC4_TEX_P1_MINFILT_LIN_MIP_NEAR 4 +# define VC4_TEX_P1_MINFILT_LIN_MIP_LIN 5 + +#define VC4_TEX_P1_WRAP_T_MASK VC4_MASK(3, 2) +#define VC4_TEX_P1_WRAP_T_SHIFT 2 +#define VC4_TEX_P1_WRAP_S_MASK VC4_MASK(1, 0) +#define VC4_TEX_P1_WRAP_S_SHIFT 0 +# define VC4_TEX_P1_WRAP_REPEAT 0 +# define VC4_TEX_P1_WRAP_CLAMP 1 +# define VC4_TEX_P1_WRAP_MIRROR 2 +# define VC4_TEX_P1_WRAP_BORDER 3 + +#define VC4_TEX_P2_PTYPE_MASK VC4_MASK(31, 30) +#define VC4_TEX_P2_PTYPE_SHIFT 30 +# define VC4_TEX_P2_PTYPE_IGNORED 0 +# define VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE 1 +# define VC4_TEX_P2_PTYPE_CHILD_IMAGE_DIMENSIONS 2 +# define VC4_TEX_P2_PTYPE_CHILD_IMAGE_OFFSETS 3 + +/* VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE bits */ +#define VC4_TEX_P2_CMST_MASK VC4_MASK(29, 12) +#define VC4_TEX_P2_CMST_SHIFT 12 +#define VC4_TEX_P2_BSLOD_MASK VC4_MASK(0, 0) +#define VC4_TEX_P2_BSLOD_SHIFT 0 + +/* VC4_TEX_P2_PTYPE_CHILD_IMAGE_DIMENSIONS */ +#define VC4_TEX_P2_CHEIGHT_MASK VC4_MASK(22, 12) +#define VC4_TEX_P2_CHEIGHT_SHIFT 12 +#define VC4_TEX_P2_CWIDTH_MASK VC4_MASK(10, 0) +#define VC4_TEX_P2_CWIDTH_SHIFT 0 + +/* VC4_TEX_P2_PTYPE_CHILD_IMAGE_OFFSETS */ +#define VC4_TEX_P2_CYOFF_MASK VC4_MASK(22, 12) +#define VC4_TEX_P2_CYOFF_SHIFT 12 +#define VC4_TEX_P2_CXOFF_MASK VC4_MASK(10, 0) +#define VC4_TEX_P2_CXOFF_SHIFT 0 + +#endif /* VC4_PACKET_H */ diff --git a/lib/libdrm/vc4/vc4_qpu_defines.h b/lib/libdrm/vc4/vc4_qpu_defines.h new file mode 100644 index 000000000..26fcf505f --- /dev/null +++ b/lib/libdrm/vc4/vc4_qpu_defines.h @@ -0,0 +1,274 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef VC4_QPU_DEFINES_H +#define VC4_QPU_DEFINES_H + +enum qpu_op_add { + QPU_A_NOP, + QPU_A_FADD, + QPU_A_FSUB, + QPU_A_FMIN, + QPU_A_FMAX, + QPU_A_FMINABS, + QPU_A_FMAXABS, + QPU_A_FTOI, + QPU_A_ITOF, + QPU_A_ADD = 12, + QPU_A_SUB, + QPU_A_SHR, + QPU_A_ASR, + QPU_A_ROR, + QPU_A_SHL, + QPU_A_MIN, + QPU_A_MAX, + QPU_A_AND, + QPU_A_OR, + QPU_A_XOR, + QPU_A_NOT, + QPU_A_CLZ, + QPU_A_V8ADDS = 30, + QPU_A_V8SUBS = 31, +}; + +enum qpu_op_mul { + QPU_M_NOP, + QPU_M_FMUL, + QPU_M_MUL24, + QPU_M_V8MULD, + QPU_M_V8MIN, + QPU_M_V8MAX, + QPU_M_V8ADDS, + QPU_M_V8SUBS, +}; + +enum qpu_raddr { + QPU_R_FRAG_PAYLOAD_ZW = 15, /* W for A file, Z for B file */ + /* 0-31 are the plain regfile a or b fields */ + QPU_R_UNIF = 32, + QPU_R_VARY = 35, + QPU_R_ELEM_QPU = 38, + QPU_R_NOP, + QPU_R_XY_PIXEL_COORD = 41, + QPU_R_MS_REV_FLAGS = 42, + QPU_R_VPM = 48, + QPU_R_VPM_LD_BUSY, + QPU_R_VPM_LD_WAIT, + QPU_R_MUTEX_ACQUIRE, +}; + +enum qpu_waddr { + /* 0-31 are the plain regfile a or b fields */ + QPU_W_ACC0 = 32, /* aka r0 */ + QPU_W_ACC1, + QPU_W_ACC2, + QPU_W_ACC3, + QPU_W_TMU_NOSWAP, + QPU_W_ACC5, + QPU_W_HOST_INT, + QPU_W_NOP, + QPU_W_UNIFORMS_ADDRESS, + QPU_W_QUAD_XY, /* X for regfile a, Y for regfile b */ + QPU_W_MS_FLAGS = 42, + QPU_W_REV_FLAG = 42, + QPU_W_TLB_STENCIL_SETUP = 43, + QPU_W_TLB_Z, + QPU_W_TLB_COLOR_MS, + QPU_W_TLB_COLOR_ALL, + QPU_W_TLB_ALPHA_MASK, + QPU_W_VPM, + QPU_W_VPMVCD_SETUP, /* LD for regfile a, ST for regfile b */ + QPU_W_VPM_ADDR, /* LD for regfile a, ST for regfile b */ + QPU_W_MUTEX_RELEASE, + QPU_W_SFU_RECIP, + QPU_W_SFU_RECIPSQRT, + QPU_W_SFU_EXP, + QPU_W_SFU_LOG, + QPU_W_TMU0_S, + QPU_W_TMU0_T, + QPU_W_TMU0_R, + QPU_W_TMU0_B, + QPU_W_TMU1_S, + QPU_W_TMU1_T, + QPU_W_TMU1_R, + QPU_W_TMU1_B, +}; + +enum qpu_sig_bits { + QPU_SIG_SW_BREAKPOINT, + QPU_SIG_NONE, + QPU_SIG_THREAD_SWITCH, + QPU_SIG_PROG_END, + QPU_SIG_WAIT_FOR_SCOREBOARD, + QPU_SIG_SCOREBOARD_UNLOCK, + QPU_SIG_LAST_THREAD_SWITCH, + QPU_SIG_COVERAGE_LOAD, + QPU_SIG_COLOR_LOAD, + QPU_SIG_COLOR_LOAD_END, + QPU_SIG_LOAD_TMU0, + QPU_SIG_LOAD_TMU1, + QPU_SIG_ALPHA_MASK_LOAD, + QPU_SIG_SMALL_IMM, + QPU_SIG_LOAD_IMM, + QPU_SIG_BRANCH +}; + +enum qpu_mux { + /* hardware mux values */ + QPU_MUX_R0, + QPU_MUX_R1, + QPU_MUX_R2, + QPU_MUX_R3, + QPU_MUX_R4, + QPU_MUX_R5, + QPU_MUX_A, + QPU_MUX_B, + + /** + * Non-hardware mux value, stores a small immediate field to be + * programmed into raddr_b in the qpu_reg.index. + */ + QPU_MUX_SMALL_IMM, +}; + +enum qpu_cond { + QPU_COND_NEVER, + QPU_COND_ALWAYS, + QPU_COND_ZS, + QPU_COND_ZC, + QPU_COND_NS, + QPU_COND_NC, + QPU_COND_CS, + QPU_COND_CC, +}; + +enum qpu_pack_mul { + QPU_PACK_MUL_NOP, + QPU_PACK_MUL_8888 = 3, /* replicated to each 8 bits of the 32-bit dst. */ + QPU_PACK_MUL_8A, + QPU_PACK_MUL_8B, + QPU_PACK_MUL_8C, + QPU_PACK_MUL_8D, +}; + +enum qpu_pack_a { + QPU_PACK_A_NOP, + /* convert to 16 bit float if float input, or to int16. */ + QPU_PACK_A_16A, + QPU_PACK_A_16B, + /* replicated to each 8 bits of the 32-bit dst. */ + QPU_PACK_A_8888, + /* Convert to 8-bit unsigned int. */ + QPU_PACK_A_8A, + QPU_PACK_A_8B, + QPU_PACK_A_8C, + QPU_PACK_A_8D, + + /* Saturating variants of the previous instructions. */ + QPU_PACK_A_32_SAT, /* int-only */ + QPU_PACK_A_16A_SAT, /* int or float */ + QPU_PACK_A_16B_SAT, + QPU_PACK_A_8888_SAT, + QPU_PACK_A_8A_SAT, + QPU_PACK_A_8B_SAT, + QPU_PACK_A_8C_SAT, + QPU_PACK_A_8D_SAT, +}; + +enum qpu_unpack { + QPU_UNPACK_NOP, + QPU_UNPACK_16A, + QPU_UNPACK_16B, + QPU_UNPACK_8D_REP, + QPU_UNPACK_8A, + QPU_UNPACK_8B, + QPU_UNPACK_8C, + QPU_UNPACK_8D, +}; + +#define QPU_MASK(high, low) ((((uint64_t)1<<((high)-(low)+1))-1)<<(low)) +/* Using the GNU statement expression extension */ +#define QPU_SET_FIELD(value, field) \ + ({ \ + uint64_t fieldval = (uint64_t)(value) << field ## _SHIFT; \ + assert((fieldval & ~ field ## _MASK) == 0); \ + fieldval & field ## _MASK; \ + }) + +#define QPU_GET_FIELD(word, field) ((uint32_t)(((word) & field ## _MASK) >> field ## _SHIFT)) + +#define QPU_UPDATE_FIELD(inst, value, field) \ + (((inst) & ~(field ## _MASK)) | QPU_SET_FIELD(value, field)) + +#define QPU_SIG_SHIFT 60 +#define QPU_SIG_MASK QPU_MASK(63, 60) + +#define QPU_UNPACK_SHIFT 57 +#define QPU_UNPACK_MASK QPU_MASK(59, 57) + +/** + * If set, the pack field means PACK_MUL or R4 packing, instead of normal + * regfile a packing. + */ +#define QPU_PM ((uint64_t)1 << 56) + +#define QPU_PACK_SHIFT 52 +#define QPU_PACK_MASK QPU_MASK(55, 52) + +#define QPU_COND_ADD_SHIFT 49 +#define QPU_COND_ADD_MASK QPU_MASK(51, 49) +#define QPU_COND_MUL_SHIFT 46 +#define QPU_COND_MUL_MASK QPU_MASK(48, 46) + +#define QPU_SF ((uint64_t)1 << 45) + +#define QPU_WADDR_ADD_SHIFT 38 +#define QPU_WADDR_ADD_MASK QPU_MASK(43, 38) +#define QPU_WADDR_MUL_SHIFT 32 +#define QPU_WADDR_MUL_MASK QPU_MASK(37, 32) + +#define QPU_OP_MUL_SHIFT 29 +#define QPU_OP_MUL_MASK QPU_MASK(31, 29) + +#define QPU_RADDR_A_SHIFT 18 +#define QPU_RADDR_A_MASK QPU_MASK(23, 18) +#define QPU_RADDR_B_SHIFT 12 +#define QPU_RADDR_B_MASK QPU_MASK(17, 12) +#define QPU_SMALL_IMM_SHIFT 12 +#define QPU_SMALL_IMM_MASK QPU_MASK(17, 12) + +#define QPU_ADD_A_SHIFT 9 +#define QPU_ADD_A_MASK QPU_MASK(11, 9) +#define QPU_ADD_B_SHIFT 6 +#define QPU_ADD_B_MASK QPU_MASK(8, 6) +#define QPU_MUL_A_SHIFT 3 +#define QPU_MUL_A_MASK QPU_MASK(5, 3) +#define QPU_MUL_B_SHIFT 0 +#define QPU_MUL_B_MASK QPU_MASK(2, 0) + +#define QPU_WS ((uint64_t)1 << 44) + +#define QPU_OP_ADD_SHIFT 24 +#define QPU_OP_ADD_MASK QPU_MASK(28, 24) + +#endif /* VC4_QPU_DEFINES_H */ |