From bdfa17a781f273d4711d23ff91f8bb032bc10213 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Sun, 17 Nov 2013 06:45:33 +0000 Subject: [PATCH] intel-2D: gen6 debug output git-svn-id: svn://kolibrios.org@4245 a494cfbc-eb01-0410-851d-a64ba20cac60 --- drivers/video/Intel-2D/drm.h | 825 ------------- drivers/video/Intel-2D/gen3_render.c | 20 +- drivers/video/Intel-2D/i915_drm.h | 954 --------------- drivers/video/Intel-2D/kgem-sna.c | 92 +- drivers/video/Intel-2D/kgem.h | 1378 +++++++++++----------- drivers/video/Intel-2D/kgem_debug.c | 451 +++++++ drivers/video/Intel-2D/kgem_debug.h | 34 + drivers/video/Intel-2D/kgem_debug_gen6.c | 1077 +++++++++++++++++ drivers/video/Intel-2D/pixlib2.c | 282 +++++ 9 files changed, 2608 insertions(+), 2505 deletions(-) delete mode 100644 drivers/video/Intel-2D/drm.h delete mode 100644 drivers/video/Intel-2D/i915_drm.h create mode 100644 drivers/video/Intel-2D/kgem_debug.c create mode 100644 drivers/video/Intel-2D/kgem_debug.h create mode 100644 drivers/video/Intel-2D/kgem_debug_gen6.c create mode 100644 drivers/video/Intel-2D/pixlib2.c diff --git a/drivers/video/Intel-2D/drm.h b/drivers/video/Intel-2D/drm.h deleted file mode 100644 index 87acad348f..0000000000 --- a/drivers/video/Intel-2D/drm.h +++ /dev/null @@ -1,825 +0,0 @@ -/** - * \file drm.h - * Header for the Direct Rendering Manager - * - * \author Rickard E. (Rik) Faith - * - * \par Acknowledgments: - * Dec 1999, Richard Henderson , move to generic \c cmpxchg. - */ - -/* - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * 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 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 _DRM_H_ -#define _DRM_H_ - -#include -//#include - -typedef int8_t __s8; -typedef uint8_t __u8; -typedef int16_t __s16; -typedef uint16_t __u16; -typedef int32_t __s32; -typedef uint32_t __u32; -typedef int64_t __s64; -typedef uint64_t __u64; -typedef unsigned int drm_handle_t; - - -#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ -#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ -#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ -#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ - -#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ -#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ -#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) -#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) -#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) - -typedef unsigned int drm_context_t; -typedef unsigned int drm_drawable_t; -typedef unsigned int drm_magic_t; - -/** - * Cliprect. - * - * \warning: If you change this structure, make sure you change - * XF86DRIClipRectRec in the server as well - * - * \note KW: Actually it's illegal to change either for - * backwards-compatibility reasons. - */ -struct drm_clip_rect { - unsigned short x1; - unsigned short y1; - unsigned short x2; - unsigned short y2; -}; - -/** - * Drawable information. - */ -struct drm_drawable_info { - unsigned int num_rects; - struct drm_clip_rect *rects; -}; - -/** - * Texture region, - */ -struct drm_tex_region { - unsigned char next; - unsigned char prev; - unsigned char in_use; - unsigned char padding; - unsigned int age; -}; - -/** - * Hardware lock. - * - * The lock structure is a simple cache-line aligned integer. To avoid - * processor bus contention on a multiprocessor system, there should not be any - * other data stored in the same cache line. - */ -struct drm_hw_lock { - __volatile__ unsigned int lock; /**< lock variable */ - char padding[60]; /**< Pad to cache line */ -}; - -/** - * DRM_IOCTL_VERSION ioctl argument type. - * - * \sa drmGetVersion(). - */ -struct drm_version { - int version_major; /**< Major version */ - int version_minor; /**< Minor version */ - int version_patchlevel; /**< Patch level */ - size_t name_len; /**< Length of name buffer */ - char *name; /**< Name of driver */ - size_t date_len; /**< Length of date buffer */ - char *date; /**< User-space buffer to hold date */ - size_t desc_len; /**< Length of desc buffer */ - char *desc; /**< User-space buffer to hold desc */ -}; - -/** - * DRM_IOCTL_GET_UNIQUE ioctl argument type. - * - * \sa drmGetBusid() and drmSetBusId(). - */ -struct drm_unique { - size_t unique_len; /**< Length of unique */ - char *unique; /**< Unique name for driver instantiation */ -}; - -struct drm_list { - int count; /**< Length of user-space structures */ - struct drm_version *version; -}; - -struct drm_block { - int unused; -}; - -/** - * DRM_IOCTL_CONTROL ioctl argument type. - * - * \sa drmCtlInstHandler() and drmCtlUninstHandler(). - */ -struct drm_control { - enum { - DRM_ADD_COMMAND, - DRM_RM_COMMAND, - DRM_INST_HANDLER, - DRM_UNINST_HANDLER - } func; - int irq; -}; - -/** - * Type of memory to map. - */ -enum drm_map_type { - _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ - _DRM_REGISTERS = 1, /**< no caching, no core dump */ - _DRM_SHM = 2, /**< shared, cached */ - _DRM_AGP = 3, /**< AGP/GART */ - _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ - _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ - _DRM_GEM = 6, /**< GEM object */ -}; - -/** - * Memory mapping flags. - */ -enum drm_map_flags { - _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ - _DRM_READ_ONLY = 0x02, - _DRM_LOCKED = 0x04, /**< shared, cached, locked */ - _DRM_KERNEL = 0x08, /**< kernel requires access */ - _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ - _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ - _DRM_REMOVABLE = 0x40, /**< Removable mapping */ - _DRM_DRIVER = 0x80 /**< Managed by driver */ -}; - -struct drm_ctx_priv_map { - unsigned int ctx_id; /**< Context requesting private mapping */ - void *handle; /**< Handle of map */ -}; - -/** - * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls - * argument type. - * - * \sa drmAddMap(). - */ -struct drm_map { - unsigned long offset; /**< Requested physical address (0 for SAREA)*/ - unsigned long size; /**< Requested physical size (bytes) */ - enum drm_map_type type; /**< Type of memory to map */ - enum drm_map_flags flags; /**< Flags */ - void *handle; /**< User-space: "Handle" to pass to mmap() */ - /**< Kernel-space: kernel-virtual address */ - int mtrr; /**< MTRR slot used */ - /* Private data */ -}; - -/** - * DRM_IOCTL_GET_CLIENT ioctl argument type. - */ -struct drm_client { - int idx; /**< Which client desired? */ - int auth; /**< Is client authenticated? */ - unsigned long pid; /**< Process ID */ - unsigned long uid; /**< User ID */ - unsigned long magic; /**< Magic */ - unsigned long iocs; /**< Ioctl count */ -}; - -enum drm_stat_type { - _DRM_STAT_LOCK, - _DRM_STAT_OPENS, - _DRM_STAT_CLOSES, - _DRM_STAT_IOCTLS, - _DRM_STAT_LOCKS, - _DRM_STAT_UNLOCKS, - _DRM_STAT_VALUE, /**< Generic value */ - _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ - _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ - - _DRM_STAT_IRQ, /**< IRQ */ - _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ - _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ - _DRM_STAT_DMA, /**< DMA */ - _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ - _DRM_STAT_MISSED /**< Missed DMA opportunity */ - /* Add to the *END* of the list */ -}; - -/** - * DRM_IOCTL_GET_STATS ioctl argument type. - */ -struct drm_stats { - unsigned long count; - struct { - unsigned long value; - enum drm_stat_type type; - } data[15]; -}; - -/** - * Hardware locking flags. - */ -enum drm_lock_flags { - _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ - _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ - _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ - _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ - /* These *HALT* flags aren't supported yet - -- they will be used to support the - full-screen DGA-like mode. */ - _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ - _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ -}; - -/** - * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. - * - * \sa drmGetLock() and drmUnlock(). - */ -struct drm_lock { - int context; - enum drm_lock_flags flags; -}; - -/** - * DMA flags - * - * \warning - * These values \e must match xf86drm.h. - * - * \sa drm_dma. - */ -enum drm_dma_flags { - /* Flags for DMA buffer dispatch */ - _DRM_DMA_BLOCK = 0x01, /**< - * Block until buffer dispatched. - * - * \note The buffer may not yet have - * been processed by the hardware -- - * getting a hardware lock with the - * hardware quiescent will ensure - * that the buffer has been - * processed. - */ - _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ - _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ - - /* Flags for DMA buffer request */ - _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ - _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ - _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ -}; - -/** - * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. - * - * \sa drmAddBufs(). - */ -struct drm_buf_desc { - int count; /**< Number of buffers of this size */ - int size; /**< Size in bytes */ - int low_mark; /**< Low water mark */ - int high_mark; /**< High water mark */ - enum { - _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ - _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ - _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ - _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ - _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ - } flags; - unsigned long agp_start; /**< - * Start address of where the AGP buffers are - * in the AGP aperture - */ -}; - -/** - * DRM_IOCTL_INFO_BUFS ioctl argument type. - */ -struct drm_buf_info { - int count; /**< Entries in list */ - struct drm_buf_desc *list; -}; - -/** - * DRM_IOCTL_FREE_BUFS ioctl argument type. - */ -struct drm_buf_free { - int count; - int *list; -}; - -/** - * Buffer information - * - * \sa drm_buf_map. - */ -struct drm_buf_pub { - int idx; /**< Index into the master buffer list */ - int total; /**< Buffer size */ - int used; /**< Amount of buffer in use (for DMA) */ - void *address; /**< Address of buffer */ -}; - -/** - * DRM_IOCTL_MAP_BUFS ioctl argument type. - */ -struct drm_buf_map { - int count; /**< Length of the buffer list */ -#ifdef __cplusplus - void *virt; -#else - void *virtual; /**< Mmap'd area in user-virtual */ -#endif - struct drm_buf_pub *list; /**< Buffer information */ -}; - -/** - * DRM_IOCTL_DMA ioctl argument type. - * - * Indices here refer to the offset into the buffer list in drm_buf_get. - * - * \sa drmDMA(). - */ -struct drm_dma { - int context; /**< Context handle */ - int send_count; /**< Number of buffers to send */ - int *send_indices; /**< List of handles to buffers */ - int *send_sizes; /**< Lengths of data to send */ - enum drm_dma_flags flags; /**< Flags */ - int request_count; /**< Number of buffers requested */ - int request_size; /**< Desired size for buffers */ - int *request_indices; /**< Buffer information */ - int *request_sizes; - int granted_count; /**< Number of buffers granted */ -}; - -enum drm_ctx_flags { - _DRM_CONTEXT_PRESERVED = 0x01, - _DRM_CONTEXT_2DONLY = 0x02 -}; - -/** - * DRM_IOCTL_ADD_CTX ioctl argument type. - * - * \sa drmCreateContext() and drmDestroyContext(). - */ -struct drm_ctx { - drm_context_t handle; - enum drm_ctx_flags flags; -}; - -/** - * DRM_IOCTL_RES_CTX ioctl argument type. - */ -struct drm_ctx_res { - int count; - struct drm_ctx *contexts; -}; - -/** - * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. - */ -struct drm_draw { - drm_drawable_t handle; -}; - -/** - * DRM_IOCTL_UPDATE_DRAW ioctl argument type. - */ -typedef enum { - DRM_DRAWABLE_CLIPRECTS, -} drm_drawable_info_type_t; - -struct drm_update_draw { - drm_drawable_t handle; - unsigned int type; - unsigned int num; - unsigned long long data; -}; - -/** - * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. - */ -struct drm_auth { - drm_magic_t magic; -}; - -/** - * DRM_IOCTL_IRQ_BUSID ioctl argument type. - * - * \sa drmGetInterruptFromBusID(). - */ -struct drm_irq_busid { - int irq; /**< IRQ number */ - int busnum; /**< bus number */ - int devnum; /**< device number */ - int funcnum; /**< function number */ -}; - -enum drm_vblank_seq_type { - _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ - _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ - _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ - _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ - _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ - _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ - _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ -}; - -#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) -#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ - _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) - -struct drm_wait_vblank_request { - enum drm_vblank_seq_type type; - unsigned int sequence; - unsigned long signal; -}; - -struct drm_wait_vblank_reply { - enum drm_vblank_seq_type type; - unsigned int sequence; - long tval_sec; - long tval_usec; -}; - -/** - * DRM_IOCTL_WAIT_VBLANK ioctl argument type. - * - * \sa drmWaitVBlank(). - */ -union drm_wait_vblank { - struct drm_wait_vblank_request request; - struct drm_wait_vblank_reply reply; -}; - -#define _DRM_PRE_MODESET 1 -#define _DRM_POST_MODESET 2 - -/** - * DRM_IOCTL_MODESET_CTL ioctl argument type - * - * \sa drmModesetCtl(). - */ -struct drm_modeset_ctl { - __u32 crtc; - __u32 cmd; -}; - -/** - * DRM_IOCTL_AGP_ENABLE ioctl argument type. - * - * \sa drmAgpEnable(). - */ -struct drm_agp_mode { - unsigned long mode; /**< AGP mode */ -}; - -/** - * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. - * - * \sa drmAgpAlloc() and drmAgpFree(). - */ -struct drm_agp_buffer { - unsigned long size; /**< In bytes -- will round to page boundary */ - unsigned long handle; /**< Used for binding / unbinding */ - unsigned long type; /**< Type of memory to allocate */ - unsigned long physical; /**< Physical used by i810 */ -}; - -/** - * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. - * - * \sa drmAgpBind() and drmAgpUnbind(). - */ -struct drm_agp_binding { - unsigned long handle; /**< From drm_agp_buffer */ - unsigned long offset; /**< In bytes -- will round to page boundary */ -}; - -/** - * DRM_IOCTL_AGP_INFO ioctl argument type. - * - * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), - * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), - * drmAgpVendorId() and drmAgpDeviceId(). - */ -struct drm_agp_info { - int agp_version_major; - int agp_version_minor; - unsigned long mode; - unsigned long aperture_base; /* physical address */ - unsigned long aperture_size; /* bytes */ - unsigned long memory_allowed; /* bytes */ - unsigned long memory_used; - - /* PCI information */ - unsigned short id_vendor; - unsigned short id_device; -}; - -/** - * DRM_IOCTL_SG_ALLOC ioctl argument type. - */ -struct drm_scatter_gather { - unsigned long size; /**< In bytes -- will round to page boundary */ - unsigned long handle; /**< Used for mapping / unmapping */ -}; - -/** - * DRM_IOCTL_SET_VERSION ioctl argument type. - */ -struct drm_set_version { - int drm_di_major; - int drm_di_minor; - int drm_dd_major; - int drm_dd_minor; -}; - -/** DRM_IOCTL_GEM_CLOSE ioctl argument type */ -struct drm_gem_close { - /** Handle of the object to be closed. */ - __u32 handle; - __u32 pad; -}; - -/** DRM_IOCTL_GEM_FLINK ioctl argument type */ -struct drm_gem_flink { - /** Handle for the object being named */ - __u32 handle; - - /** Returned global name */ - __u32 name; -}; - -/** DRM_IOCTL_GEM_OPEN ioctl argument type */ -struct drm_gem_open { - /** Name of object being opened */ - __u32 name; - - /** Returned handle for the object */ - __u32 handle; - - /** Returned size of the object */ - __u64 size; -}; - -/** DRM_IOCTL_GET_CAP ioctl argument type */ -struct drm_get_cap { - __u64 capability; - __u64 value; -}; - -#define DRM_CLOEXEC O_CLOEXEC -struct drm_prime_handle { - __u32 handle; - - /** Flags.. only applicable for handle->fd */ - __u32 flags; - - /** Returned dmabuf file descriptor */ - __s32 fd; -}; - -//#include "drm_mode.h" - -#if 0 - -#define DRM_IOCTL_BASE 'd' -#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) -#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) -#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) -#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) - -#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) -#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) -#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) -#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) -#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) -#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) -#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) -#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) -#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) -#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) -#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) -#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) -#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) - -#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) -#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) -#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) -#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) -#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) -#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) -#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) -#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) -#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) -#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) -#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) - -#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) - -#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) -#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) - -#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) -#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) - -#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) -#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) -#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) -#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) -#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) -#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) -#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) -#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) -#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) -#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) -#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) -#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) -#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) - -#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) -#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) - -#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) -#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) -#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) -#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) -#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) -#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) -#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) -#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) - -#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) -#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) - -#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) - -#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) - -#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) -#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) -#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) -#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) -#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) -#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) -#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) -#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) -#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) -#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) - -#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) -#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) -#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) -#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) -#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) -#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) -#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) -#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) - -#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) -#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) -#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) -#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) -#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) -#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) -#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) -#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) -#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) - -#endif - -/** - * Device specific ioctls should only be in their respective headers - * The device specific ioctl range is from 0x40 to 0x99. - * Generic IOCTLS restart at 0xA0. - * - * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and - * drmCommandReadWrite(). - */ -#define DRM_COMMAND_BASE 0x40 -#define DRM_COMMAND_END 0xA0 - -/** - * Header for events written back to userspace on the drm fd. The - * type defines the type of event, the length specifies the total - * length of the event (including the header), and user_data is - * typically a 64 bit value passed with the ioctl that triggered the - * event. A read on the drm fd will always only return complete - * events, that is, if for example the read buffer is 100 bytes, and - * there are two 64 byte events pending, only one will be returned. - * - * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and - * up are chipset specific. - */ -struct drm_event { - __u32 type; - __u32 length; -}; - -#define DRM_EVENT_VBLANK 0x01 -#define DRM_EVENT_FLIP_COMPLETE 0x02 - -struct drm_event_vblank { - struct drm_event base; - __u64 user_data; - __u32 tv_sec; - __u32 tv_usec; - __u32 sequence; - __u32 reserved; -}; - -#define DRM_CAP_DUMB_BUFFER 0x1 -#define DRM_CAP_VBLANK_HIGH_CRTC 0x2 -#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 -#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 -#define DRM_CAP_PRIME 0x5 - -#define DRM_PRIME_CAP_IMPORT 0x1 -#define DRM_PRIME_CAP_EXPORT 0x2 - -/* typedef area */ -typedef struct drm_clip_rect drm_clip_rect_t; -typedef struct drm_drawable_info drm_drawable_info_t; -typedef struct drm_tex_region drm_tex_region_t; -typedef struct drm_hw_lock drm_hw_lock_t; -typedef struct drm_version drm_version_t; -typedef struct drm_unique drm_unique_t; -typedef struct drm_list drm_list_t; -typedef struct drm_block drm_block_t; -typedef struct drm_control drm_control_t; -typedef enum drm_map_type drm_map_type_t; -typedef enum drm_map_flags drm_map_flags_t; -typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; -typedef struct drm_map drm_map_t; -typedef struct drm_client drm_client_t; -typedef enum drm_stat_type drm_stat_type_t; -typedef struct drm_stats drm_stats_t; -typedef enum drm_lock_flags drm_lock_flags_t; -typedef struct drm_lock drm_lock_t; -typedef enum drm_dma_flags drm_dma_flags_t; -typedef struct drm_buf_desc drm_buf_desc_t; -typedef struct drm_buf_info drm_buf_info_t; -typedef struct drm_buf_free drm_buf_free_t; -typedef struct drm_buf_pub drm_buf_pub_t; -typedef struct drm_buf_map drm_buf_map_t; -typedef struct drm_dma drm_dma_t; -typedef union drm_wait_vblank drm_wait_vblank_t; -typedef struct drm_agp_mode drm_agp_mode_t; -typedef enum drm_ctx_flags drm_ctx_flags_t; -typedef struct drm_ctx drm_ctx_t; -typedef struct drm_ctx_res drm_ctx_res_t; -typedef struct drm_draw drm_draw_t; -typedef struct drm_update_draw drm_update_draw_t; -typedef struct drm_auth drm_auth_t; -typedef struct drm_irq_busid drm_irq_busid_t; -typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; - -typedef struct drm_agp_buffer drm_agp_buffer_t; -typedef struct drm_agp_binding drm_agp_binding_t; -typedef struct drm_agp_info drm_agp_info_t; -typedef struct drm_scatter_gather drm_scatter_gather_t; -typedef struct drm_set_version drm_set_version_t; - -#endif diff --git a/drivers/video/Intel-2D/gen3_render.c b/drivers/video/Intel-2D/gen3_render.c index 941f2a9e9d..53717a5034 100644 --- a/drivers/video/Intel-2D/gen3_render.c +++ b/drivers/video/Intel-2D/gen3_render.c @@ -134,8 +134,8 @@ static uint32_t gen3_get_blend_cntl(int op, uint32_t sblend; uint32_t dblend; - sblend = BLENDFACT_ONE; - dblend = BLENDFACT_INV_SRC_ALPHA; + sblend = BLENDFACT_ONE; + dblend = BLENDFACT_INV_SRC_ALPHA; #if 0 if (op <= PictOpSrc) /* for clear and src disable blending */ @@ -1837,7 +1837,7 @@ gen3_blit_tex(struct sna *sna, uint8_t op, bool scale, PixmapPtr src, struct kgem_bo *src_bo, PixmapPtr mask,struct kgem_bo *mask_bo, - PixmapPtr dst, struct kgem_bo *dst_bo, + PixmapPtr dst, struct kgem_bo *dst_bo, int32_t src_x, int32_t src_y, int32_t msk_x, int32_t msk_y, int32_t dst_x, int32_t dst_y, @@ -1868,9 +1868,9 @@ gen3_blit_tex(struct sna *sna, tmp->src.bo = src_bo; tmp->src.pict_format = PICT_x8r8g8b8; - + gen3_composite_channel_set_format(&tmp->src, tmp->src.pict_format); - + tmp->src.width = src->drawable.width; tmp->src.height = src->drawable.height; @@ -1912,11 +1912,11 @@ gen3_blit_tex(struct sna *sna, tmp->floats_per_vertex += tmp->src.is_affine ? 2 : 4; if (!is_constant_ps(tmp->mask.u.gen3.type)) tmp->floats_per_vertex += tmp->mask.is_affine ? 2 : 4; - DBG(("%s: floats_per_vertex = 2 + %d + %d = %d [specialised emitter? %d]\n", __FUNCTION__, - !is_constant_ps(tmp->src.u.gen3.type) ? tmp->src.is_affine ? 2 : 4 : 0, - !is_constant_ps(tmp->mask.u.gen3.type) ? tmp->mask.is_affine ? 2 : 4 : 0, - tmp->floats_per_vertex, - tmp->prim_emit != gen3_emit_composite_primitive)); +// DBG(("%s: floats_per_vertex = 2 + %d + %d = %d [specialised emitter? %d]\n", __FUNCTION__, +// !is_constant_ps(tmp->src.u.gen3.type) ? tmp->src.is_affine ? 2 : 4 : 0, +// !is_constant_ps(tmp->mask.u.gen3.type) ? tmp->mask.is_affine ? 2 : 4 : 0, +// tmp->floats_per_vertex, +// tmp->prim_emit != gen3_emit_composite_primitive)); tmp->floats_per_rect = 3 * tmp->floats_per_vertex; tmp->blt = gen3_render_composite_blt; diff --git a/drivers/video/Intel-2D/i915_drm.h b/drivers/video/Intel-2D/i915_drm.h deleted file mode 100644 index d1b306cb6f..0000000000 --- a/drivers/video/Intel-2D/i915_drm.h +++ /dev/null @@ -1,954 +0,0 @@ -/* - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * 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, sub license, 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 _I915_DRM_H_ -#define _I915_DRM_H_ - -#include "drm.h" - -/* Please note that modifications to all structs defined here are - * subject to backwards-compatibility constraints. - */ - - -/* Each region is a minimum of 16k, and there are at most 255 of them. - */ -#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use - * of chars for next/prev indices */ -#define I915_LOG_MIN_TEX_REGION_SIZE 14 - -typedef struct _drm_i915_init { - enum { - I915_INIT_DMA = 0x01, - I915_CLEANUP_DMA = 0x02, - I915_RESUME_DMA = 0x03 - } func; - unsigned int mmio_offset; - int sarea_priv_offset; - unsigned int ring_start; - unsigned int ring_end; - unsigned int ring_size; - unsigned int front_offset; - unsigned int back_offset; - unsigned int depth_offset; - unsigned int w; - unsigned int h; - unsigned int pitch; - unsigned int pitch_bits; - unsigned int back_pitch; - unsigned int depth_pitch; - unsigned int cpp; - unsigned int chipset; -} drm_i915_init_t; - -typedef struct _drm_i915_sarea { - struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; - int last_upload; /* last time texture was uploaded */ - int last_enqueue; /* last time a buffer was enqueued */ - int last_dispatch; /* age of the most recently dispatched buffer */ - int ctxOwner; /* last context to upload state */ - int texAge; - int pf_enabled; /* is pageflipping allowed? */ - int pf_active; - int pf_current_page; /* which buffer is being displayed? */ - int perf_boxes; /* performance boxes to be displayed */ - int width, height; /* screen size in pixels */ - - drm_handle_t front_handle; - int front_offset; - int front_size; - - drm_handle_t back_handle; - int back_offset; - int back_size; - - drm_handle_t depth_handle; - int depth_offset; - int depth_size; - - drm_handle_t tex_handle; - int tex_offset; - int tex_size; - int log_tex_granularity; - int pitch; - int rotation; /* 0, 90, 180 or 270 */ - int rotated_offset; - int rotated_size; - int rotated_pitch; - int virtualX, virtualY; - - unsigned int front_tiled; - unsigned int back_tiled; - unsigned int depth_tiled; - unsigned int rotated_tiled; - unsigned int rotated2_tiled; - - int pipeA_x; - int pipeA_y; - int pipeA_w; - int pipeA_h; - int pipeB_x; - int pipeB_y; - int pipeB_w; - int pipeB_h; - - /* fill out some space for old userspace triple buffer */ - drm_handle_t unused_handle; - __u32 unused1, unused2, unused3; - - /* buffer object handles for static buffers. May change - * over the lifetime of the client. - */ - __u32 front_bo_handle; - __u32 back_bo_handle; - __u32 unused_bo_handle; - __u32 depth_bo_handle; - -} drm_i915_sarea_t; - -/* due to userspace building against these headers we need some compat here */ -#define planeA_x pipeA_x -#define planeA_y pipeA_y -#define planeA_w pipeA_w -#define planeA_h pipeA_h -#define planeB_x pipeB_x -#define planeB_y pipeB_y -#define planeB_w pipeB_w -#define planeB_h pipeB_h - -/* Flags for perf_boxes - */ -#define I915_BOX_RING_EMPTY 0x1 -#define I915_BOX_FLIP 0x2 -#define I915_BOX_WAIT 0x4 -#define I915_BOX_TEXTURE_LOAD 0x8 -#define I915_BOX_LOST_CONTEXT 0x10 - -/* I915 specific ioctls - * The device specific ioctl range is 0x40 to 0x79. - */ -#define DRM_I915_INIT 0x00 -#define DRM_I915_FLUSH 0x01 -#define DRM_I915_FLIP 0x02 -#define DRM_I915_BATCHBUFFER 0x03 -#define DRM_I915_IRQ_EMIT 0x04 -#define DRM_I915_IRQ_WAIT 0x05 -#define DRM_I915_GETPARAM 0x06 -#define DRM_I915_SETPARAM 0x07 -#define DRM_I915_ALLOC 0x08 -#define DRM_I915_FREE 0x09 -#define DRM_I915_INIT_HEAP 0x0a -#define DRM_I915_CMDBUFFER 0x0b -#define DRM_I915_DESTROY_HEAP 0x0c -#define DRM_I915_SET_VBLANK_PIPE 0x0d -#define DRM_I915_GET_VBLANK_PIPE 0x0e -#define DRM_I915_VBLANK_SWAP 0x0f -#define DRM_I915_HWS_ADDR 0x11 -#define DRM_I915_GEM_INIT 0x13 -#define DRM_I915_GEM_EXECBUFFER 0x14 -#define DRM_I915_GEM_PIN 0x15 -#define DRM_I915_GEM_UNPIN 0x16 -#define DRM_I915_GEM_BUSY 0x17 -#define DRM_I915_GEM_THROTTLE 0x18 -#define DRM_I915_GEM_ENTERVT 0x19 -#define DRM_I915_GEM_LEAVEVT 0x1a -#define DRM_I915_GEM_CREATE 0x1b -#define DRM_I915_GEM_PREAD 0x1c -#define DRM_I915_GEM_PWRITE 0x1d -#define DRM_I915_GEM_MMAP 0x1e -#define DRM_I915_GEM_SET_DOMAIN 0x1f -#define DRM_I915_GEM_SW_FINISH 0x20 -#define DRM_I915_GEM_SET_TILING 0x21 -#define DRM_I915_GEM_GET_TILING 0x22 -#define DRM_I915_GEM_GET_APERTURE 0x23 -#define DRM_I915_GEM_MMAP_GTT 0x24 -#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25 -#define DRM_I915_GEM_MADVISE 0x26 -#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 -#define DRM_I915_OVERLAY_ATTRS 0x28 -#define DRM_I915_GEM_EXECBUFFER2 0x29 -#define DRM_I915_GET_SPRITE_COLORKEY 0x2a -#define DRM_I915_SET_SPRITE_COLORKEY 0x2b -#define DRM_I915_GEM_WAIT 0x2c -#define DRM_I915_GEM_CONTEXT_CREATE 0x2d -#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e -#define DRM_I915_GEM_SET_CACHEING 0x2f -#define DRM_I915_GEM_GET_CACHEING 0x30 -#define DRM_I915_REG_READ 0x31 - -#define DRM_IOCTL_I915_INIT -#define DRM_IOCTL_I915_FLUSH -#define DRM_IOCTL_I915_FLIP -#define DRM_IOCTL_I915_BATCHBUFFER -#define DRM_IOCTL_I915_IRQ_EMIT -#define DRM_IOCTL_I915_IRQ_WAIT -#define DRM_IOCTL_I915_GETPARAM SRV_GET_PARAM -#define DRM_IOCTL_I915_SETPARAM -#define DRM_IOCTL_I915_ALLOC -#define DRM_IOCTL_I915_FREE -#define DRM_IOCTL_I915_INIT_HEAP -#define DRM_IOCTL_I915_CMDBUFFER -#define DRM_IOCTL_I915_DESTROY_HEAP -#define DRM_IOCTL_I915_SET_VBLANK_PIPE -#define DRM_IOCTL_I915_GET_VBLANK_PIPE -#define DRM_IOCTL_I915_VBLANK_SWAP -#define DRM_IOCTL_I915_HWS_ADDR -#define DRM_IOCTL_I915_GEM_INIT -#define DRM_IOCTL_I915_GEM_EXECBUFFER -#define DRM_IOCTL_I915_GEM_EXECBUFFER2 SRV_I915_GEM_EXECBUFFER2 -#define DRM_IOCTL_I915_GEM_PIN SRV_I915_GEM_PIN -#define DRM_IOCTL_I915_GEM_UNPIN -#define DRM_IOCTL_I915_GEM_BUSY SRV_I915_GEM_BUSY -#define DRM_IOCTL_I915_GEM_SET_CACHEING SRV_I915_GEM_SET_CACHEING -#define DRM_IOCTL_I915_GEM_GET_CACHEING -#define DRM_IOCTL_I915_GEM_THROTTLE SRV_I915_GEM_THROTTLE -#define DRM_IOCTL_I915_GEM_ENTERVT -#define DRM_IOCTL_I915_GEM_LEAVEVT -#define DRM_IOCTL_I915_GEM_CREATE SRV_I915_GEM_CREATE -#define DRM_IOCTL_I915_GEM_PREAD -#define DRM_IOCTL_I915_GEM_PWRITE SRV_I915_GEM_PWRITE -#define DRM_IOCTL_I915_GEM_MMAP SRV_I915_GEM_MMAP -#define DRM_IOCTL_I915_GEM_MMAP_GTT SRV_I915_GEM_MMAP_GTT -#define DRM_IOCTL_I915_GEM_SET_DOMAIN SRV_I915_GEM_SET_DOMAIN -#define DRM_IOCTL_I915_GEM_SW_FINISH -#define DRM_IOCTL_I915_GEM_SET_TILING -#define DRM_IOCTL_I915_GEM_GET_TILING -#define DRM_IOCTL_I915_GEM_GET_APERTURE SRV_I915_GEM_GET_APERTURE -#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID -#define DRM_IOCTL_I915_GEM_MADVISE -#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE -#define DRM_IOCTL_I915_OVERLAY_ATTRS -#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY -#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY -#define DRM_IOCTL_I915_GEM_WAIT -#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE -#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY -#define DRM_IOCTL_I915_REG_READ - -/* Allow drivers to submit batchbuffers directly to hardware, relying - * on the security mechanisms provided by hardware. - */ -typedef struct drm_i915_batchbuffer { - int start; /* agp offset */ - int used; /* nr bytes in use */ - int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ - int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ - int num_cliprects; /* mulitpass with multiple cliprects? */ - struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ -} drm_i915_batchbuffer_t; - -/* As above, but pass a pointer to userspace buffer which can be - * validated by the kernel prior to sending to hardware. - */ -typedef struct _drm_i915_cmdbuffer { - char *buf; /* pointer to userspace command buffer */ - int sz; /* nr bytes in buf */ - int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ - int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ - int num_cliprects; /* mulitpass with multiple cliprects? */ - struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ -} drm_i915_cmdbuffer_t; - -/* Userspace can request & wait on irq's: - */ -typedef struct drm_i915_irq_emit { - int *irq_seq; -} drm_i915_irq_emit_t; - -typedef struct drm_i915_irq_wait { - int irq_seq; -} drm_i915_irq_wait_t; - -/* Ioctl to query kernel params: - */ -#define I915_PARAM_IRQ_ACTIVE 1 -#define I915_PARAM_ALLOW_BATCHBUFFER 2 -#define I915_PARAM_LAST_DISPATCH 3 -#define I915_PARAM_CHIPSET_ID 4 -#define I915_PARAM_HAS_GEM 5 -#define I915_PARAM_NUM_FENCES_AVAIL 6 -#define I915_PARAM_HAS_OVERLAY 7 -#define I915_PARAM_HAS_PAGEFLIPPING 8 -#define I915_PARAM_HAS_EXECBUF2 9 -#define I915_PARAM_HAS_BSD 10 -#define I915_PARAM_HAS_BLT 11 -#define I915_PARAM_HAS_RELAXED_FENCING 12 -#define I915_PARAM_HAS_COHERENT_RINGS 13 -#define I915_PARAM_HAS_EXEC_CONSTANTS 14 -#define I915_PARAM_HAS_RELAXED_DELTA 15 -#define I915_PARAM_HAS_GEN7_SOL_RESET 16 -#define I915_PARAM_HAS_LLC 17 -#define I915_PARAM_HAS_ALIASING_PPGTT 18 -#define I915_PARAM_HAS_WAIT_TIMEOUT 19 - -typedef struct drm_i915_getparam { - int param; - int *value; -} drm_i915_getparam_t; - -/* Ioctl to set kernel params: - */ -#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 -#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 -#define I915_SETPARAM_ALLOW_BATCHBUFFER 3 -#define I915_SETPARAM_NUM_USED_FENCES 4 - -typedef struct drm_i915_setparam { - int param; - int value; -} drm_i915_setparam_t; - -/* A memory manager for regions of shared memory: - */ -#define I915_MEM_REGION_AGP 1 - -typedef struct drm_i915_mem_alloc { - int region; - int alignment; - int size; - int *region_offset; /* offset from start of fb or agp */ -} drm_i915_mem_alloc_t; - -typedef struct drm_i915_mem_free { - int region; - int region_offset; -} drm_i915_mem_free_t; - -typedef struct drm_i915_mem_init_heap { - int region; - int size; - int start; -} drm_i915_mem_init_heap_t; - -/* Allow memory manager to be torn down and re-initialized (eg on - * rotate): - */ -typedef struct drm_i915_mem_destroy_heap { - int region; -} drm_i915_mem_destroy_heap_t; - -/* Allow X server to configure which pipes to monitor for vblank signals - */ -#define DRM_I915_VBLANK_PIPE_A 1 -#define DRM_I915_VBLANK_PIPE_B 2 - -typedef struct drm_i915_vblank_pipe { - int pipe; -} drm_i915_vblank_pipe_t; - -/* Schedule buffer swap at given vertical blank: - */ -typedef struct drm_i915_vblank_swap { - drm_drawable_t drawable; - enum drm_vblank_seq_type seqtype; - unsigned int sequence; -} drm_i915_vblank_swap_t; - -typedef struct drm_i915_hws_addr { - __u64 addr; -} drm_i915_hws_addr_t; - -struct drm_i915_gem_init { - /** - * Beginning offset in the GTT to be managed by the DRM memory - * manager. - */ - __u64 gtt_start; - /** - * Ending offset in the GTT to be managed by the DRM memory - * manager. - */ - __u64 gtt_end; -}; - -struct drm_i915_gem_create { - /** - * Requested size for the object. - * - * The (page-aligned) allocated size for the object will be returned. - */ - __u64 size; - /** - * Returned handle for the object. - * - * Object handles are nonzero. - */ - __u32 handle; - __u32 pad; -}; - -struct drm_i915_gem_pread { - /** Handle for the object being read. */ - __u32 handle; - __u32 pad; - /** Offset into the object to read from */ - __u64 offset; - /** Length of data to read */ - __u64 size; - /** - * Pointer to write the data into. - * - * This is a fixed-size type for 32/64 compatibility. - */ - __u64 data_ptr; -}; - -struct drm_i915_gem_pwrite { - /** Handle for the object being written to. */ - __u32 handle; - __u32 pad; - /** Offset into the object to write to */ - __u64 offset; - /** Length of data to write */ - __u64 size; - /** - * Pointer to read the data from. - * - * This is a fixed-size type for 32/64 compatibility. - */ - __u64 data_ptr; -}; - -struct drm_i915_gem_mmap { - /** Handle for the object being mapped. */ - __u32 handle; - __u32 pad; - /** Offset in the object to map. */ - __u64 offset; - /** - * Length of data to map. - * - * The value will be page-aligned. - */ - __u64 size; - /** - * Returned pointer the data was mapped at. - * - * This is a fixed-size type for 32/64 compatibility. - */ - __u64 addr_ptr; -}; - -struct drm_i915_gem_mmap_gtt { - /** Handle for the object being mapped. */ - __u32 handle; - __u32 pad; - /** - * Fake offset to use for subsequent mmap call - * - * This is a fixed-size type for 32/64 compatibility. - */ - __u64 offset; -}; - -struct drm_i915_gem_set_domain { - /** Handle for the object */ - __u32 handle; - - /** New read domains */ - __u32 read_domains; - - /** New write domain */ - __u32 write_domain; -}; - -struct drm_i915_gem_sw_finish { - /** Handle for the object */ - __u32 handle; -}; - -struct drm_i915_gem_relocation_entry { - /** - * Handle of the buffer being pointed to by this relocation entry. - * - * It's appealing to make this be an index into the mm_validate_entry - * list to refer to the buffer, but this allows the driver to create - * a relocation list for state buffers and not re-write it per - * exec using the buffer. - */ - __u32 target_handle; - - /** - * Value to be added to the offset of the target buffer to make up - * the relocation entry. - */ - __u32 delta; - - /** Offset in the buffer the relocation entry will be written into */ - __u64 offset; - - /** - * Offset value of the target buffer that the relocation entry was last - * written as. - * - * If the buffer has the same offset as last time, we can skip syncing - * and writing the relocation. This value is written back out by - * the execbuffer ioctl when the relocation is written. - */ - __u64 presumed_offset; - - /** - * Target memory domains read by this operation. - */ - __u32 read_domains; - - /** - * Target memory domains written by this operation. - * - * Note that only one domain may be written by the whole - * execbuffer operation, so that where there are conflicts, - * the application will get -EINVAL back. - */ - __u32 write_domain; -}; - -/** @{ - * Intel memory domains - * - * Most of these just align with the various caches in - * the system and are used to flush and invalidate as - * objects end up cached in different domains. - */ -/** CPU cache */ -#define I915_GEM_DOMAIN_CPU 0x00000001 -/** Render cache, used by 2D and 3D drawing */ -#define I915_GEM_DOMAIN_RENDER 0x00000002 -/** Sampler cache, used by texture engine */ -#define I915_GEM_DOMAIN_SAMPLER 0x00000004 -/** Command queue, used to load batch buffers */ -#define I915_GEM_DOMAIN_COMMAND 0x00000008 -/** Instruction cache, used by shader programs */ -#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 -/** Vertex address cache */ -#define I915_GEM_DOMAIN_VERTEX 0x00000020 -/** GTT domain - aperture and scanout */ -#define I915_GEM_DOMAIN_GTT 0x00000040 -/** @} */ - -struct drm_i915_gem_exec_object { - /** - * User's handle for a buffer to be bound into the GTT for this - * operation. - */ - __u32 handle; - - /** Number of relocations to be performed on this buffer */ - __u32 relocation_count; - /** - * Pointer to array of struct drm_i915_gem_relocation_entry containing - * the relocations to be performed in this buffer. - */ - __u64 relocs_ptr; - - /** Required alignment in graphics aperture */ - __u64 alignment; - - /** - * Returned value of the updated offset of the object, for future - * presumed_offset writes. - */ - __u64 offset; -}; - -struct drm_i915_gem_execbuffer { - /** - * List of buffers to be validated with their relocations to be - * performend on them. - * - * This is a pointer to an array of struct drm_i915_gem_validate_entry. - * - * These buffers must be listed in an order such that all relocations - * a buffer is performing refer to buffers that have already appeared - * in the validate list. - */ - __u64 buffers_ptr; - __u32 buffer_count; - - /** Offset in the batchbuffer to start execution from. */ - __u32 batch_start_offset; - /** Bytes used in batchbuffer from batch_start_offset */ - __u32 batch_len; - __u32 DR1; - __u32 DR4; - __u32 num_cliprects; - /** This is a struct drm_clip_rect *cliprects */ - __u64 cliprects_ptr; -}; - -struct drm_i915_gem_exec_object2 { - /** - * User's handle for a buffer to be bound into the GTT for this - * operation. - */ - __u32 handle; - - /** Number of relocations to be performed on this buffer */ - __u32 relocation_count; - /** - * Pointer to array of struct drm_i915_gem_relocation_entry containing - * the relocations to be performed in this buffer. - */ - __u64 relocs_ptr; - - /** Required alignment in graphics aperture */ - __u64 alignment; - - /** - * Returned value of the updated offset of the object, for future - * presumed_offset writes. - */ - __u64 offset; - -#define EXEC_OBJECT_NEEDS_FENCE (1<<0) - __u64 flags; - __u64 rsvd1; - __u64 rsvd2; -}; - -struct drm_i915_gem_execbuffer2 { - /** - * List of gem_exec_object2 structs - */ - __u64 buffers_ptr; - __u32 buffer_count; - - /** Offset in the batchbuffer to start execution from. */ - __u32 batch_start_offset; - /** Bytes used in batchbuffer from batch_start_offset */ - __u32 batch_len; - __u32 DR1; - __u32 DR4; - __u32 num_cliprects; - /** This is a struct drm_clip_rect *cliprects */ - __u64 cliprects_ptr; -#define I915_EXEC_RING_MASK (7<<0) -#define I915_EXEC_DEFAULT (0<<0) -#define I915_EXEC_RENDER (1<<0) -#define I915_EXEC_BSD (2<<0) -#define I915_EXEC_BLT (3<<0) - -/* Used for switching the constants addressing mode on gen4+ RENDER ring. - * Gen6+ only supports relative addressing to dynamic state (default) and - * absolute addressing. - * - * These flags are ignored for the BSD and BLT rings. - */ -#define I915_EXEC_CONSTANTS_MASK (3<<6) -#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */ -#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) -#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ - __u64 flags; - __u64 rsvd1; /* now used for context info */ - __u64 rsvd2; -}; - -/** Resets the SO write offset registers for transform feedback on gen7. */ -#define I915_EXEC_GEN7_SOL_RESET (1<<8) - -#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) -#define i915_execbuffer2_set_context_id(eb2, context) \ - (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK -#define i915_execbuffer2_get_context_id(eb2) \ - ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) - -struct drm_i915_gem_pin { - /** Handle of the buffer to be pinned. */ - __u32 handle; - __u32 pad; - - /** alignment required within the aperture */ - __u64 alignment; - - /** Returned GTT offset of the buffer. */ - __u64 offset; -}; - -struct drm_i915_gem_unpin { - /** Handle of the buffer to be unpinned. */ - __u32 handle; - __u32 pad; -}; - -struct drm_i915_gem_busy { - /** Handle of the buffer to check for busy */ - __u32 handle; - - /** Return busy status (1 if busy, 0 if idle). - * The high word is used to indicate on which rings the object - * currently resides: - * 16:31 - busy (r or r/w) rings (16 render, 17 bsd, 18 blt, etc) - */ - __u32 busy; -}; - -#define I915_CACHEING_NONE 0 -#define I915_CACHEING_CACHED 1 - -struct drm_i915_gem_cacheing { - /** - * Handle of the buffer to set/get the cacheing level of. */ - __u32 handle; - - /** - * Cacheing level to apply or return value - * - * bits0-15 are for generic cacheing control (i.e. the above defined - * values). bits16-31 are reserved for platform-specific variations - * (e.g. l3$ caching on gen7). */ - __u32 cacheing; -}; - -#define I915_TILING_NONE 0 -#define I915_TILING_X 1 -#define I915_TILING_Y 2 - -#define I915_BIT_6_SWIZZLE_NONE 0 -#define I915_BIT_6_SWIZZLE_9 1 -#define I915_BIT_6_SWIZZLE_9_10 2 -#define I915_BIT_6_SWIZZLE_9_11 3 -#define I915_BIT_6_SWIZZLE_9_10_11 4 -/* Not seen by userland */ -#define I915_BIT_6_SWIZZLE_UNKNOWN 5 -/* Seen by userland. */ -#define I915_BIT_6_SWIZZLE_9_17 6 -#define I915_BIT_6_SWIZZLE_9_10_17 7 - -struct drm_i915_gem_set_tiling { - /** Handle of the buffer to have its tiling state updated */ - __u32 handle; - - /** - * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, - * I915_TILING_Y). - * - * This value is to be set on request, and will be updated by the - * kernel on successful return with the actual chosen tiling layout. - * - * The tiling mode may be demoted to I915_TILING_NONE when the system - * has bit 6 swizzling that can't be managed correctly by GEM. - * - * Buffer contents become undefined when changing tiling_mode. - */ - __u32 tiling_mode; - - /** - * Stride in bytes for the object when in I915_TILING_X or - * I915_TILING_Y. - */ - __u32 stride; - - /** - * Returned address bit 6 swizzling required for CPU access through - * mmap mapping. - */ - __u32 swizzle_mode; -}; - -struct drm_i915_gem_get_tiling { - /** Handle of the buffer to get tiling state for. */ - __u32 handle; - - /** - * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, - * I915_TILING_Y). - */ - __u32 tiling_mode; - - /** - * Returned address bit 6 swizzling required for CPU access through - * mmap mapping. - */ - __u32 swizzle_mode; -}; - -struct drm_i915_gem_get_aperture { - /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ - __u64 aper_size; - - /** - * Available space in the aperture used by i915_gem_execbuffer, in - * bytes - */ - __u64 aper_available_size; -}; - -struct drm_i915_get_pipe_from_crtc_id { - /** ID of CRTC being requested **/ - __u32 crtc_id; - - /** pipe of requested CRTC **/ - __u32 pipe; -}; - -#define I915_MADV_WILLNEED 0 -#define I915_MADV_DONTNEED 1 -#define __I915_MADV_PURGED 2 /* internal state */ - -struct drm_i915_gem_madvise { - /** Handle of the buffer to change the backing store advice */ - __u32 handle; - - /* Advice: either the buffer will be needed again in the near future, - * or wont be and could be discarded under memory pressure. - */ - __u32 madv; - - /** Whether the backing store still exists. */ - __u32 retained; -}; - -/* flags */ -#define I915_OVERLAY_TYPE_MASK 0xff -#define I915_OVERLAY_YUV_PLANAR 0x01 -#define I915_OVERLAY_YUV_PACKED 0x02 -#define I915_OVERLAY_RGB 0x03 - -#define I915_OVERLAY_DEPTH_MASK 0xff00 -#define I915_OVERLAY_RGB24 0x1000 -#define I915_OVERLAY_RGB16 0x2000 -#define I915_OVERLAY_RGB15 0x3000 -#define I915_OVERLAY_YUV422 0x0100 -#define I915_OVERLAY_YUV411 0x0200 -#define I915_OVERLAY_YUV420 0x0300 -#define I915_OVERLAY_YUV410 0x0400 - -#define I915_OVERLAY_SWAP_MASK 0xff0000 -#define I915_OVERLAY_NO_SWAP 0x000000 -#define I915_OVERLAY_UV_SWAP 0x010000 -#define I915_OVERLAY_Y_SWAP 0x020000 -#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000 - -#define I915_OVERLAY_FLAGS_MASK 0xff000000 -#define I915_OVERLAY_ENABLE 0x01000000 - -struct drm_intel_overlay_put_image { - /* various flags and src format description */ - __u32 flags; - /* source picture description */ - __u32 bo_handle; - /* stride values and offsets are in bytes, buffer relative */ - __u16 stride_Y; /* stride for packed formats */ - __u16 stride_UV; - __u32 offset_Y; /* offset for packet formats */ - __u32 offset_U; - __u32 offset_V; - /* in pixels */ - __u16 src_width; - __u16 src_height; - /* to compensate the scaling factors for partially covered surfaces */ - __u16 src_scan_width; - __u16 src_scan_height; - /* output crtc description */ - __u32 crtc_id; - __u16 dst_x; - __u16 dst_y; - __u16 dst_width; - __u16 dst_height; -}; - -/* flags */ -#define I915_OVERLAY_UPDATE_ATTRS (1<<0) -#define I915_OVERLAY_UPDATE_GAMMA (1<<1) -struct drm_intel_overlay_attrs { - __u32 flags; - __u32 color_key; - __s32 brightness; - __u32 contrast; - __u32 saturation; - __u32 gamma0; - __u32 gamma1; - __u32 gamma2; - __u32 gamma3; - __u32 gamma4; - __u32 gamma5; -}; - -/* - * Intel sprite handling - * - * Color keying works with a min/mask/max tuple. Both source and destination - * color keying is allowed. - * - * Source keying: - * Sprite pixels within the min & max values, masked against the color channels - * specified in the mask field, will be transparent. All other pixels will - * be displayed on top of the primary plane. For RGB surfaces, only the min - * and mask fields will be used; ranged compares are not allowed. - * - * Destination keying: - * Primary plane pixels that match the min value, masked against the color - * channels specified in the mask field, will be replaced by corresponding - * pixels from the sprite plane. - * - * Note that source & destination keying are exclusive; only one can be - * active on a given plane. - */ - -#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ -#define I915_SET_COLORKEY_DESTINATION (1<<1) -#define I915_SET_COLORKEY_SOURCE (1<<2) -struct drm_intel_sprite_colorkey { - __u32 plane_id; - __u32 min_value; - __u32 channel_mask; - __u32 max_value; - __u32 flags; -}; - -struct drm_i915_gem_wait { - /** Handle of BO we shall wait on */ - __u32 bo_handle; - __u32 flags; - /** Number of nanoseconds to wait, Returns time remaining. */ - __s64 timeout_ns; -}; - -struct drm_i915_gem_context_create { - /* output: id of new context*/ - __u32 ctx_id; - __u32 pad; -}; - -struct drm_i915_gem_context_destroy { - __u32 ctx_id; - __u32 pad; -}; - -struct drm_i915_reg_read { - __u64 offset; - __u64 val; /* Return value */ -}; - -struct drm_i915_mask_update { - __u32 handle; - __u32 width; - __u32 height; - __u32 bo_size; - __u32 bo_pitch; - __u32 bo_map; -}; - -#endif /* _I915_DRM_H_ */ diff --git a/drivers/video/Intel-2D/kgem-sna.c b/drivers/video/Intel-2D/kgem-sna.c index 59afd260d2..3c9098ea85 100644 --- a/drivers/video/Intel-2D/kgem-sna.c +++ b/drivers/video/Intel-2D/kgem-sna.c @@ -75,7 +75,7 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags); #define DEBUG_SYNC 0 #endif -#define SHOW_BATCH 0 +#define SHOW_BATCH 1 #if 0 #define ASSERT_IDLE(kgem__, handle__) assert(!__kgem_busy(kgem__, handle__)) @@ -136,7 +136,7 @@ struct local_i915_gem_cacheing { uint32_t cacheing; }; -#define LOCAL_IOCTL_I915_GEM_SET_CACHEING SRV_I915_GEM_SET_CACHEING +#define LOCAL_IOCTL_I915_GEM_SET_CACHEING SRV_I915_GEM_SET_CACHING struct local_fbinfo { int width; @@ -215,7 +215,7 @@ static bool gem_set_tiling(int fd, uint32_t handle, int tiling, int stride) ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); -*/ +*/ return false;//ret == 0; } @@ -228,10 +228,10 @@ static bool gem_set_cacheing(int fd, uint32_t handle, int cacheing) arg.cacheing = cacheing; return drmIoctl(fd, LOCAL_IOCTL_I915_GEM_SET_CACHEING, &arg) == 0; } - - - + + + static bool __kgem_throttle_retire(struct kgem *kgem, unsigned flags) { @@ -335,12 +335,12 @@ static int gem_write(int fd, uint32_t handle, } return drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); } - + bool __kgem_busy(struct kgem *kgem, int handle) { struct drm_i915_gem_busy busy; - + VG_CLEAR(busy); busy.handle = handle; busy.busy = !kgem->wedged; @@ -594,12 +594,12 @@ total_ram_size(void) { uint32_t data[9]; size_t size = 0; - + asm volatile("int $0x40" : "=a" (size) : "a" (18),"b"(20), "c" (data) : "memory"); - + return size != -1 ? size : 0; } @@ -3638,7 +3638,7 @@ struct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem, return NULL; } - + #endif @@ -3790,7 +3790,7 @@ uint32_t kgem_add_reloc(struct kgem *kgem, } return 0; }; - + index = kgem->nreloc++; assert(index < ARRAY_SIZE(kgem->reloc)); kgem->reloc[index].offset = pos * sizeof(kgem->batch[0]); @@ -3913,6 +3913,48 @@ static void kgem_trim_vma_cache(struct kgem *kgem, int type, int bucket) } } +void *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo) +{ + void *ptr; + + DBG(("%s: handle=%d, offset=%d, tiling=%d, map=%p, domain=%d\n", __FUNCTION__, + bo->handle, bo->presumed_offset, bo->tiling, bo->map, bo->domain)); + + assert(!bo->purged); + assert(bo->proxy == NULL); + assert(list_is_empty(&bo->list)); + + if (bo->tiling == I915_TILING_NONE && !bo->scanout && kgem->has_llc) { + DBG(("%s: converting request for GTT map into CPU map\n", + __FUNCTION__)); + return kgem_bo_map__cpu(kgem, bo); + } + + if (IS_CPU_MAP(bo->map)) + kgem_bo_release_map(kgem, bo); + + ptr = bo->map; + if (ptr == NULL) { + assert(kgem_bo_size(bo) <= kgem->aperture_mappable / 2); + + kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo)); + + ptr = __kgem_bo_map__gtt(kgem, bo); + if (ptr == NULL) + return NULL; + + /* Cache this mapping to avoid the overhead of an + * excruciatingly slow GTT pagefault. This is more an + * issue with compositing managers which need to frequently + * flush CPU damage to their GPU bo. + */ + bo->map = ptr; + DBG(("%s: caching GTT vma for %d\n", __FUNCTION__, bo->handle)); + } + + return ptr; +} + void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo) { @@ -4015,6 +4057,10 @@ void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo) return ptr; } +void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo) +{ + return kgem_bo_map__async(kgem, bo); +} void *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo) { @@ -4180,9 +4226,9 @@ int kgem_init_fb(struct kgem *kgem, struct sna_fb *fb) ret = drmIoctl(kgem->fd, SRV_FBINFO, fb); if( ret != 0 ) return 0; - + size = fb->pitch * fb->height / PAGE_SIZE; - + bo = __kgem_bo_alloc(-2, size); if (!bo) { return 0; @@ -4193,11 +4239,11 @@ int kgem_init_fb(struct kgem *kgem, struct sna_fb *fb) bo->pitch = fb->pitch; bo->tiling = I915_TILING_NONE; bo->scanout = 1; - fb->fb_bo = bo; + fb->fb_bo = bo; // printf("fb width %d height %d pitch %d bo %p\n", // fb->width, fb->height, fb->pitch, fb->fb_bo); - + return 1; }; @@ -4207,29 +4253,29 @@ int kgem_update_fb(struct kgem *kgem, struct sna_fb *fb) struct kgem_bo *bo; size_t size; int ret; - + bo = fb->fb_bo; - + ret = drmIoctl(kgem->fd, SRV_FBINFO, fb); if( ret != 0 ) return 0; - fb->fb_bo = bo; - + fb->fb_bo = bo; + size = fb->pitch * fb->height / PAGE_SIZE; if((size != bo->size.pages.count) || - (fb->pitch != bo->pitch)) + (fb->pitch != bo->pitch)) { bo->size.pages.count = size; bo->pitch = fb->pitch; printf("fb width %d height %d pitch %d bo %p\n", fb->width, fb->height, fb->pitch, fb->fb_bo); - + return 1; } - + return 0; }; diff --git a/drivers/video/Intel-2D/kgem.h b/drivers/video/Intel-2D/kgem.h index 73b6bfde66..1b5dfbaab7 100644 --- a/drivers/video/Intel-2D/kgem.h +++ b/drivers/video/Intel-2D/kgem.h @@ -1,693 +1,685 @@ -/* - * Copyright (c) 2011 Intel 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. - * - * Authors: - * Chris Wilson - * - */ - -#ifndef KGEM_H -#define KGEM_H - -#define HAS_DEBUG_FULL 0 - -#include -#include -#include -#include - -#include - -#include "compiler.h" -#include "intel_list.h" - -static inline void delay(uint32_t time) -{ - __asm__ __volatile__( - "int $0x40" - ::"a"(5), "b"(time) - :"memory"); -}; - -#undef DBG - -#if HAS_DEBUG_FULL -#define DBG(x) printf x -#else -#define DBG(x) -#endif - -struct kgem_bo { - struct kgem_request *rq; -#define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3)) -#define RQ_RING(rq) ((uintptr_t)(rq) & 3) -#define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT) - struct drm_i915_gem_exec_object2 *exec; - - struct kgem_bo *proxy; - - struct list list; - struct list request; - struct list vma; - - void *map; -#define IS_CPU_MAP(ptr) ((uintptr_t)(ptr) & 1) -#define IS_GTT_MAP(ptr) (ptr && ((uintptr_t)(ptr) & 1) == 0) - - struct kgem_bo_binding { - struct kgem_bo_binding *next; - uint32_t format; - uint16_t offset; - } binding; - - uint32_t unique_id; - uint32_t refcnt; - uint32_t handle; - uint32_t target_handle; - uint32_t presumed_offset; - uint32_t delta; - union { - struct { - uint32_t count:27; -#define PAGE_SIZE 4096 - uint32_t bucket:5; -#define NUM_CACHE_BUCKETS 16 -#define MAX_CACHE_SIZE (1 << (NUM_CACHE_BUCKETS+12)) - } pages; - uint32_t bytes; - } size; - uint32_t pitch : 18; /* max 128k */ - uint32_t tiling : 2; - uint32_t reusable : 1; - uint32_t dirty : 1; - uint32_t domain : 2; - uint32_t needs_flush : 1; - uint32_t snoop : 1; - uint32_t io : 1; - uint32_t flush : 1; - uint32_t scanout : 1; - uint32_t purged : 1; -}; -#define DOMAIN_NONE 0 -#define DOMAIN_CPU 1 -#define DOMAIN_GTT 2 -#define DOMAIN_GPU 3 - -struct kgem_request { - struct list list; - struct kgem_bo *bo; - struct list buffers; - int ring; -}; - -enum { - MAP_GTT = 0, - MAP_CPU, - NUM_MAP_TYPES, -}; - -struct kgem { - int fd; - int wedged; - unsigned gen; - - uint32_t unique_id; - - enum kgem_mode { - /* order matches I915_EXEC_RING ordering */ - KGEM_NONE = 0, - KGEM_RENDER, - KGEM_BSD, - KGEM_BLT, - } mode, ring; - - struct list flushing; - struct list large; - struct list large_inactive; - struct list active[NUM_CACHE_BUCKETS][3]; - struct list inactive[NUM_CACHE_BUCKETS]; - struct list pinned_batches[2]; - struct list snoop; - struct list scanout; - struct list batch_buffers, active_buffers; - - struct list requests[2]; - struct kgem_request *next_request; - struct kgem_request static_request; - - struct { - struct list inactive[NUM_CACHE_BUCKETS]; - int16_t count; - } vma[NUM_MAP_TYPES]; - - uint32_t batch_flags; - uint32_t batch_flags_base; -#define I915_EXEC_SECURE (1<<9) -#define LOCAL_EXEC_OBJECT_WRITE (1<<2) - - uint16_t nbatch; - uint16_t surface; - uint16_t nexec; - uint16_t nreloc; - uint16_t nreloc__self; - uint16_t nfence; - uint16_t batch_size; - uint16_t min_alignment; - - uint32_t flush:1; - uint32_t need_expire:1; - uint32_t need_purge:1; - uint32_t need_retire:1; - uint32_t need_throttle:1; - uint32_t scanout_busy:1; - uint32_t busy:1; - - uint32_t has_userptr :1; - uint32_t has_blt :1; - uint32_t has_relaxed_fencing :1; - uint32_t has_relaxed_delta :1; - uint32_t has_semaphores :1; - uint32_t has_secure_batches :1; - uint32_t has_pinned_batches :1; - uint32_t has_cacheing :1; - uint32_t has_llc :1; - uint32_t has_no_reloc :1; - uint32_t has_handle_lut :1; - - uint32_t can_blt_cpu :1; - - uint16_t fence_max; - uint16_t half_cpu_cache_pages; - uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable; - uint32_t aperture, aperture_fenced; - uint32_t max_upload_tile_size, max_copy_tile_size; - uint32_t max_gpu_size, max_cpu_size; - uint32_t large_object_size, max_object_size; - uint32_t buffer_size; - - void (*context_switch)(struct kgem *kgem, int new_mode); - void (*retire)(struct kgem *kgem); - void (*expire)(struct kgem *kgem); - - uint32_t batch[64*1024-8]; - struct drm_i915_gem_exec_object2 exec[256]; - struct drm_i915_gem_relocation_entry reloc[4096]; - uint16_t reloc__self[256]; - -#ifdef DEBUG_MEMORY - struct { - int bo_allocs; - size_t bo_bytes; - } debug_memory; -#endif -}; - -#define KGEM_BATCH_RESERVED 1 -#define KGEM_RELOC_RESERVED 4 -#define KGEM_EXEC_RESERVED 1 - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) -#endif - -#define KGEM_BATCH_SIZE(K) ((K)->batch_size-KGEM_BATCH_RESERVED) -#define KGEM_EXEC_SIZE(K) (int)(ARRAY_SIZE((K)->exec)-KGEM_EXEC_RESERVED) -#define KGEM_RELOC_SIZE(K) (int)(ARRAY_SIZE((K)->reloc)-KGEM_RELOC_RESERVED) - -void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen); -void kgem_reset(struct kgem *kgem); - -struct kgem_bo *kgem_create_map(struct kgem *kgem, - void *ptr, uint32_t size, - bool read_only); - -struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name); - -struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags); -struct kgem_bo *kgem_create_proxy(struct kgem *kgem, - struct kgem_bo *target, - int offset, int length); - - -int kgem_choose_tiling(struct kgem *kgem, - int tiling, int width, int height, int bpp); -unsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth); -#define KGEM_CAN_CREATE_GPU 0x1 -#define KGEM_CAN_CREATE_CPU 0x2 -#define KGEM_CAN_CREATE_LARGE 0x4 -#define KGEM_CAN_CREATE_GTT 0x8 - -struct kgem_bo * -kgem_replace_bo(struct kgem *kgem, - struct kgem_bo *src, - uint32_t width, - uint32_t height, - uint32_t pitch, - uint32_t bpp); -enum { - CREATE_EXACT = 0x1, - CREATE_INACTIVE = 0x2, - CREATE_CPU_MAP = 0x4, - CREATE_GTT_MAP = 0x8, - CREATE_SCANOUT = 0x10, - CREATE_PRIME = 0x20, - CREATE_TEMPORARY = 0x40, - CREATE_CACHED = 0x80, - CREATE_NO_RETIRE = 0x100, - CREATE_NO_THROTTLE = 0x200, -}; -struct kgem_bo *kgem_create_2d(struct kgem *kgem, - int width, - int height, - int bpp, - int tiling, - uint32_t flags); -struct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem, - int width, - int height, - int bpp, - uint32_t flags); - -uint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format); -void kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset); -int kgem_bo_get_swizzling(struct kgem *kgem, struct kgem_bo *bo); - -bool kgem_retire(struct kgem *kgem); - -bool __kgem_ring_is_idle(struct kgem *kgem, int ring); -static inline bool kgem_ring_is_idle(struct kgem *kgem, int ring) -{ - ring = ring == KGEM_BLT; - - if (list_is_empty(&kgem->requests[ring])) - return true; - - return __kgem_ring_is_idle(kgem, ring); -} - -static inline bool kgem_is_idle(struct kgem *kgem) -{ - if (!kgem->need_retire) - return true; - - return kgem_ring_is_idle(kgem, kgem->ring); -} - -void _kgem_submit(struct kgem *kgem); -static inline void kgem_submit(struct kgem *kgem) -{ - if (kgem->nbatch) - _kgem_submit(kgem); -} - -static inline bool kgem_flush(struct kgem *kgem, bool flush) -{ - if (kgem->nreloc == 0) - return false; - - return (kgem->flush ^ flush) && kgem_ring_is_idle(kgem, kgem->ring); -} - -static inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo) -{ - if (bo->exec) - _kgem_submit(kgem); -} - -void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo); -static inline void kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo) -{ - kgem_bo_submit(kgem, bo); - - if (!bo->needs_flush) - return; - - /* If the kernel fails to emit the flush, then it will be forced when - * we assume direct access. And as the useual failure is EIO, we do - * not actualy care. - */ - __kgem_flush(kgem, bo); -} - -static inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo) -{ - assert(bo->refcnt); - bo->refcnt++; - return bo; -} - -void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo); -static inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) -{ - assert(bo->refcnt); - if (--bo->refcnt == 0) - _kgem_bo_destroy(kgem, bo); -} - -void kgem_clear_dirty(struct kgem *kgem); - -static inline void kgem_set_mode(struct kgem *kgem, - enum kgem_mode mode, - struct kgem_bo *bo) -{ - assert(!kgem->wedged); - -#if DEBUG_FLUSH_BATCH - kgem_submit(kgem); -#endif - - if (kgem->mode == mode) - return; - -// kgem->context_switch(kgem, mode); - kgem->mode = mode; -} - -static inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode) -{ - assert(kgem->mode == KGEM_NONE); - assert(kgem->nbatch == 0); - assert(!kgem->wedged); -// kgem->context_switch(kgem, mode); - kgem->mode = mode; -} - -static inline bool kgem_check_batch(struct kgem *kgem, int num_dwords) -{ - assert(num_dwords > 0); - assert(kgem->nbatch < kgem->surface); - assert(kgem->surface <= kgem->batch_size); - return likely(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED <= kgem->surface); -} - -static inline bool kgem_check_reloc(struct kgem *kgem, int n) -{ - assert(kgem->nreloc <= KGEM_RELOC_SIZE(kgem)); - return likely(kgem->nreloc + n <= KGEM_RELOC_SIZE(kgem)); -} - -static inline bool kgem_check_exec(struct kgem *kgem, int n) -{ - assert(kgem->nexec <= KGEM_EXEC_SIZE(kgem)); - return likely(kgem->nexec + n <= KGEM_EXEC_SIZE(kgem)); -} - -static inline bool kgem_check_reloc_and_exec(struct kgem *kgem, int n) -{ - return kgem_check_reloc(kgem, n) && kgem_check_exec(kgem, n); -} - -static inline bool kgem_check_batch_with_surfaces(struct kgem *kgem, - int num_dwords, - int num_surfaces) -{ - return (int)(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED) <= (int)(kgem->surface - num_surfaces*8) && - kgem_check_reloc(kgem, num_surfaces) && - kgem_check_exec(kgem, num_surfaces); -} - -static inline uint32_t *kgem_get_batch(struct kgem *kgem) -{ - - return kgem->batch + kgem->nbatch; -} - -bool kgem_check_bo(struct kgem *kgem, ...) __attribute__((sentinel(0))); -bool kgem_check_bo_fenced(struct kgem *kgem, struct kgem_bo *bo); -bool kgem_check_many_bo_fenced(struct kgem *kgem, ...) __attribute__((sentinel(0))); - -#define KGEM_RELOC_FENCED 0x8000 -uint32_t kgem_add_reloc(struct kgem *kgem, - uint32_t pos, - struct kgem_bo *bo, - uint32_t read_write_domains, - uint32_t delta); - -void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo); -void *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo); -void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo); -void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo); -void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo); -void *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo); -void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo); -void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write); -void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo); -void __kgem_bo_unmap__cpu(struct kgem *kgem, struct kgem_bo *bo, void *ptr); -uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo); - -bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo, - const void *data, int length); - -int kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo); -void kgem_get_tile_size(struct kgem *kgem, int tiling, - int *tile_width, int *tile_height, int *tile_size); - -static inline int __kgem_buffer_size(struct kgem_bo *bo) -{ - assert(bo->proxy != NULL); - return bo->size.bytes; -} - -static inline int __kgem_bo_size(struct kgem_bo *bo) -{ - assert(bo->proxy == NULL); - return PAGE_SIZE * bo->size.pages.count; -} - -static inline int kgem_bo_size(struct kgem_bo *bo) -{ - if (bo->proxy) - return __kgem_buffer_size(bo); - else - return __kgem_bo_size(bo); -} - -/* -static inline bool kgem_bo_blt_pitch_is_ok(struct kgem *kgem, - struct kgem_bo *bo) -{ - int pitch = bo->pitch; - if (kgem->gen >= 040 && bo->tiling) - pitch /= 4; - if (pitch > MAXSHORT) { - DBG(("%s: can not blt to handle=%d, adjusted pitch=%d\n", - __FUNCTION__, bo->handle, pitch)); - return false; - } - - return true; -} - -static inline bool kgem_bo_can_blt(struct kgem *kgem, - struct kgem_bo *bo) -{ - if (bo->tiling == I915_TILING_Y) { - DBG(("%s: can not blt to handle=%d, tiling=Y\n", - __FUNCTION__, bo->handle)); - return false; - } - - return kgem_bo_blt_pitch_is_ok(kgem, bo); -} -*/ - -static inline bool __kgem_bo_is_mappable(struct kgem *kgem, - struct kgem_bo *bo) -{ - if (bo->domain == DOMAIN_GTT) - return true; - - if (kgem->gen < 040 && bo->tiling && - bo->presumed_offset & (kgem_bo_fenced_size(kgem, bo) - 1)) - return false; - - if (!bo->presumed_offset) - return kgem_bo_size(bo) <= kgem->aperture_mappable / 4; - - return bo->presumed_offset + kgem_bo_size(bo) <= kgem->aperture_mappable; -} - -static inline bool kgem_bo_is_mappable(struct kgem *kgem, - struct kgem_bo *bo) -{ - DBG(("%s: domain=%d, offset: %d size: %d\n", - __FUNCTION__, bo->domain, bo->presumed_offset, kgem_bo_size(bo))); - assert(bo->refcnt); - return __kgem_bo_is_mappable(kgem, bo); -} - -static inline bool kgem_bo_mapped(struct kgem *kgem, struct kgem_bo *bo) -{ - DBG(("%s: map=%p, tiling=%d, domain=%d\n", - __FUNCTION__, bo->map, bo->tiling, bo->domain)); - assert(bo->refcnt); - - if (bo->map == NULL) - return bo->tiling == I915_TILING_NONE && bo->domain == DOMAIN_CPU; - - return IS_CPU_MAP(bo->map) == !bo->tiling; -} - -static inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo) -{ - if (kgem_bo_mapped(kgem, bo)) - return true; - - if (!bo->tiling && kgem->has_llc) - return true; - - if (kgem->gen == 021 && bo->tiling == I915_TILING_Y) - return false; - - return kgem_bo_size(bo) <= kgem->aperture_mappable / 4; -} - -static inline bool kgem_bo_is_snoop(struct kgem_bo *bo) -{ - assert(bo->refcnt); - while (bo->proxy) - bo = bo->proxy; - return bo->snoop; -} - -bool __kgem_busy(struct kgem *kgem, int handle); - -static inline void kgem_bo_mark_busy(struct kgem_bo *bo, int ring) -{ - bo->rq = (struct kgem_request *)((uintptr_t)bo->rq | ring); -} - -inline static void __kgem_bo_clear_busy(struct kgem_bo *bo) -{ - bo->needs_flush = false; - list_del(&bo->request); - bo->rq = NULL; - bo->domain = DOMAIN_NONE; -} - -static inline bool kgem_bo_is_busy(struct kgem_bo *bo) -{ - DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, - bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL)); - assert(bo->refcnt); - return bo->rq; -} - -/* - -static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo) -{ - DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, - bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL)); - assert(bo->refcnt); - - if (bo->exec) - return true; - - if (kgem_flush(kgem, bo->flush)) - kgem_submit(kgem); - - if (bo->rq && !__kgem_busy(kgem, bo->handle)) - __kgem_bo_clear_busy(bo); - - return kgem_bo_is_busy(bo); -} - -*/ - -static inline bool kgem_bo_is_dirty(struct kgem_bo *bo) -{ - if (bo == NULL) - return false; - - assert(bo->refcnt); - return bo->dirty; -} - -static inline void kgem_bo_unclean(struct kgem *kgem, struct kgem_bo *bo) -{ - /* The bo is outside of our control, so presume it is written to */ - bo->needs_flush = true; - if (bo->rq == NULL) - bo->rq = (void *)kgem; - - if (bo->domain != DOMAIN_GPU) - bo->domain = DOMAIN_NONE; -} - -static inline void __kgem_bo_mark_dirty(struct kgem_bo *bo) -{ - DBG(("%s: handle=%d (proxy? %d)\n", __FUNCTION__, - bo->handle, bo->proxy != NULL)); - - bo->exec->flags |= LOCAL_EXEC_OBJECT_WRITE; - bo->needs_flush = bo->dirty = true; - list_move(&bo->request, &RQ(bo->rq)->buffers); -} - -static inline void kgem_bo_mark_dirty(struct kgem_bo *bo) -{ - assert(bo->refcnt); - do { - assert(bo->exec); - assert(bo->rq); - - if (bo->dirty) - return; - - __kgem_bo_mark_dirty(bo); - } while ((bo = bo->proxy)); -} - -#define KGEM_BUFFER_WRITE 0x1 -#define KGEM_BUFFER_INPLACE 0x2 -#define KGEM_BUFFER_LAST 0x4 - -#define KGEM_BUFFER_WRITE_INPLACE (KGEM_BUFFER_WRITE | KGEM_BUFFER_INPLACE) - -struct kgem_bo *kgem_create_buffer(struct kgem *kgem, - uint32_t size, uint32_t flags, - void **ret); -struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem, - int width, int height, int bpp, - uint32_t flags, - void **ret); -bool kgem_buffer_is_inplace(struct kgem_bo *bo); -void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo); - -void kgem_throttle(struct kgem *kgem); -#define MAX_INACTIVE_TIME 10 -bool kgem_expire_cache(struct kgem *kgem); -void kgem_purge_cache(struct kgem *kgem); -void kgem_cleanup_cache(struct kgem *kgem); - -#if HAS_DEBUG_FULL -void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch); -#else -static inline void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) -{ - (void)kgem; - (void)nbatch; -} -#endif - -#endif /* KGEM_H */ +/* + * Copyright (c) 2011 Intel 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. + * + * Authors: + * Chris Wilson + * + */ + +#ifndef KGEM_H +#define KGEM_H + +#define HAS_DEBUG_FULL 1 + +#include +#include +#include +#include + +#include + +#include "compiler.h" +#include "intel_list.h" + +#undef DBG + +#if HAS_DEBUG_FULL +#define DBG(x) printf x +#else +#define DBG(x) +#endif + +struct kgem_bo { + struct kgem_request *rq; +#define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3)) +#define RQ_RING(rq) ((uintptr_t)(rq) & 3) +#define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT) + struct drm_i915_gem_exec_object2 *exec; + + struct kgem_bo *proxy; + + struct list list; + struct list request; + struct list vma; + + void *map; +#define IS_CPU_MAP(ptr) ((uintptr_t)(ptr) & 1) +#define IS_GTT_MAP(ptr) (ptr && ((uintptr_t)(ptr) & 1) == 0) + + struct kgem_bo_binding { + struct kgem_bo_binding *next; + uint32_t format; + uint16_t offset; + } binding; + + uint32_t unique_id; + uint32_t refcnt; + uint32_t handle; + uint32_t target_handle; + uint32_t presumed_offset; + uint32_t delta; + union { + struct { + uint32_t count:27; +#define PAGE_SIZE 4096 + uint32_t bucket:5; +#define NUM_CACHE_BUCKETS 16 +#define MAX_CACHE_SIZE (1 << (NUM_CACHE_BUCKETS+12)) + } pages; + uint32_t bytes; + } size; + uint32_t pitch : 18; /* max 128k */ + uint32_t tiling : 2; + uint32_t reusable : 1; + uint32_t dirty : 1; + uint32_t domain : 2; + uint32_t needs_flush : 1; + uint32_t snoop : 1; + uint32_t io : 1; + uint32_t flush : 1; + uint32_t scanout : 1; + uint32_t purged : 1; +}; +#define DOMAIN_NONE 0 +#define DOMAIN_CPU 1 +#define DOMAIN_GTT 2 +#define DOMAIN_GPU 3 + +struct kgem_request { + struct list list; + struct kgem_bo *bo; + struct list buffers; + int ring; +}; + +enum { + MAP_GTT = 0, + MAP_CPU, + NUM_MAP_TYPES, +}; + +struct kgem { + int fd; + int wedged; + unsigned gen; + + uint32_t unique_id; + + enum kgem_mode { + /* order matches I915_EXEC_RING ordering */ + KGEM_NONE = 0, + KGEM_RENDER, + KGEM_BSD, + KGEM_BLT, + } mode, ring; + + struct list flushing; + struct list large; + struct list large_inactive; + struct list active[NUM_CACHE_BUCKETS][3]; + struct list inactive[NUM_CACHE_BUCKETS]; + struct list pinned_batches[2]; + struct list snoop; + struct list scanout; + struct list batch_buffers, active_buffers; + + struct list requests[2]; + struct kgem_request *next_request; + struct kgem_request static_request; + + struct { + struct list inactive[NUM_CACHE_BUCKETS]; + int16_t count; + } vma[NUM_MAP_TYPES]; + + uint32_t batch_flags; + uint32_t batch_flags_base; +#define I915_EXEC_SECURE (1<<9) +#define LOCAL_EXEC_OBJECT_WRITE (1<<2) + + uint16_t nbatch; + uint16_t surface; + uint16_t nexec; + uint16_t nreloc; + uint16_t nreloc__self; + uint16_t nfence; + uint16_t batch_size; + uint16_t min_alignment; + + uint32_t flush:1; + uint32_t need_expire:1; + uint32_t need_purge:1; + uint32_t need_retire:1; + uint32_t need_throttle:1; + uint32_t scanout_busy:1; + uint32_t busy:1; + + uint32_t has_userptr :1; + uint32_t has_blt :1; + uint32_t has_relaxed_fencing :1; + uint32_t has_relaxed_delta :1; + uint32_t has_semaphores :1; + uint32_t has_secure_batches :1; + uint32_t has_pinned_batches :1; + uint32_t has_cacheing :1; + uint32_t has_llc :1; + uint32_t has_no_reloc :1; + uint32_t has_handle_lut :1; + + uint32_t can_blt_cpu :1; + + uint16_t fence_max; + uint16_t half_cpu_cache_pages; + uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable; + uint32_t aperture, aperture_fenced; + uint32_t max_upload_tile_size, max_copy_tile_size; + uint32_t max_gpu_size, max_cpu_size; + uint32_t large_object_size, max_object_size; + uint32_t buffer_size; + + void (*context_switch)(struct kgem *kgem, int new_mode); + void (*retire)(struct kgem *kgem); + void (*expire)(struct kgem *kgem); + + uint32_t batch[64*1024-8]; + struct drm_i915_gem_exec_object2 exec[256]; + struct drm_i915_gem_relocation_entry reloc[4096]; + uint16_t reloc__self[256]; + +#ifdef DEBUG_MEMORY + struct { + int bo_allocs; + size_t bo_bytes; + } debug_memory; +#endif +}; + +#define KGEM_BATCH_RESERVED 1 +#define KGEM_RELOC_RESERVED 4 +#define KGEM_EXEC_RESERVED 1 + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) +#endif + +#define KGEM_BATCH_SIZE(K) ((K)->batch_size-KGEM_BATCH_RESERVED) +#define KGEM_EXEC_SIZE(K) (int)(ARRAY_SIZE((K)->exec)-KGEM_EXEC_RESERVED) +#define KGEM_RELOC_SIZE(K) (int)(ARRAY_SIZE((K)->reloc)-KGEM_RELOC_RESERVED) + +void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen); +void kgem_reset(struct kgem *kgem); + +struct kgem_bo *kgem_create_map(struct kgem *kgem, + void *ptr, uint32_t size, + bool read_only); + +struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name); + +struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags); +struct kgem_bo *kgem_create_proxy(struct kgem *kgem, + struct kgem_bo *target, + int offset, int length); + + +int kgem_choose_tiling(struct kgem *kgem, + int tiling, int width, int height, int bpp); +unsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth); +#define KGEM_CAN_CREATE_GPU 0x1 +#define KGEM_CAN_CREATE_CPU 0x2 +#define KGEM_CAN_CREATE_LARGE 0x4 +#define KGEM_CAN_CREATE_GTT 0x8 + +struct kgem_bo * +kgem_replace_bo(struct kgem *kgem, + struct kgem_bo *src, + uint32_t width, + uint32_t height, + uint32_t pitch, + uint32_t bpp); +enum { + CREATE_EXACT = 0x1, + CREATE_INACTIVE = 0x2, + CREATE_CPU_MAP = 0x4, + CREATE_GTT_MAP = 0x8, + CREATE_SCANOUT = 0x10, + CREATE_PRIME = 0x20, + CREATE_TEMPORARY = 0x40, + CREATE_CACHED = 0x80, + CREATE_NO_RETIRE = 0x100, + CREATE_NO_THROTTLE = 0x200, +}; +struct kgem_bo *kgem_create_2d(struct kgem *kgem, + int width, + int height, + int bpp, + int tiling, + uint32_t flags); +struct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem, + int width, + int height, + int bpp, + uint32_t flags); + +uint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format); +void kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset); +int kgem_bo_get_swizzling(struct kgem *kgem, struct kgem_bo *bo); + +bool kgem_retire(struct kgem *kgem); + +bool __kgem_ring_is_idle(struct kgem *kgem, int ring); +static inline bool kgem_ring_is_idle(struct kgem *kgem, int ring) +{ + ring = ring == KGEM_BLT; + + if (list_is_empty(&kgem->requests[ring])) + return true; + + return __kgem_ring_is_idle(kgem, ring); +} + +static inline bool kgem_is_idle(struct kgem *kgem) +{ + if (!kgem->need_retire) + return true; + + return kgem_ring_is_idle(kgem, kgem->ring); +} + +void _kgem_submit(struct kgem *kgem); +static inline void kgem_submit(struct kgem *kgem) +{ + if (kgem->nbatch) + _kgem_submit(kgem); +} + +static inline bool kgem_flush(struct kgem *kgem, bool flush) +{ + if (kgem->nreloc == 0) + return false; + + return (kgem->flush ^ flush) && kgem_ring_is_idle(kgem, kgem->ring); +} + +static inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo) +{ + if (bo->exec) + _kgem_submit(kgem); +} + +void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo); +static inline void kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo) +{ + kgem_bo_submit(kgem, bo); + + if (!bo->needs_flush) + return; + + /* If the kernel fails to emit the flush, then it will be forced when + * we assume direct access. And as the useual failure is EIO, we do + * not actualy care. + */ + __kgem_flush(kgem, bo); +} + +static inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo) +{ + assert(bo->refcnt); + bo->refcnt++; + return bo; +} + +void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo); +static inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) +{ + assert(bo->refcnt); + if (--bo->refcnt == 0) + _kgem_bo_destroy(kgem, bo); +} + +void kgem_clear_dirty(struct kgem *kgem); + +static inline void kgem_set_mode(struct kgem *kgem, + enum kgem_mode mode, + struct kgem_bo *bo) +{ + assert(!kgem->wedged); + +#if DEBUG_FLUSH_BATCH + kgem_submit(kgem); +#endif + + if (kgem->mode == mode) + return; + +// kgem->context_switch(kgem, mode); + kgem->mode = mode; +} + +static inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode) +{ + assert(kgem->mode == KGEM_NONE); + assert(kgem->nbatch == 0); + assert(!kgem->wedged); +// kgem->context_switch(kgem, mode); + kgem->mode = mode; +} + +static inline bool kgem_check_batch(struct kgem *kgem, int num_dwords) +{ + assert(num_dwords > 0); + assert(kgem->nbatch < kgem->surface); + assert(kgem->surface <= kgem->batch_size); + return likely(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED <= kgem->surface); +} + +static inline bool kgem_check_reloc(struct kgem *kgem, int n) +{ + assert(kgem->nreloc <= KGEM_RELOC_SIZE(kgem)); + return likely(kgem->nreloc + n <= KGEM_RELOC_SIZE(kgem)); +} + +static inline bool kgem_check_exec(struct kgem *kgem, int n) +{ + assert(kgem->nexec <= KGEM_EXEC_SIZE(kgem)); + return likely(kgem->nexec + n <= KGEM_EXEC_SIZE(kgem)); +} + +static inline bool kgem_check_reloc_and_exec(struct kgem *kgem, int n) +{ + return kgem_check_reloc(kgem, n) && kgem_check_exec(kgem, n); +} + +static inline bool kgem_check_batch_with_surfaces(struct kgem *kgem, + int num_dwords, + int num_surfaces) +{ + return (int)(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED) <= (int)(kgem->surface - num_surfaces*8) && + kgem_check_reloc(kgem, num_surfaces) && + kgem_check_exec(kgem, num_surfaces); +} + +static inline uint32_t *kgem_get_batch(struct kgem *kgem) +{ + + return kgem->batch + kgem->nbatch; +} + +bool kgem_check_bo(struct kgem *kgem, ...) __attribute__((sentinel(0))); +bool kgem_check_bo_fenced(struct kgem *kgem, struct kgem_bo *bo); +bool kgem_check_many_bo_fenced(struct kgem *kgem, ...) __attribute__((sentinel(0))); + +#define KGEM_RELOC_FENCED 0x8000 +uint32_t kgem_add_reloc(struct kgem *kgem, + uint32_t pos, + struct kgem_bo *bo, + uint32_t read_write_domains, + uint32_t delta); + +void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo); +void *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo); +void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo); +void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo); +void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo); +void *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo); +void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo); +void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write); +void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo); +void __kgem_bo_unmap__cpu(struct kgem *kgem, struct kgem_bo *bo, void *ptr); +uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo); + +bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo, + const void *data, int length); + +int kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo); +void kgem_get_tile_size(struct kgem *kgem, int tiling, + int *tile_width, int *tile_height, int *tile_size); + +static inline int __kgem_buffer_size(struct kgem_bo *bo) +{ + assert(bo->proxy != NULL); + return bo->size.bytes; +} + +static inline int __kgem_bo_size(struct kgem_bo *bo) +{ + assert(bo->proxy == NULL); + return PAGE_SIZE * bo->size.pages.count; +} + +static inline int kgem_bo_size(struct kgem_bo *bo) +{ + if (bo->proxy) + return __kgem_buffer_size(bo); + else + return __kgem_bo_size(bo); +} + +/* +static inline bool kgem_bo_blt_pitch_is_ok(struct kgem *kgem, + struct kgem_bo *bo) +{ + int pitch = bo->pitch; + if (kgem->gen >= 040 && bo->tiling) + pitch /= 4; + if (pitch > MAXSHORT) { + DBG(("%s: can not blt to handle=%d, adjusted pitch=%d\n", + __FUNCTION__, bo->handle, pitch)); + return false; + } + + return true; +} + +static inline bool kgem_bo_can_blt(struct kgem *kgem, + struct kgem_bo *bo) +{ + if (bo->tiling == I915_TILING_Y) { + DBG(("%s: can not blt to handle=%d, tiling=Y\n", + __FUNCTION__, bo->handle)); + return false; + } + + return kgem_bo_blt_pitch_is_ok(kgem, bo); +} +*/ + +static inline bool __kgem_bo_is_mappable(struct kgem *kgem, + struct kgem_bo *bo) +{ + if (bo->domain == DOMAIN_GTT) + return true; + + if (kgem->gen < 040 && bo->tiling && + bo->presumed_offset & (kgem_bo_fenced_size(kgem, bo) - 1)) + return false; + + if (!bo->presumed_offset) + return kgem_bo_size(bo) <= kgem->aperture_mappable / 4; + + return bo->presumed_offset + kgem_bo_size(bo) <= kgem->aperture_mappable; +} + +static inline bool kgem_bo_is_mappable(struct kgem *kgem, + struct kgem_bo *bo) +{ + DBG(("%s: domain=%d, offset: %d size: %d\n", + __FUNCTION__, bo->domain, bo->presumed_offset, kgem_bo_size(bo))); + assert(bo->refcnt); + return __kgem_bo_is_mappable(kgem, bo); +} + +static inline bool kgem_bo_mapped(struct kgem *kgem, struct kgem_bo *bo) +{ + DBG(("%s: map=%p, tiling=%d, domain=%d\n", + __FUNCTION__, bo->map, bo->tiling, bo->domain)); + assert(bo->refcnt); + + if (bo->map == NULL) + return bo->tiling == I915_TILING_NONE && bo->domain == DOMAIN_CPU; + + return IS_CPU_MAP(bo->map) == !bo->tiling; +} + +static inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo) +{ + if (kgem_bo_mapped(kgem, bo)) + return true; + + if (!bo->tiling && kgem->has_llc) + return true; + + if (kgem->gen == 021 && bo->tiling == I915_TILING_Y) + return false; + + return kgem_bo_size(bo) <= kgem->aperture_mappable / 4; +} + +static inline bool kgem_bo_is_snoop(struct kgem_bo *bo) +{ + assert(bo->refcnt); + while (bo->proxy) + bo = bo->proxy; + return bo->snoop; +} + +bool __kgem_busy(struct kgem *kgem, int handle); + +static inline void kgem_bo_mark_busy(struct kgem_bo *bo, int ring) +{ + bo->rq = (struct kgem_request *)((uintptr_t)bo->rq | ring); +} + +inline static void __kgem_bo_clear_busy(struct kgem_bo *bo) +{ + bo->needs_flush = false; + list_del(&bo->request); + bo->rq = NULL; + bo->domain = DOMAIN_NONE; +} + +static inline bool kgem_bo_is_busy(struct kgem_bo *bo) +{ + DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, + bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL)); + assert(bo->refcnt); + return bo->rq; +} + +/* + +static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo) +{ + DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, + bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL)); + assert(bo->refcnt); + + if (bo->exec) + return true; + + if (kgem_flush(kgem, bo->flush)) + kgem_submit(kgem); + + if (bo->rq && !__kgem_busy(kgem, bo->handle)) + __kgem_bo_clear_busy(bo); + + return kgem_bo_is_busy(bo); +} + +*/ + +static inline bool kgem_bo_is_dirty(struct kgem_bo *bo) +{ + if (bo == NULL) + return false; + + assert(bo->refcnt); + return bo->dirty; +} + +static inline void kgem_bo_unclean(struct kgem *kgem, struct kgem_bo *bo) +{ + /* The bo is outside of our control, so presume it is written to */ + bo->needs_flush = true; + if (bo->rq == NULL) + bo->rq = (void *)kgem; + + if (bo->domain != DOMAIN_GPU) + bo->domain = DOMAIN_NONE; +} + +static inline void __kgem_bo_mark_dirty(struct kgem_bo *bo) +{ + DBG(("%s: handle=%d (proxy? %d)\n", __FUNCTION__, + bo->handle, bo->proxy != NULL)); + + bo->exec->flags |= LOCAL_EXEC_OBJECT_WRITE; + bo->needs_flush = bo->dirty = true; + list_move(&bo->request, &RQ(bo->rq)->buffers); +} + +static inline void kgem_bo_mark_dirty(struct kgem_bo *bo) +{ + assert(bo->refcnt); + do { + assert(bo->exec); + assert(bo->rq); + + if (bo->dirty) + return; + + __kgem_bo_mark_dirty(bo); + } while ((bo = bo->proxy)); +} + +#define KGEM_BUFFER_WRITE 0x1 +#define KGEM_BUFFER_INPLACE 0x2 +#define KGEM_BUFFER_LAST 0x4 + +#define KGEM_BUFFER_WRITE_INPLACE (KGEM_BUFFER_WRITE | KGEM_BUFFER_INPLACE) + +struct kgem_bo *kgem_create_buffer(struct kgem *kgem, + uint32_t size, uint32_t flags, + void **ret); +struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem, + int width, int height, int bpp, + uint32_t flags, + void **ret); +bool kgem_buffer_is_inplace(struct kgem_bo *bo); +void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo); + +void kgem_throttle(struct kgem *kgem); +#define MAX_INACTIVE_TIME 10 +bool kgem_expire_cache(struct kgem *kgem); +void kgem_purge_cache(struct kgem *kgem); +void kgem_cleanup_cache(struct kgem *kgem); + +#if HAS_DEBUG_FULL +void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch); +#else +static inline void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) +{ + (void)kgem; + (void)nbatch; +} +#endif + +#endif /* KGEM_H */ diff --git a/drivers/video/Intel-2D/kgem_debug.c b/drivers/video/Intel-2D/kgem_debug.c new file mode 100644 index 0000000000..91769fbd75 --- /dev/null +++ b/drivers/video/Intel-2D/kgem_debug.c @@ -0,0 +1,451 @@ +/* + * Copyright © 2007-2011 Intel 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. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +//#include +#include + +#include "sna.h" +#include "sna_reg.h" + +#include "kgem_debug.h" + +#include + +/* +void +ErrorF(const char *f, ...) +{ + va_list args; + + va_start(args, f); + VErrorF(f, args); + va_end(args); +} +*/ + +#define ErrorF printf + +struct drm_i915_gem_relocation_entry * +kgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset) +{ + int i; + + offset *= sizeof(uint32_t); + + for (i = 0; i < kgem->nreloc; i++) + if (kgem->reloc[i].offset == offset) + return kgem->reloc+i; + + assert(!"valid relocation entry, unknown batch offset"); + return NULL; +} + +struct kgem_bo * +kgem_debug_get_bo_for_reloc_entry(struct kgem *kgem, + struct drm_i915_gem_relocation_entry *reloc) +{ + struct kgem_bo *bo; + + if (reloc == NULL) + return NULL; + + list_for_each_entry(bo, &kgem->next_request->buffers, request) + if (bo->target_handle == reloc->target_handle && bo->proxy == NULL) + break; + + assert(&bo->request != &kgem->next_request->buffers); + + return bo; +} + +static int kgem_debug_handle_is_fenced(struct kgem *kgem, uint32_t handle) +{ + int i; + + if (kgem->has_handle_lut) + return kgem->exec[handle].flags & EXEC_OBJECT_NEEDS_FENCE; + + for (i = 0; i < kgem->nexec; i++) + if (kgem->exec[i].handle == handle) + return kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE; + + return 0; +} + +static int kgem_debug_handle_tiling(struct kgem *kgem, uint32_t handle) +{ + struct kgem_bo *bo; + + list_for_each_entry(bo, &kgem->next_request->buffers, request) + if (bo->target_handle == handle) + return bo->tiling; + + return 0; +} + +void +kgem_debug_print(const uint32_t *data, + uint32_t offset, unsigned int index, + const char *fmt, ...) +{ + va_list va; + char buf[240]; + int len; + + len = snprintf(buf, sizeof(buf), + "0x%08x: 0x%08x: %s", + (offset + index) * 4, + data[index], + index == 0 ? "" : " "); + + va_start(va, fmt); + vsnprintf(buf + len, sizeof(buf) - len, fmt, va); + va_end(va); + + ErrorF("%s", buf); + delay(1); +} + +static int +decode_nop(struct kgem *kgem, uint32_t offset) +{ + uint32_t *data = kgem->batch + offset; + kgem_debug_print(data, offset, 0, "UNKNOWN\n"); + assert(0); + return 1; +} + +static int +decode_mi(struct kgem *kgem, uint32_t offset) +{ + static const struct { + uint32_t opcode; + int len_mask; + int min_len; + int max_len; + const char *name; + } opcodes[] = { + { 0x08, 0, 1, 1, "MI_ARB_ON_OFF" }, + { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" }, + { 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" }, + { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" }, + { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" }, + { 0x04, 0, 1, 1, "MI_FLUSH" }, + { 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" }, + { 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" }, + { 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" }, + { 0x00, 0, 1, 1, "MI_NOOP" }, + { 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" }, + { 0x07, 0, 1, 1, "MI_REPORT_HEAD" }, + { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" }, + { 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" }, + { 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" }, + { 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" }, + { 0x02, 0, 1, 1, "MI_USER_INTERRUPT" }, + { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" }, + { 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" }, + { 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" }, + { 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH" }, + }; + uint32_t *data = kgem->batch + offset; + int op; + + for (op = 0; op < ARRAY_SIZE(opcodes); op++) { + if ((data[0] & 0x1f800000) >> 23 == opcodes[op].opcode) { + unsigned int len = 1, i; + + kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); + if (opcodes[op].max_len > 1) { + len = (data[0] & opcodes[op].len_mask) + 2; + if (len < opcodes[op].min_len || + len > opcodes[op].max_len) + { + ErrorF("Bad length (%d) in %s, [%d, %d]\n", + len, opcodes[op].name, + opcodes[op].min_len, + opcodes[op].max_len); + assert(0); + } + } + + for (i = 1; i < len; i++) + kgem_debug_print(data, offset, i, "dword %d\n", i); + + return len; + } + } + + kgem_debug_print(data, offset, 0, "MI UNKNOWN\n"); + assert(0); + return 1; +} + +static int +decode_2d(struct kgem *kgem, uint32_t offset) +{ + static const struct { + uint32_t opcode; + int min_len; + int max_len; + const char *name; + } opcodes[] = { + { 0x40, 5, 5, "COLOR_BLT" }, + { 0x43, 6, 6, "SRC_COPY_BLT" }, + { 0x01, 8, 8, "XY_SETUP_BLT" }, + { 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" }, + { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, + { 0x24, 2, 2, "XY_PIXEL_BLT" }, + { 0x25, 3, 3, "XY_SCANLINES_BLT" }, + { 0x26, 4, 4, "Y_TEXT_BLT" }, + { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, + { 0x50, 6, 6, "XY_COLOR_BLT" }, + { 0x51, 6, 6, "XY_PAT_BLT" }, + { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, + { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, + { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, + { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, + { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, + { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, + { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, + { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, + { 0x55, 9, 9, "XY_FULL_BLT" }, + { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, + { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, + { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, + { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, + { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, + }; + + unsigned int op, len; + const char *format = NULL; + uint32_t *data = kgem->batch + offset; + struct drm_i915_gem_relocation_entry *reloc; + + /* Special case the two most common ops that we detail in full */ + switch ((data[0] & 0x1fc00000) >> 22) { + case 0x50: + kgem_debug_print(data, offset, 0, + "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", + (data[0] & (1 << 20)) ? "en" : "dis", + (data[0] & (1 << 21)) ? "en" : "dis", + (data[0] >> 11) & 1); + + len = (data[0] & 0x000000ff) + 2; + assert(len == 6); + + switch ((data[1] >> 24) & 0x3) { + case 0: + format="8"; + break; + case 1: + format="565"; + break; + case 2: + format="1555"; + break; + case 3: + format="8888"; + break; + } + + kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " + "clipping %sabled\n", format, + (data[1] >> 16) & 0xff, + (short)(data[1] & 0xffff), + data[1] & (1 << 30) ? "en" : "dis"); + kgem_debug_print(data, offset, 2, "(%d,%d)\n", + data[2] & 0xffff, data[2] >> 16); + kgem_debug_print(data, offset, 3, "(%d,%d)\n", + data[3] & 0xffff, data[3] >> 16); + reloc = kgem_debug_get_reloc_entry(kgem, offset+4); + kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", + data[4], + reloc->target_handle, reloc->delta, + reloc->read_domains, reloc->write_domain, + kgem_debug_handle_is_fenced(kgem, reloc->target_handle), + kgem_debug_handle_tiling(kgem, reloc->target_handle)); + kgem_debug_print(data, offset, 5, "color\n"); + assert(kgem->gen >= 040 || + kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); + return len; + + case 0x53: + kgem_debug_print(data, offset, 0, + "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " + "src tile %d, dst tile %d)\n", + (data[0] & (1 << 20)) ? "en" : "dis", + (data[0] & (1 << 21)) ? "en" : "dis", + (data[0] >> 15) & 1, + (data[0] >> 11) & 1); + + len = (data[0] & 0x000000ff) + 2; + assert(len == 8); + + switch ((data[1] >> 24) & 0x3) { + case 0: + format="8"; + break; + case 1: + format="565"; + break; + case 2: + format="1555"; + break; + case 3: + format="8888"; + break; + } + + kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " + "clipping %sabled\n", format, + (data[1] >> 16) & 0xff, + (short)(data[1] & 0xffff), + data[1] & (1 << 30) ? "en" : "dis"); + kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", + data[2] & 0xffff, data[2] >> 16); + kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", + data[3] & 0xffff, data[3] >> 16); + reloc = kgem_debug_get_reloc_entry(kgem, offset+4); + assert(reloc); + kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", + data[4], + reloc->target_handle, reloc->delta, + reloc->read_domains, reloc->write_domain, + kgem_debug_handle_is_fenced(kgem, reloc->target_handle), + kgem_debug_handle_tiling(kgem, reloc->target_handle)); + assert(kgem->gen >= 040 || + kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); + + kgem_debug_print(data, offset, 5, "src (%d,%d)\n", + data[5] & 0xffff, data[5] >> 16); + kgem_debug_print(data, offset, 6, "src pitch %d\n", + (short)(data[6] & 0xffff)); + reloc = kgem_debug_get_reloc_entry(kgem, offset+7); + assert(reloc); + kgem_debug_print(data, offset, 7, "src offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", + data[7], + reloc->target_handle, reloc->delta, + reloc->read_domains, reloc->write_domain, + kgem_debug_handle_is_fenced(kgem, reloc->target_handle), + kgem_debug_handle_tiling(kgem, reloc->target_handle)); + assert(kgem->gen >= 040 || + kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); + + return len; + } + + for (op = 0; op < ARRAY_SIZE(opcodes); op++) { + if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { + unsigned int i; + + len = 1; + kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); + if (opcodes[op].max_len > 1) { + len = (data[0] & 0x000000ff) + 2; + assert(len >= opcodes[op].min_len && + len <= opcodes[op].max_len); + } + + for (i = 1; i < len; i++) + kgem_debug_print(data, offset, i, "dword %d\n", i); + + return len; + } + } + + kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); + assert(0); + return 1; +} + +static int (*decode_3d(int gen))(struct kgem*, uint32_t) +{ + return kgem_gen6_decode_3d; +/* + if (gen >= 0100) { + } else if (gen >= 070) { + return kgem_gen7_decode_3d; + } else if (gen >= 060) { + return kgem_gen6_decode_3d; + } else if (gen >= 050) { + return kgem_gen5_decode_3d; + } else if (gen >= 040) { + return kgem_gen4_decode_3d; + } else if (gen >= 030) { + return kgem_gen3_decode_3d; + } else if (gen >= 020) { + return kgem_gen2_decode_3d; + } + assert(0); +*/ +} + +static void (*finish_state(int gen))(struct kgem*) +{ + + return kgem_gen6_finish_state; +/* + if (gen >= 0100) { + } else if (gen >= 070) { + return kgem_gen7_finish_state; + } else if (gen >= 060) { + return kgem_gen6_finish_state; + } else if (gen >= 050) { + return kgem_gen5_finish_state; + } else if (gen >= 040) { + return kgem_gen4_finish_state; + } else if (gen >= 030) { + return kgem_gen3_finish_state; + } else if (gen >= 020) { + return kgem_gen2_finish_state; + } + assert(0); +*/ +} + +void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) +{ + int (*const decode[])(struct kgem *, uint32_t) = { + decode_mi, + decode_nop, + decode_2d, + decode_3d(kgem->gen), + }; + uint32_t offset = 0; + + while (offset < nbatch) { + int class = (kgem->batch[offset] & 0xe0000000) >> 29; + assert(class < ARRAY_SIZE(decode)); + offset += decode[class](kgem, offset); + } + + finish_state(kgem->gen)(kgem); +} diff --git a/drivers/video/Intel-2D/kgem_debug.h b/drivers/video/Intel-2D/kgem_debug.h new file mode 100644 index 0000000000..747772a656 --- /dev/null +++ b/drivers/video/Intel-2D/kgem_debug.h @@ -0,0 +1,34 @@ +#ifndef KGEM_DEBUG_H +#define KGEM_DEBUG_H + +void +kgem_debug_print(const uint32_t *data, + uint32_t offset, unsigned int index, + const char *fmt, ...); + +struct drm_i915_gem_relocation_entry * +kgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset); + +struct kgem_bo * +kgem_debug_get_bo_for_reloc_entry(struct kgem *kgem, + struct drm_i915_gem_relocation_entry *reloc); + +int kgem_gen7_decode_3d(struct kgem *kgem, uint32_t offset); +void kgem_gen7_finish_state(struct kgem *kgem); + +int kgem_gen6_decode_3d(struct kgem *kgem, uint32_t offset); +void kgem_gen6_finish_state(struct kgem *kgem); + +int kgem_gen5_decode_3d(struct kgem *kgem, uint32_t offset); +void kgem_gen5_finish_state(struct kgem *kgem); + +int kgem_gen4_decode_3d(struct kgem *kgem, uint32_t offset); +void kgem_gen4_finish_state(struct kgem *kgem); + +int kgem_gen3_decode_3d(struct kgem *kgem, uint32_t offset); +void kgem_gen3_finish_state(struct kgem *kgem); + +int kgem_gen2_decode_3d(struct kgem *kgem, uint32_t offset); +void kgem_gen2_finish_state(struct kgem *kgem); + +#endif diff --git a/drivers/video/Intel-2D/kgem_debug_gen6.c b/drivers/video/Intel-2D/kgem_debug_gen6.c new file mode 100644 index 0000000000..7ab00f5db6 --- /dev/null +++ b/drivers/video/Intel-2D/kgem_debug_gen6.c @@ -0,0 +1,1077 @@ +/* + * Copyright © 2007-2011 Intel 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. + * + * Authors: + * Eric Anholt + * Chris Wilson + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +//#include +#include + +#include "sna.h" +#include "sna_reg.h" +#include "gen6_render.h" + +#include "kgem_debug.h" + +#define ErrorF printf + +static struct state { + struct vertex_buffer { + int handle; + const char *ptr; + int pitch; + + struct kgem_bo *current; + } vb[33]; + struct vertex_elements { + int buffer; + int offset; + bool valid; + uint32_t type; + uint8_t swizzle[4]; + } ve[33]; + int num_ve; + + struct dynamic_state { + struct kgem_bo *current; + void *base, *ptr; + } dynamic_state; +} state; + +static void gen6_update_vertex_buffer(struct kgem *kgem, const uint32_t *data) +{ + uint32_t reloc = sizeof(uint32_t) * (&data[1] - kgem->batch); + struct kgem_bo *bo = NULL; + void *base; + int i; + + for (i = 0; i < kgem->nreloc; i++) + if (kgem->reloc[i].offset == reloc) + break; + assert(i < kgem->nreloc); + reloc = kgem->reloc[i].target_handle; + + if (reloc == -1) { + base = kgem->batch; + } else { + list_for_each_entry(bo, &kgem->next_request->buffers, request) + if (bo->target_handle == reloc) + break; + assert(&bo->request != &kgem->next_request->buffers); + base = kgem_bo_map__debug(kgem, bo); + } + + base = (char *)base + kgem->reloc[i].delta; + i = data[0] >> 26; + + state.vb[i].current = bo; + state.vb[i].ptr = base; + state.vb[i].pitch = data[0] & 0x7ff; +} + +static void gen6_update_dynamic_buffer(struct kgem *kgem, const uint32_t offset) +{ + uint32_t reloc = sizeof(uint32_t) * offset; + struct kgem_bo *bo = NULL; + void *base, *ptr; + int i; + + if ((kgem->batch[offset] & 1) == 0) + return; + + for (i = 0; i < kgem->nreloc; i++) + if (kgem->reloc[i].offset == reloc) + break; + if(i < kgem->nreloc) { + reloc = kgem->reloc[i].target_handle; + + if (reloc == 0) { + base = kgem->batch; + } else { + list_for_each_entry(bo, &kgem->next_request->buffers, request) + if (bo->handle == reloc) + break; + assert(&bo->request != &kgem->next_request->buffers); + base = kgem_bo_map__debug(kgem, bo); + } + ptr = (char *)base + (kgem->reloc[i].delta & ~1); + } else { + bo = NULL; + base = NULL; + ptr = NULL; + } + + state.dynamic_state.current = bo; + state.dynamic_state.base = base; + state.dynamic_state.ptr = ptr; +} + +static uint32_t +get_ve_component(uint32_t data, int component) +{ + return (data >> (16 + (3 - component) * 4)) & 0x7; +} + +static void gen6_update_vertex_elements(struct kgem *kgem, int id, const uint32_t *data) +{ + state.ve[id].buffer = data[0] >> 26; + state.ve[id].valid = !!(data[0] & (1 << 25)); + state.ve[id].type = (data[0] >> 16) & 0x1ff; + state.ve[id].offset = data[0] & 0x7ff; + state.ve[id].swizzle[0] = get_ve_component(data[1], 0); + state.ve[id].swizzle[1] = get_ve_component(data[1], 1); + state.ve[id].swizzle[2] = get_ve_component(data[1], 2); + state.ve[id].swizzle[3] = get_ve_component(data[1], 3); +} + +static void gen6_update_sf_state(struct kgem *kgem, uint32_t *data) +{ + state.num_ve = 1 + ((data[1] >> 22) & 0x3f); +} + +static void vertices_sint16_out(const struct vertex_elements *ve, const int16_t *v, int max) +{ + int c; + + ErrorF("("); + for (c = 0; c < max; c++) { + switch (ve->swizzle[c]) { + case 0: ErrorF("#"); break; + case 1: ErrorF("%d", v[c]); break; + case 2: ErrorF("0.0"); break; + case 3: ErrorF("1.0"); break; + case 4: ErrorF("0x1"); break; + case 5: break; + default: ErrorF("?"); + } + if (c < 3) + ErrorF(", "); + } + for (; c < 4; c++) { + switch (ve->swizzle[c]) { + case 0: ErrorF("#"); break; + case 1: ErrorF("1.0"); break; + case 2: ErrorF("0.0"); break; + case 3: ErrorF("1.0"); break; + case 4: ErrorF("0x1"); break; + case 5: break; + default: ErrorF("?"); + } + if (c < 3) + ErrorF(", "); + } + ErrorF(")"); +} + +static void vertices_float_out(const struct vertex_elements *ve, const float *f, int max) +{ + int c, o; + + ErrorF("("); + for (c = o = 0; c < 4 && o < max; c++) { + switch (ve->swizzle[c]) { + case 0: ErrorF("#"); break; + case 1: ErrorF("%f", f[o++]); break; + case 2: ErrorF("0.0"); break; + case 3: ErrorF("1.0"); break; + case 4: ErrorF("0x1"); break; + case 5: break; + default: ErrorF("?"); + } + if (c < 3) + ErrorF(", "); + } + for (; c < 4; c++) { + switch (ve->swizzle[c]) { + case 0: ErrorF("#"); break; + case 1: ErrorF("1.0"); break; + case 2: ErrorF("0.0"); break; + case 3: ErrorF("1.0"); break; + case 4: ErrorF("0x1"); break; + case 5: break; + default: ErrorF("?"); + } + if (c < 3) + ErrorF(", "); + } + ErrorF(")"); +} + +static void ve_out(const struct vertex_elements *ve, const void *ptr) +{ + switch (ve->type) { + case GEN6_SURFACEFORMAT_R32_FLOAT: + vertices_float_out(ve, ptr, 1); + break; + case GEN6_SURFACEFORMAT_R32G32_FLOAT: + vertices_float_out(ve, ptr, 2); + break; + case GEN6_SURFACEFORMAT_R32G32B32_FLOAT: + vertices_float_out(ve, ptr, 3); + break; + case GEN6_SURFACEFORMAT_R32G32B32A32_FLOAT: + vertices_float_out(ve, ptr, 4); + break; + case GEN6_SURFACEFORMAT_R16_SINT: + vertices_sint16_out(ve, ptr, 1); + break; + case GEN6_SURFACEFORMAT_R16G16_SINT: + vertices_sint16_out(ve, ptr, 2); + break; + case GEN6_SURFACEFORMAT_R16G16B16A16_SINT: + vertices_sint16_out(ve, ptr, 4); + break; + case GEN6_SURFACEFORMAT_R16_SSCALED: + vertices_sint16_out(ve, ptr, 1); + break; + case GEN6_SURFACEFORMAT_R16G16_SSCALED: + vertices_sint16_out(ve, ptr, 2); + break; + case GEN6_SURFACEFORMAT_R16G16B16A16_SSCALED: + vertices_sint16_out(ve, ptr, 4); + break; + } +} + +static void indirect_vertex_out(struct kgem *kgem, uint32_t v) +{ + int i = 1; + + do { + const struct vertex_elements *ve = &state.ve[i]; + const struct vertex_buffer *vb = &state.vb[ve->buffer]; + const void *ptr = vb->ptr + v * vb->pitch + ve->offset; + + if (ve->valid) + ve_out(ve, ptr); + + while (++i <= state.num_ve && !state.ve[i].valid) + ; + + if (i <= state.num_ve) + ErrorF(", "); + } while (i <= state.num_ve); +} + +static void primitive_out(struct kgem *kgem, uint32_t *data) +{ + int n; + + assert((data[0] & (1<<15)) == 0); /* XXX index buffers */ + + for (n = 0; n < data[1]; n++) { + int v = data[2] + n; + ErrorF(" [%d:%d] = ", n, v); + indirect_vertex_out(kgem, v); + ErrorF("\n"); + } +} + +static void finish_state(struct kgem *kgem) +{ + memset(&state, 0, sizeof(state)); +} + +static void +state_base_out(uint32_t *data, uint32_t offset, unsigned int index, + const char *name) +{ + if (data[index] & 1) + kgem_debug_print(data, offset, index, + "%s state base address 0x%08x\n", + name, data[index] & ~1); + else + kgem_debug_print(data, offset, index, + "%s state base not updated\n", + name); +} + +static void +state_max_out(uint32_t *data, uint32_t offset, unsigned int index, + const char *name) +{ + if (data[index] == 1) + kgem_debug_print(data, offset, index, + "%s state upper bound disabled\n", name); + else if (data[index] & 1) + kgem_debug_print(data, offset, index, + "%s state upper bound 0x%08x\n", + name, data[index] & ~1); + else + kgem_debug_print(data, offset, index, + "%s state upper bound not updated\n", + name); +} + +static const char * +get_965_surfacetype(unsigned int surfacetype) +{ + switch (surfacetype) { + case 0: return "1D"; + case 1: return "2D"; + case 2: return "3D"; + case 3: return "CUBE"; + case 4: return "BUFFER"; + case 7: return "NULL"; + default: return "unknown"; + } +} + +static const char * +get_965_depthformat(unsigned int depthformat) +{ + switch (depthformat) { + case 0: return "s8_z24float"; + case 1: return "z32float"; + case 2: return "z24s8"; + case 5: return "z16"; + default: return "unknown"; + } +} + +static const char * +get_965_element_component(uint32_t data, int component) +{ + uint32_t component_control = (data >> (16 + (3 - component) * 4)) & 0x7; + + switch (component_control) { + case 0: + return "nostore"; + case 1: + switch (component) { + case 0: return "X"; + case 1: return "Y"; + case 2: return "Z"; + case 3: return "W"; + default: return "fail"; + } + case 2: + return "0.0"; + case 3: + return "1.0"; + case 4: + return "0x1"; + case 5: + return "VID"; + default: + return "fail"; + } +} + +static const char * +get_965_prim_type(uint32_t data) +{ + uint32_t primtype = (data >> 10) & 0x1f; + + switch (primtype) { + case 0x01: return "point list"; + case 0x02: return "line list"; + case 0x03: return "line strip"; + case 0x04: return "tri list"; + case 0x05: return "tri strip"; + case 0x06: return "tri fan"; + case 0x07: return "quad list"; + case 0x08: return "quad strip"; + case 0x09: return "line list adj"; + case 0x0a: return "line strip adj"; + case 0x0b: return "tri list adj"; + case 0x0c: return "tri strip adj"; + case 0x0d: return "tri strip reverse"; + case 0x0e: return "polygon"; + case 0x0f: return "rect list"; + case 0x10: return "line loop"; + case 0x11: return "point list bf"; + case 0x12: return "line strip cont"; + case 0x13: return "line strip bf"; + case 0x14: return "line strip cont bf"; + case 0x15: return "tri fan no stipple"; + default: return "fail"; + } +} + +struct reloc { + struct kgem_bo *bo; + void *base; +}; + +static void * +get_reloc(struct kgem *kgem, + void *base, const uint32_t *reloc, + struct reloc *r) +{ + uint32_t delta = *reloc; + + memset(r, 0, sizeof(*r)); + + if (base == 0) { + uint32_t handle = sizeof(uint32_t) * (reloc - kgem->batch); + struct kgem_bo *bo = NULL; + int i; + + for (i = 0; i < kgem->nreloc; i++) + if (kgem->reloc[i].offset == handle) + break; + assert(i < kgem->nreloc); + handle = kgem->reloc[i].target_handle; + delta = kgem->reloc[i].delta; + + if (handle == 0) { + base = kgem->batch; + } else { + list_for_each_entry(bo, &kgem->next_request->buffers, request) + if (bo->handle == handle) + break; + assert(&bo->request != &kgem->next_request->buffers); + base = kgem_bo_map__debug(kgem, bo); + r->bo = bo; + r->base = base; + } + } + + return (char *)base + (delta & ~3); +} + +static const char * +gen6_filter_to_string(uint32_t filter) +{ + switch (filter) { + default: + case GEN6_MAPFILTER_NEAREST: return "nearest"; + case GEN6_MAPFILTER_LINEAR: return "linear"; + } +} + +static const char * +gen6_repeat_to_string(uint32_t repeat) +{ + switch (repeat) { + default: + case GEN6_TEXCOORDMODE_CLAMP_BORDER: return "border"; + case GEN6_TEXCOORDMODE_WRAP: return "wrap"; + case GEN6_TEXCOORDMODE_CLAMP: return "clamp"; + case GEN6_TEXCOORDMODE_MIRROR: return "mirror"; + } +} + +static void +gen6_decode_sampler_state(struct kgem *kgem, const uint32_t *reloc) +{ + const struct gen6_sampler_state *ss; + struct reloc r; + const char *min, *mag; + const char *s_wrap, *t_wrap, *r_wrap; + + ss = get_reloc(kgem, state.dynamic_state.ptr, reloc, &r); + + min = gen6_filter_to_string(ss->ss0.min_filter); + mag = gen6_filter_to_string(ss->ss0.mag_filter); + + s_wrap = gen6_repeat_to_string(ss->ss1.s_wrap_mode); + t_wrap = gen6_repeat_to_string(ss->ss1.t_wrap_mode); + r_wrap = gen6_repeat_to_string(ss->ss1.r_wrap_mode); + + ErrorF(" Sampler 0:\n"); + ErrorF(" filter: min=%s, mag=%s\n", min, mag); + ErrorF(" wrap: s=%s, t=%s, r=%s\n", s_wrap, t_wrap, r_wrap); + + ss++; + min = gen6_filter_to_string(ss->ss0.min_filter); + mag = gen6_filter_to_string(ss->ss0.mag_filter); + + s_wrap = gen6_repeat_to_string(ss->ss1.s_wrap_mode); + t_wrap = gen6_repeat_to_string(ss->ss1.t_wrap_mode); + r_wrap = gen6_repeat_to_string(ss->ss1.r_wrap_mode); + + ErrorF(" Sampler 1:\n"); + ErrorF(" filter: min=%s, mag=%s\n", min, mag); + ErrorF(" wrap: s=%s, t=%s, r=%s\n", s_wrap, t_wrap, r_wrap); +} + +static const char * +gen6_blend_factor_to_string(uint32_t v) +{ + switch (v) { +#define C(x) case GEN6_BLENDFACTOR_##x: return #x; + C(ONE); + C(SRC_COLOR); + C(SRC_ALPHA); + C(DST_ALPHA); + C(DST_COLOR); + C(SRC_ALPHA_SATURATE); + C(CONST_COLOR); + C(CONST_ALPHA); + C(SRC1_COLOR); + C(SRC1_ALPHA); + C(ZERO); + C(INV_SRC_COLOR); + C(INV_SRC_ALPHA); + C(INV_DST_ALPHA); + C(INV_DST_COLOR); + C(INV_CONST_COLOR); + C(INV_CONST_ALPHA); + C(INV_SRC1_COLOR); + C(INV_SRC1_ALPHA); +#undef C + default: return "???"; + } +} + +static const char * +gen6_blend_function_to_string(uint32_t v) +{ + switch (v) { +#define C(x) case GEN6_BLENDFUNCTION_##x: return #x; + C(ADD); + C(SUBTRACT); + C(REVERSE_SUBTRACT); + C(MIN); + C(MAX); +#undef C + default: return "???"; + } +} + +static float unpack_float(uint32_t dw) +{ + union { + float f; + uint32_t dw; + } u; + u.dw = dw; + return u.f; +} + +static void +gen6_decode_blend(struct kgem *kgem, const uint32_t *reloc) +{ + const struct gen6_blend_state *blend; + struct reloc r; + const char *dst, *src; + const char *func; + + blend = get_reloc(kgem, state.dynamic_state.ptr, reloc, &r); + + dst = gen6_blend_factor_to_string(blend->blend0.dest_blend_factor); + src = gen6_blend_factor_to_string(blend->blend0.source_blend_factor); + func = gen6_blend_function_to_string(blend->blend0.blend_func); + + ErrorF(" Blend (%s): function %s, src=%s, dst=%s\n", + blend->blend0.blend_enable ? "enabled" : "disabled", + func, src, dst); +} + +int kgem_gen6_decode_3d(struct kgem *kgem, uint32_t offset) +{ + static const struct { + uint32_t opcode; + int min_len; + int max_len; + const char *name; + } opcodes[] = { + { 0x6101, 6, 6, "STATE_BASE_ADDRESS" }, + { 0x6102, 2, 2 , "STATE_SIP" }, + { 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" }, + { 0x680b, 1, 1, "3DSTATE_VF_STATISTICS" }, + { 0x6904, 1, 1, "3DSTATE_PIPELINE_SELECT" }, + { 0x7800, 7, 7, "3DSTATE_PIPELINED_POINTERS" }, + { 0x7801, 6, 6, "3DSTATE_BINDING_TABLE_POINTERS" }, + { 0x7808, 5, 257, "3DSTATE_VERTEX_BUFFERS" }, + { 0x7809, 3, 256, "3DSTATE_VERTEX_ELEMENTS" }, + { 0x780a, 3, 3, "3DSTATE_INDEX_BUFFER" }, + { 0x780b, 1, 1, "3DSTATE_VF_STATISTICS" }, + { 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" }, + { 0x7901, 5, 5, "3DSTATE_CONSTANT_COLOR" }, + { 0x7905, 5, 7, "3DSTATE_DEPTH_BUFFER" }, + { 0x7906, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" }, + { 0x7907, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" }, + { 0x7908, 3, 3, "3DSTATE_LINE_STIPPLE" }, + { 0x7909, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" }, + { 0x7909, 2, 2, "3DSTATE_CLEAR_PARAMS" }, + { 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" }, + { 0x790b, 4, 4, "3DSTATE_GS_SVB_INDEX" }, + { 0x790d, 3, 3, "3DSTATE_MULTISAMPLE" }, + { 0x7910, 2, 2, "3DSTATE_CLEAR_PARAMS" }, + { 0x7b00, 6, 6, "3DPRIMITIVE" }, + { 0x7802, 4, 4, "3DSTATE_SAMPLER_STATE_POINTERS" }, + { 0x7805, 3, 3, "3DSTATE_URB" }, + { 0x780d, 4, 4, "3DSTATE_VIEWPORT_STATE_POINTERS" }, + { 0x780e, 4, 4, "3DSTATE_CC_STATE_POINTERS" }, + { 0x780f, 2, 2, "3DSTATE_SCISSOR_STATE_POINTERS" }, + { 0x7810, 6, 6, "3DSTATE_VS_STATE" }, + { 0x7811, 7, 7, "3DSTATE_GS_STATE" }, + { 0x7812, 4, 4, "3DSTATE_CLIP_STATE" }, + { 0x7813, 20, 20, "3DSTATE_SF_STATE" }, + { 0x7814, 9, 9, "3DSTATE_WM_STATE" }, + { 0x7815, 5, 5, "3DSTATE_CONSTANT_VS_STATE" }, + { 0x7816, 5, 5, "3DSTATE_CONSTANT_GS_STATE" }, + { 0x7817, 5, 5, "3DSTATE_CONSTANT_WM_STATE" }, + { 0x7818, 2, 2, "3DSTATE_SAMPLE_MASK" }, + }; + uint32_t *data = kgem->batch + offset; + uint32_t op; + unsigned int len; + int i, j; + const char *desc1 = NULL; + + len = (data[0] & 0xff) + 2; + op = (data[0] & 0xffff0000) >> 16; + switch (op) { + case 0x6101: + i = 0; + kgem_debug_print(data, offset, i++, "STATE_BASE_ADDRESS\n"); + if (kgem->gen >= 060) { + assert(len == 10); + + state_base_out(data, offset, i++, "general"); + state_base_out(data, offset, i++, "surface"); + state_base_out(data, offset, i++, "dynamic"); + state_base_out(data, offset, i++, "indirect"); + state_base_out(data, offset, i++, "instruction"); + + state_max_out(data, offset, i++, "general"); + state_max_out(data, offset, i++, "dynamic"); + state_max_out(data, offset, i++, "indirect"); + state_max_out(data, offset, i++, "instruction"); + + gen6_update_dynamic_buffer(kgem, offset + 3); + } else if (kgem->gen >= 050) { + assert(len == 8); + + state_base_out(data, offset, i++, "general"); + state_base_out(data, offset, i++, "surface"); + state_base_out(data, offset, i++, "media"); + state_base_out(data, offset, i++, "instruction"); + + state_max_out(data, offset, i++, "general"); + state_max_out(data, offset, i++, "media"); + state_max_out(data, offset, i++, "instruction"); + } + + return len; + + case 0x7801: + if (kgem->gen >= 060) { + assert(len == 4); + + kgem_debug_print(data, offset, 0, + "3DSTATE_BINDING_TABLE_POINTERS: VS mod %d, " + "GS mod %d, WM mod %d\n", + (data[0] & (1 << 8)) != 0, + (data[0] & (1 << 9)) != 0, + (data[0] & (1 << 12)) != 0); + kgem_debug_print(data, offset, 1, "VS binding table\n"); + kgem_debug_print(data, offset, 2, "GS binding table\n"); + kgem_debug_print(data, offset, 3, "WM binding table\n"); + } else if (kgem->gen >= 040) { + assert(len == 6); + + kgem_debug_print(data, offset, 0, + "3DSTATE_BINDING_TABLE_POINTERS\n"); + kgem_debug_print(data, offset, 1, "VS binding table\n"); + kgem_debug_print(data, offset, 2, "GS binding table\n"); + kgem_debug_print(data, offset, 3, "CLIP binding table\n"); + kgem_debug_print(data, offset, 4, "SF binding table\n"); + kgem_debug_print(data, offset, 5, "WM binding table\n"); + } + + return len; + + case 0x7802: + assert(len == 4); + kgem_debug_print(data, offset, 0, "3DSTATE_SAMPLER_STATE_POINTERS: VS mod %d, " + "GS mod %d, WM mod %d\n", + (data[0] & (1 << 8)) != 0, + (data[0] & (1 << 9)) != 0, + (data[0] & (1 << 12)) != 0); + kgem_debug_print(data, offset, 1, "VS sampler state\n"); + kgem_debug_print(data, offset, 2, "GS sampler state\n"); + kgem_debug_print(data, offset, 3, "WM sampler state\n"); + gen6_decode_sampler_state(kgem, &data[3]); + return len; + + case 0x7808: + assert((len - 1) % 4 == 0); + kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_BUFFERS\n"); + + for (i = 1; i < len;) { + gen6_update_vertex_buffer(kgem, data + i); + + kgem_debug_print(data, offset, i, "buffer %d: %s, pitch %db\n", + data[i] >> 26, + data[i] & (1 << 20) ? "random" : "sequential", + data[i] & 0x07ff); + i++; + kgem_debug_print(data, offset, i++, "buffer address\n"); + kgem_debug_print(data, offset, i++, "max index\n"); + kgem_debug_print(data, offset, i++, "mbz\n"); + } + return len; + + case 0x7809: + assert((len + 1) % 2 == 0); + kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_ELEMENTS\n"); + + for (i = 1; i < len;) { + gen6_update_vertex_elements(kgem, (i - 1)/2, data + i); + + kgem_debug_print(data, offset, i, "buffer %d: %svalid, type 0x%04x, " + "src offset 0x%04x bytes\n", + data[i] >> 26, + data[i] & (1 << 25) ? "" : "in", + (data[i] >> 16) & 0x1ff, + data[i] & 0x07ff); + i++; + kgem_debug_print(data, offset, i, "(%s, %s, %s, %s), " + "dst offset 0x%02x bytes\n", + get_965_element_component(data[i], 0), + get_965_element_component(data[i], 1), + get_965_element_component(data[i], 2), + get_965_element_component(data[i], 3), + (data[i] & 0xff) * 4); + i++; + } + return len; + + case 0x780d: + assert(len == 4); + kgem_debug_print(data, offset, 0, "3DSTATE_VIEWPORT_STATE_POINTERS\n"); + kgem_debug_print(data, offset, 1, "clip\n"); + kgem_debug_print(data, offset, 2, "sf\n"); + kgem_debug_print(data, offset, 3, "cc\n"); + return len; + + case 0x780a: + assert(len == 3); + kgem_debug_print(data, offset, 0, "3DSTATE_INDEX_BUFFER\n"); + kgem_debug_print(data, offset, 1, "beginning buffer address\n"); + kgem_debug_print(data, offset, 2, "ending buffer address\n"); + return len; + + case 0x780e: + assert(len == 4); + kgem_debug_print(data, offset, 0, "3DSTATE_CC_STATE_POINTERS\n"); + kgem_debug_print(data, offset, 1, "blend%s\n", + data[1] & 1 ? " update" : ""); + if (data[1] & 1) + gen6_decode_blend(kgem, data+1); + kgem_debug_print(data, offset, 2, "depth+stencil%s\n", + data[2] & 1 ? " update" : ""); + kgem_debug_print(data, offset, 3, "cc%s\n", + data[3] & 1 ? " update" : ""); + return len; + + case 0x780f: + assert(len == 2); + kgem_debug_print(data, offset, 0, "3DSTATE_SCISSOR_POINTERS\n"); + kgem_debug_print(data, offset, 1, "scissor rect offset\n"); + return len; + + case 0x7810: + assert(len == 6); + kgem_debug_print(data, offset, 0, "3DSTATE_VS\n"); + kgem_debug_print(data, offset, 1, "kernel pointer\n"); + kgem_debug_print(data, offset, 2, "SPF=%d, VME=%d, Sampler Count %d, " + "Binding table count %d\n", + (data[2] >> 31) & 1, + (data[2] >> 30) & 1, + (data[2] >> 27) & 7, + (data[2] >> 18) & 0xff); + kgem_debug_print(data, offset, 3, "scratch offset\n"); + kgem_debug_print(data, offset, 4, "Dispatch GRF start %d, VUE read length %d, " + "VUE read offset %d\n", + (data[4] >> 20) & 0x1f, + (data[4] >> 11) & 0x3f, + (data[4] >> 4) & 0x3f); + kgem_debug_print(data, offset, 5, "Max Threads %d, Vertex Cache %sable, " + "VS func %sable\n", + ((data[5] >> 25) & 0x7f) + 1, + (data[5] & (1 << 1)) != 0 ? "dis" : "en", + (data[5] & 1) != 0 ? "en" : "dis"); + return len; + + case 0x7811: + assert(len == 7); + kgem_debug_print(data, offset, 0, "3DSTATE_GS\n"); + kgem_debug_print(data, offset, 1, "kernel pointer\n"); + kgem_debug_print(data, offset, 2, "SPF=%d, VME=%d, Sampler Count %d, " + "Binding table count %d\n", + (data[2] >> 31) & 1, + (data[2] >> 30) & 1, + (data[2] >> 27) & 7, + (data[2] >> 18) & 0xff); + kgem_debug_print(data, offset, 3, "scratch offset\n"); + kgem_debug_print(data, offset, 4, "Dispatch GRF start %d, VUE read length %d, " + "VUE read offset %d\n", + (data[4] & 0xf), + (data[4] >> 11) & 0x3f, + (data[4] >> 4) & 0x3f); + kgem_debug_print(data, offset, 5, "Max Threads %d, Rendering %sable\n", + ((data[5] >> 25) & 0x7f) + 1, + (data[5] & (1 << 8)) != 0 ? "en" : "dis"); + kgem_debug_print(data, offset, 6, "Reorder %sable, Discard Adjaceny %sable, " + "GS %sable\n", + (data[6] & (1 << 30)) != 0 ? "en" : "dis", + (data[6] & (1 << 29)) != 0 ? "en" : "dis", + (data[6] & (1 << 15)) != 0 ? "en" : "dis"); + return len; + + case 0x7812: + assert(len == 4); + kgem_debug_print(data, offset, 0, "3DSTATE_CLIP\n"); + kgem_debug_print(data, offset, 1, "UserClip distance cull test mask 0x%x\n", + data[1] & 0xff); + kgem_debug_print(data, offset, 2, "Clip %sable, API mode %s, Viewport XY test %sable, " + "Viewport Z test %sable, Guardband test %sable, Clip mode %d, " + "Perspective Divide %sable, Non-Perspective Barycentric %sable, " + "Tri Provoking %d, Line Provoking %d, Trifan Provoking %d\n", + (data[2] & (1 << 31)) != 0 ? "en" : "dis", + (data[2] & (1 << 30)) != 0 ? "D3D" : "OGL", + (data[2] & (1 << 28)) != 0 ? "en" : "dis", + (data[2] & (1 << 27)) != 0 ? "en" : "dis", + (data[2] & (1 << 26)) != 0 ? "en" : "dis", + (data[2] >> 13) & 7, + (data[2] & (1 << 9)) != 0 ? "dis" : "en", + (data[2] & (1 << 8)) != 0 ? "en" : "dis", + (data[2] >> 4) & 3, + (data[2] >> 2) & 3, + (data[2] & 3)); + kgem_debug_print(data, offset, 3, "Min PointWidth %d, Max PointWidth %d, " + "Force Zero RTAIndex %sable, Max VPIndex %d\n", + (data[3] >> 17) & 0x7ff, + (data[3] >> 6) & 0x7ff, + (data[3] & (1 << 5)) != 0 ? "en" : "dis", + (data[3] & 0xf)); + return len; + + case 0x7813: + gen6_update_sf_state(kgem, data); + assert(len == 20); + kgem_debug_print(data, offset, 0, "3DSTATE_SF\n"); + kgem_debug_print(data, offset, 1, "Attrib Out %d, Attrib Swizzle %sable, VUE read length %d, " + "VUE read offset %d\n", + (data[1] >> 22) & 0x3f, + (data[1] & (1 << 21)) != 0 ? "en" : "dis", + (data[1] >> 11) & 0x1f, + (data[1] >> 4) & 0x3f); + kgem_debug_print(data, offset, 2, "Legacy Global DepthBias %sable, FrontFace fill %d, BF fill %d, " + "VP transform %sable, FrontWinding_%s\n", + (data[2] & (1 << 11)) != 0 ? "en" : "dis", + (data[2] >> 5) & 3, + (data[2] >> 3) & 3, + (data[2] & (1 << 1)) != 0 ? "en" : "dis", + (data[2] & 1) != 0 ? "CCW" : "CW"); + kgem_debug_print(data, offset, 3, "AA %sable, CullMode %d, Scissor %sable, Multisample m ode %d\n", + (data[3] & (1 << 31)) != 0 ? "en" : "dis", + (data[3] >> 29) & 3, + (data[3] & (1 << 11)) != 0 ? "en" : "dis", + (data[3] >> 8) & 3); + kgem_debug_print(data, offset, 4, "Last Pixel %sable, SubPixel Precision %d, Use PixelWidth %d\n", + (data[4] & (1 << 31)) != 0 ? "en" : "dis", + (data[4] & (1 << 12)) != 0 ? 4 : 8, + (data[4] & (1 << 11)) != 0); + kgem_debug_print(data, offset, 5, "Global Depth Offset Constant %f\n", unpack_float(data[5])); + kgem_debug_print(data, offset, 6, "Global Depth Offset Scale %f\n", unpack_float(data[6])); + kgem_debug_print(data, offset, 7, "Global Depth Offset Clamp %f\n", unpack_float(data[7])); + for (i = 0, j = 0; i < 8; i++, j+=2) + kgem_debug_print(data, offset, i+8, "Attrib %d (Override %s%s%s%s, Const Source %d, Swizzle Select %d, " + "Source %d); Attrib %d (Override %s%s%s%s, Const Source %d, Swizzle Select %d, Source %d)\n", + j+1, + (data[8+i] & (1 << 31)) != 0 ? "W":"", + (data[8+i] & (1 << 30)) != 0 ? "Z":"", + (data[8+i] & (1 << 29)) != 0 ? "Y":"", + (data[8+i] & (1 << 28)) != 0 ? "X":"", + (data[8+i] >> 25) & 3, (data[8+i] >> 22) & 3, + (data[8+i] >> 16) & 0x1f, + j, + (data[8+i] & (1 << 15)) != 0 ? "W":"", + (data[8+i] & (1 << 14)) != 0 ? "Z":"", + (data[8+i] & (1 << 13)) != 0 ? "Y":"", + (data[8+i] & (1 << 12)) != 0 ? "X":"", + (data[8+i] >> 9) & 3, (data[8+i] >> 6) & 3, + (data[8+i] & 0x1f)); + kgem_debug_print(data, offset, 16, "Point Sprite TexCoord Enable\n"); + kgem_debug_print(data, offset, 17, "Const Interp Enable\n"); + kgem_debug_print(data, offset, 18, "Attrib 7-0 WrapShortest Enable\n"); + kgem_debug_print(data, offset, 19, "Attrib 15-8 WrapShortest Enable\n"); + + return len; + + case 0x7814: + assert(len == 9); + kgem_debug_print(data, offset, 0, "3DSTATE_WM\n"); + kgem_debug_print(data, offset, 1, "kernel start pointer 0\n"); + kgem_debug_print(data, offset, 2, "SPF=%d, VME=%d, Sampler Count %d, " + "Binding table count %d\n", + (data[2] >> 31) & 1, + (data[2] >> 30) & 1, + (data[2] >> 27) & 7, + (data[2] >> 18) & 0xff); + kgem_debug_print(data, offset, 3, "scratch offset\n"); + kgem_debug_print(data, offset, 4, "Depth Clear %d, Depth Resolve %d, HiZ Resolve %d, " + "Dispatch GRF start[0] %d, start[1] %d, start[2] %d\n", + (data[4] & (1 << 30)) != 0, + (data[4] & (1 << 28)) != 0, + (data[4] & (1 << 27)) != 0, + (data[4] >> 16) & 0x7f, + (data[4] >> 8) & 0x7f, + (data[4] & 0x7f)); + kgem_debug_print(data, offset, 5, "MaxThreads %d, PS KillPixel %d, PS computed Z %d, " + "PS use sourceZ %d, Thread Dispatch %d, PS use sourceW %d, Dispatch32 %d, " + "Dispatch16 %d, Dispatch8 %d\n", + ((data[5] >> 25) & 0x7f) + 1, + (data[5] & (1 << 22)) != 0, + (data[5] & (1 << 21)) != 0, + (data[5] & (1 << 20)) != 0, + (data[5] & (1 << 19)) != 0, + (data[5] & (1 << 8)) != 0, + (data[5] & (1 << 2)) != 0, + (data[5] & (1 << 1)) != 0, + (data[5] & (1 << 0)) != 0); + kgem_debug_print(data, offset, 6, "Num SF output %d, Pos XY offset %d, ZW interp mode %d , " + "Barycentric interp mode 0x%x, Point raster rule %d, Multisample mode %d, " + "Multisample Dispatch mode %d\n", + (data[6] >> 20) & 0x3f, + (data[6] >> 18) & 3, + (data[6] >> 16) & 3, + (data[6] >> 10) & 0x3f, + (data[6] & (1 << 9)) != 0, + (data[6] >> 1) & 3, + (data[6] & 1)); + kgem_debug_print(data, offset, 7, "kernel start pointer 1\n"); + kgem_debug_print(data, offset, 8, "kernel start pointer 2\n"); + + return len; + + case 0x7900: + assert(len == 4); + kgem_debug_print(data, offset, 0, + "3DSTATE_DRAWING_RECTANGLE\n"); + kgem_debug_print(data, offset, 1, "top left: %d, %d\n", + (uint16_t)(data[1] & 0xffff), + (uint16_t)(data[1] >> 16)); + kgem_debug_print(data, offset, 2, "bottom right: %d, %d\n", + (uint16_t)(data[2] & 0xffff), + (uint16_t)(data[2] >> 16)); + kgem_debug_print(data, offset, 3, "origin: %d, %d\n", + (int16_t)(data[3] & 0xffff), + (int16_t)(data[3] >> 16)); + return len; + + case 0x7905: + assert(len == 7); + kgem_debug_print(data, offset, 0, + "3DSTATE_DEPTH_BUFFER\n"); + kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n", + get_965_surfacetype(data[1] >> 29), + get_965_depthformat((data[1] >> 18) & 0x7), + (data[1] & 0x0001ffff) + 1, + data[1] & (1 << 27) ? "" : "not ", + (data[1] & (1 << 22)) != 0, + (data[1] & (1 << 21)) != 0); + kgem_debug_print(data, offset, 2, "depth offset\n"); + kgem_debug_print(data, offset, 3, "%dx%d\n", + ((data[3] & 0x0007ffc0) >> 6) + 1, + ((data[3] & 0xfff80000) >> 19) + 1); + kgem_debug_print(data, offset, 4, "volume depth\n"); + kgem_debug_print(data, offset, 5, "\n"); + kgem_debug_print(data, offset, 6, "\n"); + return len; + + case 0x7a00: + assert(len == 4 || len == 5); + switch ((data[1] >> 14) & 0x3) { + case 0: desc1 = "no write"; break; + case 1: desc1 = "qword write"; break; + case 2: desc1 = "PS_DEPTH_COUNT write"; break; + case 3: desc1 = "TIMESTAMP write"; break; + } + kgem_debug_print(data, offset, 0, "PIPE_CONTROL\n"); + kgem_debug_print(data, offset, 1, + "%s, %scs stall, %stlb invalidate, " + "%ssync gfdt, %sdepth stall, %sRC write flush, " + "%sinst flush, %sTC flush\n", + desc1, + data[1] & (1 << 20) ? "" : "no ", + data[1] & (1 << 18) ? "" : "no ", + data[1] & (1 << 17) ? "" : "no ", + data[1] & (1 << 13) ? "" : "no ", + data[1] & (1 << 12) ? "" : "no ", + data[1] & (1 << 11) ? "" : "no ", + data[1] & (1 << 10) ? "" : "no "); + if (len == 5) { + kgem_debug_print(data, offset, 2, "destination address\n"); + kgem_debug_print(data, offset, 3, "immediate dword low\n"); + kgem_debug_print(data, offset, 4, "immediate dword high\n"); + } else { + for (i = 2; i < len; i++) { + kgem_debug_print(data, offset, i, "\n"); + } + } + return len; + + case 0x7b00: + assert(len == 6); + kgem_debug_print(data, offset, 0, + "3DPRIMITIVE: %s %s\n", + get_965_prim_type(data[0]), + (data[0] & (1 << 15)) ? "random" : "sequential"); + kgem_debug_print(data, offset, 1, "vertex count\n"); + kgem_debug_print(data, offset, 2, "start vertex\n"); + kgem_debug_print(data, offset, 3, "instance count\n"); + kgem_debug_print(data, offset, 4, "start instance\n"); + kgem_debug_print(data, offset, 5, "index bias\n"); + primitive_out(kgem, data); + return len; + } + + /* For the rest, just dump the bytes */ + for (i = 0; i < ARRAY_SIZE(opcodes); i++) + if (op == opcodes[i].opcode) + break; + + assert(i < ARRAY_SIZE(opcodes)); + + len = 1; + kgem_debug_print(data, offset, 0, "%s\n", opcodes[i].name); + if (opcodes[i].max_len > 1) { + len = (data[0] & 0xff) + 2; + assert(len >= opcodes[i].min_len && + len <= opcodes[i].max_len); + } + + for (i = 1; i < len; i++) + kgem_debug_print(data, offset, i, "dword %d\n", i); + + return len; +} + +void kgem_gen6_finish_state(struct kgem *kgem) +{ + finish_state(kgem); +} diff --git a/drivers/video/Intel-2D/pixlib2.c b/drivers/video/Intel-2D/pixlib2.c new file mode 100644 index 0000000000..e967599b16 --- /dev/null +++ b/drivers/video/Intel-2D/pixlib2.c @@ -0,0 +1,282 @@ + +// -kr -i4 -ts4 -bls -bl -bli0 + +#include +#include +#include +#include +#include + + +#define DISPLAY_VERSION 0x0200 /* 2.00 */ + +#define SRV_GETVERSION 0 +#define SRV_GET_CAPS 3 + + +#define BUFFER_SIZE(n) ((n)*sizeof(uint32_t)) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) + +#define to_surface(x) (surface_t*)((x)->handle) + +typedef struct +{ + uint32_t width; + uint32_t height; + void *data; + uint32_t pitch; + uint32_t bo; + uint32_t bo_size; + uint32_t flags; +} surface_t; + + +int sna_init(uint32_t service); +void sna_fini(); + +int sna_create_bitmap(bitmap_t * bitmap); +int sna_destroy_bitmap(bitmap_t * bitmap); +int sna_lock_bitmap(bitmap_t * bitmap); +int sna_resize_bitmap(bitmap_t *bitmap); +//int sna_blit_copy(bitmap_t * src_bitmap, int dst_x, int dst_y, +// int w, int h, int src_x, int src_y); +int sna_blit_tex(bitmap_t * src_bitmap, bool scale, int dst_x, int dst_y, + int w, int h, int src_x, int src_y); + + +static uint32_t service; +static uint32_t hw_caps; + + +uint32_t init_pixlib(uint32_t caps) +{ + uint32_t api_version; + ioctl_t io; + + if (service != 0) + return caps & hw_caps; + + service = get_service("DISPLAY"); + if (service == 0) + goto fail; + + io.handle = service; + io.io_code = SRV_GETVERSION; + io.input = NULL; + io.inp_size = 0; + io.output = &api_version; + io.out_size = BUFFER_SIZE(1); + + if (call_service(&io) != 0) + goto fail; + + if ((DISPLAY_VERSION > (api_version & 0xFFFF)) || + (DISPLAY_VERSION < (api_version >> 16))) + goto fail; + + hw_caps = sna_init(service); + + if (hw_caps) + printf("2D caps %s%s%s\n", + (hw_caps & HW_BIT_BLIT) != 0 ? "HW_BIT_BLIT " : "", + (hw_caps & HW_TEX_BLIT) != 0 ? "HW_TEX_BLIT " : "", + (hw_caps & HW_VID_BLIT) != 0 ? "HW_VID_BLIT " : ""); + + return caps & hw_caps; + + fail: + service = 0; + return 0; +}; + +void done_pixlib() +{ + if (hw_caps != 0) + sna_fini(); +}; + + +int create_bitmap(bitmap_t * bitmap) +{ + uint32_t size, bo_size; + uint32_t pitch, max_pitch; + void *buffer; + surface_t *sf; + + bitmap->handle = -1; + bitmap->data = (void *) -1; + bitmap->pitch = -1; + + if (bitmap->flags &= hw_caps) + return sna_create_bitmap(bitmap); + + pitch = ALIGN(bitmap->width * 4, 16); + max_pitch = ALIGN(bitmap->max_width * 4, 16); + + size = ALIGN(pitch * bitmap->height, 4096); + bo_size = ALIGN(max_pitch * bitmap->max_height, 4096); + + if (bo_size < size) + bo_size = size; + + sf = malloc(sizeof(*sf)); + if (sf == NULL) + return -1; + + buffer = user_alloc(bo_size); + + if (buffer == NULL) + { + free(sf); + return -1; + }; + + sf->width = bitmap->width; + sf->height = bitmap->height; + sf->data = buffer; + sf->pitch = pitch; + sf->bo = 0; + sf->bo_size = bo_size; + sf->flags = bitmap->flags; + + bitmap->handle = (uint32_t) sf; + +// printf("create bitmap %p handle %p data %p w %d h%d\n", +// bitmap, bitmap->handle, bitmap->data, bitmap->width, bitmap->height); + + return 0; +}; + +int destroy_bitmap(bitmap_t * bitmap) +{ + surface_t *sf = to_surface(bitmap); + + if (sf->flags & hw_caps) + return sna_destroy_bitmap(bitmap); + + user_free(sf->data); + free(sf); + + bitmap->handle = -1; + bitmap->data = (void *) -1; + bitmap->pitch = -1; + + return 0; +}; + +int lock_bitmap(bitmap_t * bitmap) +{ + surface_t *sf = to_surface(bitmap); + + if (bitmap->data != (void *) -1) + return 0; + + if (sf->flags & hw_caps) + return sna_lock_bitmap(bitmap); + + bitmap->data = sf->data; + bitmap->pitch = sf->pitch; + + return 0; +}; + +int blit_bitmap(bitmap_t * bitmap, int dst_x, int dst_y, + int w, int h, int src_x, int src_y) +{ + struct blit_call bc; + int ret; + + surface_t *sf = to_surface(bitmap); + + if (sf->flags & hw_caps & HW_BIT_BLIT) + return sna_blit_tex(bitmap, false, dst_x, dst_y, w, h, src_x, src_y); + + bc.dstx = dst_x; + bc.dsty = dst_y; + bc.w = w; + bc.h = h; + bc.srcx = 0; + bc.srcy = 0; + bc.srcw = w; + bc.srch = h; + bc.stride = sf->pitch; + bc.bitmap = sf->data; + + __asm__ __volatile__( + "int $0x40":"=a"(ret):"a"(73), "b"(0x00), + "c"(&bc):"memory"); + + bitmap->data = (void *) -1; + bitmap->pitch = -1; + + return ret; +}; + +int fplay_blit_bitmap(bitmap_t * bitmap, int dst_x, int dst_y, int w, int h) +{ + struct blit_call bc; + int ret; + + surface_t *sf = to_surface(bitmap); + + if (sf->flags & hw_caps & HW_TEX_BLIT) + return sna_blit_tex(bitmap, true, dst_x, dst_y, w, h, 0, 0); + + bc.dstx = dst_x; + bc.dsty = dst_y; + bc.w = w; + bc.h = h; + bc.srcx = 0; + bc.srcy = 0; + bc.srcw = w; + bc.srch = h; + bc.stride = sf->pitch; + bc.bitmap = sf->data; + + __asm__ __volatile__( + "int $0x40":"=a"(ret):"a"(73), "b"(0x00), + "c"(&bc):"memory"); + + bitmap->data = (void *) -1; + bitmap->pitch = -1; + + return ret; +}; + +int resize_bitmap(bitmap_t * bitmap) +{ + uint32_t size; + uint32_t pitch; + +// printf("%s\n", __FUNCTION__); + + surface_t *sf = to_surface(bitmap); + + if (sf->flags & hw_caps) + { + return sna_resize_bitmap(bitmap); + }; + + pitch = ALIGN(bitmap->width * 4, 16); + size = ALIGN(pitch * bitmap->height, 4096); + + bitmap->pitch = -1; + bitmap->data = (void *) -1; + + if (size > sf->bo_size) + { + sf->data = user_realloc(sf->data, size); /* grow buffer */ + if (sf->data == NULL) + return -1; + + sf->bo_size = size; + } else if (size < sf->bo_size) + user_unmap(sf->data, size, sf->bo_size - size); /* unmap unused pages */ + + sf->width = bitmap->width; + sf->height = bitmap->height; + sf->pitch = pitch; + + return 0; +};