diff options
Diffstat (limited to 'libdrm/intel')
| -rw-r--r-- | libdrm/intel/intel_bufmgr.c | 81 | ||||
| -rw-r--r-- | libdrm/intel/intel_bufmgr.h | 186 | ||||
| -rw-r--r-- | libdrm/intel/intel_bufmgr_fake.c | 421 | ||||
| -rw-r--r-- | libdrm/intel/intel_bufmgr_gem.c | 558 | ||||
| -rw-r--r-- | libdrm/intel/intel_bufmgr_priv.h | 70 | 
5 files changed, 832 insertions, 484 deletions
diff --git a/libdrm/intel/intel_bufmgr.c b/libdrm/intel/intel_bufmgr.c index fc7284b5..188eac22 100644 --- a/libdrm/intel/intel_bufmgr.c +++ b/libdrm/intel/intel_bufmgr.c @@ -39,26 +39,26 @@  #include "intel_bufmgr.h"  #include "intel_bufmgr_priv.h" -/** @file dri_bufmgr.c +/** @file intel_bufmgr.c   *   * Convenience functions for buffer management methods.   */ -dri_bo * -dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, -	     unsigned int alignment) +drm_intel_bo * +drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, +		   unsigned long size, unsigned int alignment)  {     return bufmgr->bo_alloc(bufmgr, name, size, alignment);  }  void -dri_bo_reference(dri_bo *bo) +drm_intel_bo_reference(drm_intel_bo *bo)  {     bo->bufmgr->bo_reference(bo);  }  void -dri_bo_unreference(dri_bo *bo) +drm_intel_bo_unreference(drm_intel_bo *bo)  {     if (bo == NULL)        return; @@ -67,38 +67,39 @@ dri_bo_unreference(dri_bo *bo)  }  int -dri_bo_map(dri_bo *buf, int write_enable) +drm_intel_bo_map(drm_intel_bo *buf, int write_enable)  {     return buf->bufmgr->bo_map(buf, write_enable);  }  int -dri_bo_unmap(dri_bo *buf) +drm_intel_bo_unmap(drm_intel_bo *buf)  {     return buf->bufmgr->bo_unmap(buf);  }  int -dri_bo_subdata(dri_bo *bo, unsigned long offset, -	       unsigned long size, const void *data) +drm_intel_bo_subdata(drm_intel_bo *bo, unsigned long offset, +		     unsigned long size, const void *data)  {     int ret; +     if (bo->bufmgr->bo_subdata)        return bo->bufmgr->bo_subdata(bo, offset, size, data);     if (size == 0 || data == NULL)        return 0; -   ret = dri_bo_map(bo, 1); +   ret = drm_intel_bo_map(bo, 1);     if (ret)         return ret;     memcpy((unsigned char *)bo->virtual + offset, data, size); -   dri_bo_unmap(bo); +   drm_intel_bo_unmap(bo);     return 0;  }  int -dri_bo_get_subdata(dri_bo *bo, unsigned long offset, -		   unsigned long size, void *data) +drm_intel_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, +			 unsigned long size, void *data)  {     int ret;     if (bo->bufmgr->bo_subdata) @@ -107,48 +108,48 @@ dri_bo_get_subdata(dri_bo *bo, unsigned long offset,     if (size == 0 || data == NULL)        return 0; -   ret = dri_bo_map(bo, 0); +   ret = drm_intel_bo_map(bo, 0);     if (ret)         return ret;     memcpy(data, (unsigned char *)bo->virtual + offset, size); -   dri_bo_unmap(bo); +   drm_intel_bo_unmap(bo);     return 0;  }  void -dri_bo_wait_rendering(dri_bo *bo) +drm_intel_bo_wait_rendering(drm_intel_bo *bo)  {     bo->bufmgr->bo_wait_rendering(bo);  }  void -dri_bufmgr_destroy(dri_bufmgr *bufmgr) +drm_intel_bufmgr_destroy(drm_intel_bufmgr *bufmgr)  {     bufmgr->destroy(bufmgr);  }  int -dri_bo_exec(dri_bo *bo, int used, -	    drm_clip_rect_t *cliprects, int num_cliprects, -	    int DR4) +drm_intel_bo_exec(drm_intel_bo *bo, int used, +		  drm_clip_rect_t *cliprects, int num_cliprects, +		  int DR4)  {     return bo->bufmgr->bo_exec(bo, used, cliprects, num_cliprects, DR4);  }  void -dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug) +drm_intel_bufmgr_set_debug(drm_intel_bufmgr *bufmgr, int enable_debug)  {     bufmgr->debug = enable_debug;  }  int -dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count) +drm_intel_bufmgr_check_aperture_space(drm_intel_bo **bo_array, int count)  {  	return bo_array[0]->bufmgr->check_aperture_space(bo_array, count);  }  int -dri_bo_flink(dri_bo *bo, uint32_t *name) +drm_intel_bo_flink(drm_intel_bo *bo, uint32_t *name)  {      if (bo->bufmgr->bo_flink)  	return bo->bufmgr->bo_flink(bo, name); @@ -157,17 +158,17 @@ dri_bo_flink(dri_bo *bo, uint32_t *name)  }  int -dri_bo_emit_reloc(dri_bo *reloc_buf, -		  uint32_t read_domains, uint32_t write_domain, -		  uint32_t delta, uint32_t offset, dri_bo *target_buf) +drm_intel_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, +			drm_intel_bo *target_bo, uint32_t target_offset, +			uint32_t read_domains, uint32_t write_domain)  { -    return reloc_buf->bufmgr->bo_emit_reloc(reloc_buf, -					    read_domains, write_domain, -					    delta, offset, target_buf); +	return bo->bufmgr->bo_emit_reloc(bo, offset, +					 target_bo, target_offset, +					 read_domains, write_domain);  }  int -dri_bo_pin(dri_bo *bo, uint32_t alignment) +drm_intel_bo_pin(drm_intel_bo *bo, uint32_t alignment)  {      if (bo->bufmgr->bo_pin)  	return bo->bufmgr->bo_pin(bo, alignment); @@ -176,7 +177,7 @@ dri_bo_pin(dri_bo *bo, uint32_t alignment)  }  int -dri_bo_unpin(dri_bo *bo) +drm_intel_bo_unpin(drm_intel_bo *bo)  {      if (bo->bufmgr->bo_unpin)  	return bo->bufmgr->bo_unpin(bo); @@ -184,11 +185,23 @@ dri_bo_unpin(dri_bo *bo)      return -ENODEV;  } -int dri_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) +int drm_intel_bo_set_tiling(drm_intel_bo *bo, uint32_t *tiling_mode, +			    uint32_t stride)  {      if (bo->bufmgr->bo_set_tiling) -	return bo->bufmgr->bo_set_tiling(bo, tiling_mode); +	return bo->bufmgr->bo_set_tiling(bo, tiling_mode, stride); + +    *tiling_mode = I915_TILING_NONE; +    return 0; +} + +int drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t *tiling_mode, +			    uint32_t *swizzle_mode) +{ +    if (bo->bufmgr->bo_get_tiling) +	return bo->bufmgr->bo_get_tiling(bo, tiling_mode, swizzle_mode);      *tiling_mode = I915_TILING_NONE; +    *swizzle_mode = I915_BIT_6_SWIZZLE_NONE;      return 0;  } diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index 67dba6a1..1f7f73a4 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h @@ -36,10 +36,10 @@  #include <stdint.h> -typedef struct _dri_bufmgr dri_bufmgr; -typedef struct _dri_bo dri_bo; +typedef struct _drm_intel_bufmgr drm_intel_bufmgr; +typedef struct _drm_intel_bo drm_intel_bo; -struct _dri_bo { +struct _drm_intel_bo {      /**       * Size in bytes of the buffer object.       * @@ -48,6 +48,13 @@ struct _dri_bo {       */      unsigned long size;      /** +     * Alignment requirement for object +     * +     * Used for GTT mapping & pinning the object. +     */ +    unsigned long align; + +    /**       * Card virtual address (offset from the beginning of the aperture) for the       * object.  Only valid while validated.       */ @@ -58,74 +65,123 @@ struct _dri_bo {      void *virtual;      /** Buffer manager context associated with this buffer object */ -    dri_bufmgr *bufmgr; +    drm_intel_bufmgr *bufmgr; +      /**       * MM-specific handle for accessing object       */      int handle;  }; -dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, -		     unsigned int alignment); -void dri_bo_reference(dri_bo *bo); -void dri_bo_unreference(dri_bo *bo); -int dri_bo_map(dri_bo *buf, int write_enable); -int dri_bo_unmap(dri_bo *buf); - -int dri_bo_subdata(dri_bo *bo, unsigned long offset, -		   unsigned long size, const void *data); -int dri_bo_get_subdata(dri_bo *bo, unsigned long offset, -		       unsigned long size, void *data); -void dri_bo_wait_rendering(dri_bo *bo); - -void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug); -void dri_bufmgr_destroy(dri_bufmgr *bufmgr); -int dri_bo_exec(dri_bo *bo, int used, -		drm_clip_rect_t *cliprects, int num_cliprects, -		int DR4); -int dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count); - -int dri_bo_emit_reloc(dri_bo *reloc_buf, -		      uint32_t read_domains, uint32_t write_domain, -		      uint32_t delta, uint32_t offset, dri_bo *target_buf); -int dri_bo_pin(dri_bo *buf, uint32_t alignment); -int dri_bo_unpin(dri_bo *buf); -int dri_bo_set_tiling(dri_bo *buf, uint32_t *tiling_mode); -int dri_bo_flink(dri_bo *buf, uint32_t *name); - -/* intel_bufmgr_gem.c */ -dri_bufmgr *intel_bufmgr_gem_init(int fd, int batch_size); -dri_bo *intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, -				      unsigned int handle); -void intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr); - -/* intel_bufmgr_fake.c */ -dri_bufmgr *intel_bufmgr_fake_init(int fd, -				   unsigned long low_offset, void *low_virtual, -				   unsigned long size, -				   volatile unsigned int *last_dispatch); -void intel_bufmgr_fake_set_last_dispatch(dri_bufmgr *bufmgr, -					 volatile unsigned int *last_dispatch); -void intel_bufmgr_fake_set_exec_callback(dri_bufmgr *bufmgr, -					 int (*exec)(dri_bo *bo, -						     unsigned int used, -						     void *priv), -					 void *priv); -void intel_bufmgr_fake_set_fence_callback(dri_bufmgr *bufmgr, -					  unsigned int (*emit)(void *priv), -					  void (*wait)(unsigned int fence, -						       void *priv), -					  void *priv); -dri_bo *intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, -				   unsigned long offset, unsigned long size, -				   void *virtual); -void intel_bo_fake_disable_backing_store(dri_bo *bo, -					 void (*invalidate_cb)(dri_bo *bo, -							       void *ptr), -					 void *ptr); - -void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); -void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); +drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, +				 unsigned long size, unsigned int alignment); +void drm_intel_bo_reference(drm_intel_bo *bo); +void drm_intel_bo_unreference(drm_intel_bo *bo); +int drm_intel_bo_map(drm_intel_bo *bo, int write_enable); +int drm_intel_bo_unmap(drm_intel_bo *bo); + +int drm_intel_bo_subdata(drm_intel_bo *bo, unsigned long offset, +		     unsigned long size, const void *data); +int drm_intel_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, +			 unsigned long size, void *data); +void drm_intel_bo_wait_rendering(drm_intel_bo *bo); + +void drm_intel_bufmgr_set_debug(drm_intel_bufmgr *bufmgr, int enable_debug); +void drm_intel_bufmgr_destroy(drm_intel_bufmgr *bufmgr); +int drm_intel_bo_exec(drm_intel_bo *bo, int used, +		      drm_clip_rect_t *cliprects, int num_cliprects, +		      int DR4); +int drm_intel_bufmgr_check_aperture_space(drm_intel_bo **bo_array, int count); + +int drm_intel_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, +			    drm_intel_bo *target_bo, uint32_t target_offset, +			    uint32_t read_domains, uint32_t write_domain); +int drm_intel_bo_pin(drm_intel_bo *bo, uint32_t alignment); +int drm_intel_bo_unpin(drm_intel_bo *bo); +int drm_intel_bo_set_tiling(drm_intel_bo *bo, uint32_t *tiling_mode, +			    uint32_t stride); +int drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t *tiling_mode, +			uint32_t *swizzle_mode); +int drm_intel_bo_flink(drm_intel_bo *bo, uint32_t *name); + +/* drm_intel_bufmgr_gem.c */ +drm_intel_bufmgr *drm_intel_bufmgr_gem_init(int fd, int batch_size); +drm_intel_bo *drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, +						const char *name, +						unsigned int handle); +void drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr); +int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo); + +/* drm_intel_bufmgr_fake.c */ +drm_intel_bufmgr *drm_intel_bufmgr_fake_init(int fd, +					     unsigned long low_offset, +					     void *low_virtual, +					     unsigned long size, +					     volatile unsigned int *last_dispatch); +void drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr, +					     volatile unsigned int *last_dispatch); +void drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr, +					     int (*exec)(drm_intel_bo *bo, +							 unsigned int used, +							 void *priv), +					     void *priv); +void drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr, +					      unsigned int (*emit)(void *priv), +					      void (*wait)(unsigned int fence, +							   void *priv), +					      void *priv); +drm_intel_bo *drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr, +					     const char *name, +					     unsigned long offset, unsigned long size, +					     void *virtual); +void drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo, +					     void (*invalidate_cb)(drm_intel_bo *bo, +								   void *ptr), +					     void *ptr); + +void drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr); +void drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr); + +/** @{ Compatibility defines to keep old code building despite the symbol rename + * from dri_* to drm_intel_* + */ +#define dri_bo drm_intel_bo +#define dri_bufmgr drm_intel_bufmgr +#define dri_bo_alloc drm_intel_bo_alloc +#define dri_bo_reference drm_intel_bo_reference +#define dri_bo_unreference drm_intel_bo_unreference +#define dri_bo_map drm_intel_bo_map +#define dri_bo_unmap drm_intel_bo_unmap +#define dri_bo_subdata drm_intel_bo_subdata +#define dri_bo_get_subdata drm_intel_bo_get_subdata +#define dri_bo_wait_rendering drm_intel_bo_wait_rendering +#define dri_bufmgr_set_debug drm_intel_bufmgr_set_debug +#define dri_bufmgr_destroy drm_intel_bufmgr_destroy +#define dri_bo_exec drm_intel_bo_exec +#define dri_bufmgr_check_aperture_space drm_intel_bufmgr_check_aperture_space +#define dri_bo_emit_reloc(reloc_bo, read, write, target_offset,		\ +			  reloc_offset, target_bo)			\ +	drm_intel_bo_emit_reloc(reloc_bo, reloc_offset,			\ +			    target_bo, target_offset,			\ +			    read, write); +#define dri_bo_pin drm_intel_bo_pin +#define dri_bo_unpin drm_intel_bo_unpin +#define dri_bo_get_tiling drm_intel_bo_get_tiling +#define dri_bo_set_tiling(bo, mode) drm_intel_bo_set_tiling(bo, mode, 0) +#define dri_bo_flink drm_intel_bo_flink +#define intel_bufmgr_gem_init drm_intel_bufmgr_gem_init +#define intel_bo_gem_create_from_name drm_intel_bo_gem_create_from_name +#define intel_bufmgr_gem_enable_reuse drm_intel_bufmgr_gem_enable_reuse +#define intel_bufmgr_fake_init drm_intel_bufmgr_fake_init +#define intel_bufmgr_fake_set_last_dispatch drm_intel_bufmgr_fake_set_last_dispatch +#define intel_bufmgr_fake_set_exec_callback drm_intel_bufmgr_fake_set_exec_callback +#define intel_bufmgr_fake_set_fence_callback drm_intel_bufmgr_fake_set_fence_callback +#define intel_bo_fake_alloc_static drm_intel_bo_fake_alloc_static +#define intel_bo_fake_disable_backing_store drm_intel_bo_fake_disable_backing_store +#define intel_bufmgr_fake_contended_lock_take drm_intel_bufmgr_fake_contended_lock_take +#define intel_bufmgr_fake_evict_all drm_intel_bufmgr_fake_evict_all + +/** @{ */  #endif /* INTEL_BUFMGR_H */ diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c index 4c281467..0e465303 100644 --- a/libdrm/intel/intel_bufmgr_fake.c +++ b/libdrm/intel/intel_bufmgr_fake.c @@ -75,7 +75,7 @@  struct fake_buffer_reloc  {     /** Buffer object that the relocation points at. */ -   dri_bo *target_buf; +   drm_intel_bo *target_buf;     /** Offset of the relocation entry within reloc_buf. */     uint32_t offset;     /** Cached value of the offset when we last performed this relocation. */ @@ -106,12 +106,12 @@ struct block {     /** Fence cookie for the block. */     unsigned fence; /* Split to read_fence, write_fence */ -   dri_bo *bo; +   drm_intel_bo *bo;     void *virtual;  };  typedef struct _bufmgr_fake { -   dri_bufmgr bufmgr; +   drm_intel_bufmgr bufmgr;     pthread_mutex_t lock; @@ -163,7 +163,7 @@ typedef struct _bufmgr_fake {      * This allows the driver to hook in a replacement for the DRM usage in      * bufmgr_fake.      */ -   int (*exec)(dri_bo *bo, unsigned int used, void *priv); +   int (*exec)(drm_intel_bo *bo, unsigned int used, void *priv);     void *exec_priv;     /** Driver-supplied argument to driver callbacks */ @@ -176,10 +176,10 @@ typedef struct _bufmgr_fake {     int debug;     int performed_rendering; -} dri_bufmgr_fake; +} drm_intel_bufmgr_fake; -typedef struct _dri_bo_fake { -   dri_bo bo; +typedef struct _drm_intel_bo_fake { +   drm_intel_bo bo;     unsigned id;			/* debug only */     const char *name; @@ -214,11 +214,11 @@ typedef struct _dri_bo_fake {     struct block *block;     void *backing_store; -   void (*invalidate_cb)(dri_bo *bo, void *ptr); +   void (*invalidate_cb)(drm_intel_bo *bo, void *ptr);     void *invalidate_ptr; -} dri_bo_fake; +} drm_intel_bo_fake; -static int clear_fenced(dri_bufmgr_fake *bufmgr_fake, +static int clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake,  			unsigned int fence_cookie);  #define MAXFENCE 0x7fffffff @@ -237,13 +237,13 @@ static int FENCE_LTE( unsigned a, unsigned b )     return 0;  } -void intel_bufmgr_fake_set_fence_callback(dri_bufmgr *bufmgr, -					  unsigned int (*emit)(void *priv), -					  void (*wait)(unsigned int fence, -						       void *priv), -					  void *priv) +void drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr, +					      unsigned int (*emit)(void *priv), +					      void (*wait)(unsigned int fence, +							   void *priv), +					      void *priv)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     bufmgr_fake->fence_emit = emit;     bufmgr_fake->fence_wait = wait; @@ -251,13 +251,15 @@ void intel_bufmgr_fake_set_fence_callback(dri_bufmgr *bufmgr,  }  static unsigned int -_fence_emit_internal(dri_bufmgr_fake *bufmgr_fake) +_fence_emit_internal(drm_intel_bufmgr_fake *bufmgr_fake)  {     struct drm_i915_irq_emit ie;     int ret, seq = 1; -   if (bufmgr_fake->fence_emit != NULL) -      return bufmgr_fake->fence_emit(bufmgr_fake->fence_priv); +   if (bufmgr_fake->fence_emit != NULL) { +      seq = bufmgr_fake->fence_emit(bufmgr_fake->fence_priv); +      return seq; +   }     ie.irq_seq = &seq;     ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT, @@ -268,12 +270,11 @@ _fence_emit_internal(dri_bufmgr_fake *bufmgr_fake)     }     DBG("emit 0x%08x\n", seq); -   bufmgr_fake->last_fence = seq; -   return bufmgr_fake->last_fence; +   return seq;  }  static void -_fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, int seq) +_fence_wait_internal(drm_intel_bufmgr_fake *bufmgr_fake, int seq)  {     struct drm_i915_irq_wait iw;     int hw_seq, busy_count = 0; @@ -282,6 +283,7 @@ _fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, int seq)     if (bufmgr_fake->fence_wait != NULL) {        bufmgr_fake->fence_wait(seq, bufmgr_fake->fence_priv); +      clear_fenced(bufmgr_fake, seq);        return;     } @@ -395,7 +397,7 @@ _fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, int seq)  }  static int -_fence_test(dri_bufmgr_fake *bufmgr_fake, unsigned fence) +_fence_test(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence)  {     /* Slight problem with wrap-around:      */ @@ -406,10 +408,10 @@ _fence_test(dri_bufmgr_fake *bufmgr_fake, unsigned fence)   * Allocate a memory manager block for the buffer.   */  static int -alloc_block(dri_bo *bo) +alloc_block(drm_intel_bo *bo)  { -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; -   dri_bufmgr_fake *bufmgr_fake= (dri_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake= (drm_intel_bufmgr_fake *)bo->bufmgr;     struct block *block = (struct block *)calloc(sizeof *block, 1);     unsigned int align_log2 = ffs(bo_fake->alignment) - 1;     unsigned int sz; @@ -442,18 +444,18 @@ alloc_block(dri_bo *bo)  /* Release the card storage associated with buf:   */ -static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block) +static void free_block(drm_intel_bufmgr_fake *bufmgr_fake, struct block *block)  { -   dri_bo_fake *bo_fake; +   drm_intel_bo_fake *bo_fake;     DBG("free block %p %08x %d %d\n", block, block->mem->ofs, block->on_hardware, block->fenced);     if (!block)        return; -   bo_fake = (dri_bo_fake *)block->bo; -   if (!(bo_fake->flags & BM_NO_BACKING_STORE) && (bo_fake->card_dirty == 1)) { +   bo_fake = (drm_intel_bo_fake *)block->bo; +   if (!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)) && (bo_fake->card_dirty == 1)) {       memcpy(bo_fake->backing_store, block->virtual, block->bo->size); -     bo_fake->card_dirty = 1; +     bo_fake->card_dirty = 0;       bo_fake->dirty = 1;     } @@ -473,10 +475,10 @@ static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block)  }  static void -alloc_backing_store(dri_bo *bo) +alloc_backing_store(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     assert(!bo_fake->backing_store);     assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE))); @@ -487,9 +489,9 @@ alloc_backing_store(dri_bo *bo)  }  static void -free_backing_store(dri_bo *bo) +free_backing_store(drm_intel_bo *bo)  { -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     if (bo_fake->backing_store) {        assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE))); @@ -499,10 +501,10 @@ free_backing_store(dri_bo *bo)  }  static void -set_dirty(dri_bo *bo) +set_dirty(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     if (bo_fake->flags & BM_NO_BACKING_STORE && bo_fake->invalidate_cb != NULL)        bo_fake->invalidate_cb(bo, bo_fake->invalidate_ptr); @@ -514,14 +516,14 @@ set_dirty(dri_bo *bo)  }  static int -evict_lru(dri_bufmgr_fake *bufmgr_fake, unsigned int max_fence) +evict_lru(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int max_fence)  {     struct block *block, *tmp;     DBG("%s\n", __FUNCTION__);     DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { -      dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo; +      drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)block->bo;        if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA))  	 continue; @@ -540,14 +542,14 @@ evict_lru(dri_bufmgr_fake *bufmgr_fake, unsigned int max_fence)  }  static int -evict_mru(dri_bufmgr_fake *bufmgr_fake) +evict_mru(drm_intel_bufmgr_fake *bufmgr_fake)  {     struct block *block, *tmp;     DBG("%s\n", __FUNCTION__);     DRMLISTFOREACHSAFEREVERSE(block, tmp, &bufmgr_fake->lru) { -      dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo; +      drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)block->bo;        if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA))  	 continue; @@ -565,12 +567,13 @@ evict_mru(dri_bufmgr_fake *bufmgr_fake)  /**   * Removes all objects from the fenced list older than the given fence.   */ -static int clear_fenced(dri_bufmgr_fake *bufmgr_fake, +static int clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake,  			unsigned int fence_cookie)  {     struct block *block, *tmp;     int ret = 0; +   bufmgr_fake->last_fence = fence_cookie;     DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->fenced) {        assert(block->fenced); @@ -608,7 +611,7 @@ static int clear_fenced(dri_bufmgr_fake *bufmgr_fake,     return ret;  } -static void fence_blocks(dri_bufmgr_fake *bufmgr_fake, unsigned fence) +static void fence_blocks(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence)  {     struct block *block, *tmp; @@ -629,10 +632,10 @@ static void fence_blocks(dri_bufmgr_fake *bufmgr_fake, unsigned fence)     assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));  } -static int evict_and_alloc_block(dri_bo *bo) +static int evict_and_alloc_block(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     assert(bo_fake->block == NULL); @@ -699,7 +702,7 @@ static int evict_and_alloc_block(dri_bo *bo)   * Wait for hardware idle by emitting a fence and waiting for it.   */  static void -dri_bufmgr_fake_wait_idle(dri_bufmgr_fake *bufmgr_fake) +drm_intel_bufmgr_fake_wait_idle(drm_intel_bufmgr_fake *bufmgr_fake)  {     unsigned int cookie; @@ -714,20 +717,24 @@ dri_bufmgr_fake_wait_idle(dri_bufmgr_fake *bufmgr_fake)   * the necessary flushing.   */  static void -dri_fake_bo_wait_rendering(dri_bo *bo) +drm_intel_fake_bo_wait_rendering_locked(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; - -   pthread_mutex_lock(&bufmgr_fake->lock); +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo; -   if (bo_fake->block == NULL || !bo_fake->block->fenced) { -      pthread_mutex_unlock(&bufmgr_fake->lock); +   if (bo_fake->block == NULL || !bo_fake->block->fenced)        return; -   }     _fence_wait_internal(bufmgr_fake, bo_fake->block->fence); +} + +static void +drm_intel_fake_bo_wait_rendering(drm_intel_bo *bo) +{ +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   pthread_mutex_lock(&bufmgr_fake->lock); +   drm_intel_fake_bo_wait_rendering_locked(bo);     pthread_mutex_unlock(&bufmgr_fake->lock);  } @@ -736,9 +743,9 @@ dri_fake_bo_wait_rendering(dri_bo *bo)   *  -- and wait for idle   */  void -intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr) +drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     struct block *block, *tmp;     pthread_mutex_lock(&bufmgr_fake->lock); @@ -750,7 +757,7 @@ intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr)      * happening, so we'll need to wait anyway before letting anything get      * put on the card again.      */ -   dri_bufmgr_fake_wait_idle(bufmgr_fake); +   drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);     /* Check that we hadn't released the lock without having fenced the last      * set of buffers. @@ -766,14 +773,14 @@ intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr)     pthread_mutex_unlock(&bufmgr_fake->lock);  } -static dri_bo * -dri_fake_bo_alloc(dri_bufmgr *bufmgr, const char *name, -		  unsigned long size, unsigned int alignment) +static drm_intel_bo * +drm_intel_fake_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, +			unsigned long size, unsigned int alignment)  { -   dri_bufmgr_fake *bufmgr_fake; -   dri_bo_fake *bo_fake; +   drm_intel_bufmgr_fake *bufmgr_fake; +   drm_intel_bo_fake *bo_fake; -   bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     assert(size != 0); @@ -803,15 +810,15 @@ dri_fake_bo_alloc(dri_bufmgr *bufmgr, const char *name,     return &bo_fake->bo;  } -dri_bo * -intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, -			   unsigned long offset, unsigned long size, -			   void *virtual) +drm_intel_bo * +drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr, const char *name, +			       unsigned long offset, unsigned long size, +			       void *virtual)  { -   dri_bufmgr_fake *bufmgr_fake; -   dri_bo_fake *bo_fake; +   drm_intel_bufmgr_fake *bufmgr_fake; +   drm_intel_bo_fake *bo_fake; -   bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     assert(size != 0); @@ -836,10 +843,10 @@ intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name,  }  static void -dri_fake_bo_reference(dri_bo *bo) +drm_intel_fake_bo_reference(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     pthread_mutex_lock(&bufmgr_fake->lock);     bo_fake->refcount++; @@ -847,18 +854,18 @@ dri_fake_bo_reference(dri_bo *bo)  }  static void -dri_fake_bo_reference_locked(dri_bo *bo) +drm_intel_fake_bo_reference_locked(drm_intel_bo *bo)  { -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     bo_fake->refcount++;  }  static void -dri_fake_bo_unreference_locked(dri_bo *bo) +drm_intel_fake_bo_unreference_locked(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     int i;     if (--bo_fake->refcount == 0) { @@ -869,7 +876,7 @@ dri_fake_bo_unreference_locked(dri_bo *bo)        free_backing_store(bo);        for (i = 0; i < bo_fake->nr_relocs; i++) -	 dri_fake_bo_unreference_locked(bo_fake->relocs[i].target_buf); +	 drm_intel_fake_bo_unreference_locked(bo_fake->relocs[i].target_buf);        DBG("drm_bo_unreference: free buf %d %s\n", bo_fake->id, bo_fake->name); @@ -879,12 +886,12 @@ dri_fake_bo_unreference_locked(dri_bo *bo)  }  static void -dri_fake_bo_unreference(dri_bo *bo) +drm_intel_fake_bo_unreference(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr;     pthread_mutex_lock(&bufmgr_fake->lock); -   dri_fake_bo_unreference_locked(bo); +   drm_intel_fake_bo_unreference_locked(bo);     pthread_mutex_unlock(&bufmgr_fake->lock);  } @@ -892,13 +899,13 @@ dri_fake_bo_unreference(dri_bo *bo)   * Set the buffer as not requiring backing store, and instead get the callback   * invoked whenever it would be set dirty.   */ -void intel_bo_fake_disable_backing_store(dri_bo *bo, -					 void (*invalidate_cb)(dri_bo *bo, -							       void *ptr), -					 void *ptr) +void drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo, +					     void (*invalidate_cb)(drm_intel_bo *bo, +								   void *ptr), +					     void *ptr)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     pthread_mutex_lock(&bufmgr_fake->lock); @@ -927,14 +934,19 @@ void intel_bo_fake_disable_backing_store(dri_bo *bo,   * BM_NO_BACKING_STORE or BM_PINNED) or backing store, as necessary.   */  static int -dri_fake_bo_map_locked(dri_bo *bo, int write_enable) +drm_intel_fake_bo_map_locked(drm_intel_bo *bo, int write_enable)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     /* Static buffers are always mapped. */ -   if (bo_fake->is_static) +   if (bo_fake->is_static) { +      if (bo_fake->card_dirty) { +         drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); +         bo_fake->card_dirty = 0; +      }        return 0; +   }     /* Allow recursive mapping.  Mesa may recursively map buffers with      * nested display loops, and it is used internally in bufmgr_fake @@ -964,7 +976,7 @@ dri_fake_bo_map_locked(dri_bo *bo, int write_enable)  	    if (!(bo_fake->flags & BM_NO_FENCE_SUBDATA) &&  		bo_fake->block->fenced) { -	       dri_fake_bo_wait_rendering(bo); +	       drm_intel_fake_bo_wait_rendering_locked(bo);  	    }  	    bo->virtual = bo_fake->block->virtual; @@ -977,6 +989,14 @@ dri_fake_bo_map_locked(dri_bo *bo, int write_enable)  	 if (bo_fake->backing_store == 0)  	    alloc_backing_store(bo); +         if ((bo_fake->card_dirty == 1) && bo_fake->block) { +            if (bo_fake->block->fenced) +               drm_intel_fake_bo_wait_rendering_locked(bo); + +            memcpy(bo_fake->backing_store, bo_fake->block->virtual, bo_fake->block->bo->size); +            bo_fake->card_dirty = 0; +         } +  	 bo->virtual = bo_fake->backing_store;        }     } @@ -985,23 +1005,23 @@ dri_fake_bo_map_locked(dri_bo *bo, int write_enable)  }  static int -dri_fake_bo_map(dri_bo *bo, int write_enable) +drm_intel_fake_bo_map(drm_intel_bo *bo, int write_enable)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr;     int ret;     pthread_mutex_lock(&bufmgr_fake->lock); -   ret = dri_fake_bo_map_locked(bo, write_enable); +   ret = drm_intel_fake_bo_map_locked(bo, write_enable);     pthread_mutex_unlock(&bufmgr_fake->lock);     return ret;  }  static int -dri_fake_bo_unmap_locked(dri_bo *bo) +drm_intel_fake_bo_unmap_locked(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     /* Static buffers are always mapped. */     if (bo_fake->is_static) @@ -1020,30 +1040,28 @@ dri_fake_bo_unmap_locked(dri_bo *bo)  }  static int -dri_fake_bo_unmap(dri_bo *bo) +drm_intel_fake_bo_unmap(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr;     int ret;     pthread_mutex_lock(&bufmgr_fake->lock); -   ret = dri_fake_bo_unmap_locked(bo); +   ret = drm_intel_fake_bo_unmap_locked(bo);     pthread_mutex_unlock(&bufmgr_fake->lock);     return ret;  }  static void -dri_fake_kick_all(dri_bufmgr_fake *bufmgr_fake) +drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake *bufmgr_fake)  {     struct block *block, *tmp; -   pthread_mutex_lock(&bufmgr_fake->lock); -     bufmgr_fake->performed_rendering = 0;     /* okay for ever BO that is on the HW kick it off.        seriously not afraid of the POLICE right now */     DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) { -      dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo; +      drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)block->bo;        block->on_hardware = 0;        free_block(bufmgr_fake, block); @@ -1052,17 +1070,15 @@ dri_fake_kick_all(dri_bufmgr_fake *bufmgr_fake)        if (!(bo_fake->flags & BM_NO_BACKING_STORE))           bo_fake->dirty = 1;     } - -   pthread_mutex_unlock(&bufmgr_fake->lock);  }  static int -dri_fake_bo_validate(dri_bo *bo) +drm_intel_fake_bo_validate(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo; -   bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; +   bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr;     DBG("drm_bo_validate: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,         bo_fake->bo.size / 1024); @@ -1103,7 +1119,7 @@ dri_fake_bo_validate(dri_bo *bo)         * which we would be tracking when we free it.  Waiting for idle is         * a sufficiently large hammer for now.         */ -      dri_bufmgr_fake_wait_idle(bufmgr_fake); +      drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);        /* we may never have mapped this BO so it might not have any backing         * store if this happens it should be rare, but 0 the card memory @@ -1128,9 +1144,9 @@ dri_fake_bo_validate(dri_bo *bo)  }  static void -dri_fake_fence_validated(dri_bufmgr *bufmgr) +drm_intel_fake_fence_validated(drm_intel_bufmgr *bufmgr)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     unsigned int cookie;     cookie = _fence_emit_internal(bufmgr_fake); @@ -1140,9 +1156,9 @@ dri_fake_fence_validated(dri_bufmgr *bufmgr)  }  static void -dri_fake_destroy(dri_bufmgr *bufmgr) +drm_intel_fake_destroy(drm_intel_bufmgr *bufmgr)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     pthread_mutex_destroy(&bufmgr_fake->lock);     mmDestroy(bufmgr_fake->heap); @@ -1150,46 +1166,46 @@ dri_fake_destroy(dri_bufmgr *bufmgr)  }  static int -dri_fake_emit_reloc(dri_bo *reloc_buf, -		    uint32_t read_domains, uint32_t write_domain, -		    uint32_t delta, uint32_t offset, dri_bo *target_buf) +drm_intel_fake_emit_reloc(drm_intel_bo *bo, uint32_t offset, +			  drm_intel_bo *target_bo, uint32_t target_offset, +			  uint32_t read_domains, uint32_t write_domain)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)reloc_buf->bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr;     struct fake_buffer_reloc *r; -   dri_bo_fake *reloc_fake = (dri_bo_fake *)reloc_buf; -   dri_bo_fake *target_fake = (dri_bo_fake *)target_buf; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo; +   drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *)target_bo;     int i;     pthread_mutex_lock(&bufmgr_fake->lock); -   assert(reloc_buf); -   assert(target_buf); +   assert(bo); +   assert(target_bo); -   if (reloc_fake->relocs == NULL) { -      reloc_fake->relocs = malloc(sizeof(struct fake_buffer_reloc) * -				  MAX_RELOCS); +   if (bo_fake->relocs == NULL) { +      bo_fake->relocs = malloc(sizeof(struct fake_buffer_reloc) * MAX_RELOCS);     } -   r = &reloc_fake->relocs[reloc_fake->nr_relocs++]; - -   assert(reloc_fake->nr_relocs <= MAX_RELOCS); +   r = &bo_fake->relocs[bo_fake->nr_relocs++]; -   dri_fake_bo_reference_locked(target_buf); +   assert(bo_fake->nr_relocs <= MAX_RELOCS); -   if (!target_fake->is_static) -      reloc_fake->child_size += ALIGN(target_buf->size, target_fake->alignment); +   drm_intel_fake_bo_reference_locked(target_bo); -   r->target_buf = target_buf; +   if (!target_fake->is_static) { +      bo_fake->child_size += ALIGN(target_bo->size, target_fake->alignment); +      bo_fake->child_size += target_fake->child_size; +   } +   r->target_buf = target_bo;     r->offset = offset; -   r->last_target_offset = target_buf->offset; -   r->delta = delta; +   r->last_target_offset = target_bo->offset; +   r->delta = target_offset;     r->read_domains = read_domains;     r->write_domain = write_domain;     if (bufmgr_fake->debug) {        /* Check that a conflicting relocation hasn't already been emitted. */ -      for (i = 0; i < reloc_fake->nr_relocs - 1; i++) { -	 struct fake_buffer_reloc *r2 = &reloc_fake->relocs[i]; +      for (i = 0; i < bo_fake->nr_relocs - 1; i++) { +	 struct fake_buffer_reloc *r2 = &bo_fake->relocs[i];  	 assert(r->offset != r2->offset);        } @@ -1205,45 +1221,44 @@ dri_fake_emit_reloc(dri_bo *reloc_buf,   * the combined validation flags for the buffer on this batchbuffer submission.   */  static void -dri_fake_calculate_domains(dri_bo *bo) +drm_intel_fake_calculate_domains(drm_intel_bo *bo)  { -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     int i;     for (i = 0; i < bo_fake->nr_relocs; i++) {        struct fake_buffer_reloc *r = &bo_fake->relocs[i]; -      dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; +      drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *)r->target_buf;        /* Do the same for the tree of buffers we depend on */ -      dri_fake_calculate_domains(r->target_buf); +      drm_intel_fake_calculate_domains(r->target_buf);        target_fake->read_domains |= r->read_domains; -      if (target_fake->write_domain != 0) -	 target_fake->write_domain = r->write_domain; +      target_fake->write_domain |= r->write_domain;     }  }  static int -dri_fake_reloc_and_validate_buffer(dri_bo *bo) +drm_intel_fake_reloc_and_validate_buffer(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     int i, ret;     assert(bo_fake->map_count == 0);     for (i = 0; i < bo_fake->nr_relocs; i++) {        struct fake_buffer_reloc *r = &bo_fake->relocs[i]; -      dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; +      drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *)r->target_buf;        uint32_t reloc_data;        /* Validate the target buffer if that hasn't been done. */        if (!target_fake->validated) { -         ret = dri_fake_reloc_and_validate_buffer(r->target_buf); +         ret = drm_intel_fake_reloc_and_validate_buffer(r->target_buf);           if (ret != 0) {              if (bo->virtual != NULL) -                dri_fake_bo_unmap_locked(bo); +                drm_intel_fake_bo_unmap_locked(bo);              return ret;           }        } @@ -1253,7 +1268,7 @@ dri_fake_reloc_and_validate_buffer(dri_bo *bo)  	 reloc_data = r->target_buf->offset + r->delta;  	 if (bo->virtual == NULL) -	    dri_fake_bo_map_locked(bo, 1); +	    drm_intel_fake_bo_map_locked(bo, 1);  	 *(uint32_t *)((uint8_t *)bo->virtual + r->offset) = reloc_data; @@ -1262,34 +1277,33 @@ dri_fake_reloc_and_validate_buffer(dri_bo *bo)     }     if (bo->virtual != NULL) -      dri_fake_bo_unmap_locked(bo); +      drm_intel_fake_bo_unmap_locked(bo);     if (bo_fake->write_domain != 0) {        if (!(bo_fake->flags & (BM_NO_BACKING_STORE|BM_PINNED))) {           if (bo_fake->backing_store == 0)              alloc_backing_store(bo); - -         bo_fake->card_dirty = 1;        } +      bo_fake->card_dirty = 1;        bufmgr_fake->performed_rendering = 1;     } -   return dri_fake_bo_validate(bo); +   return drm_intel_fake_bo_validate(bo);  }  static void -dri_bo_fake_post_submit(dri_bo *bo) +drm_intel_bo_fake_post_submit(drm_intel_bo *bo)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *bo_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo;     int i;     for (i = 0; i < bo_fake->nr_relocs; i++) {        struct fake_buffer_reloc *r = &bo_fake->relocs[i]; -      dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf; +      drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *)r->target_buf;        if (target_fake->validated) -	 dri_bo_fake_post_submit(r->target_buf); +	 drm_intel_bo_fake_post_submit(r->target_buf);        DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n",  	  bo_fake->name, (uint32_t)bo->offset, r->offset, @@ -1303,25 +1317,25 @@ dri_bo_fake_post_submit(dri_bo *bo)  } -void intel_bufmgr_fake_set_exec_callback(dri_bufmgr *bufmgr, -					 int (*exec)(dri_bo *bo, -						     unsigned int used, -						     void *priv), -					 void *priv) +void drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr, +					     int (*exec)(drm_intel_bo *bo, +							 unsigned int used, +							 void *priv), +					     void *priv)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     bufmgr_fake->exec = exec;     bufmgr_fake->exec_priv = priv;  }  static int -dri_fake_bo_exec(dri_bo *bo, int used, -		 drm_clip_rect_t *cliprects, int num_cliprects, -		 int DR4) +drm_intel_fake_bo_exec(drm_intel_bo *bo, int used, +		       drm_clip_rect_t *cliprects, int num_cliprects, +		       int DR4)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; -   dri_bo_fake *batch_fake = (dri_bo_fake *)bo; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo->bufmgr; +   drm_intel_bo_fake *batch_fake = (drm_intel_bo_fake *)bo;     struct drm_i915_batchbuffer batch;     int ret;     int retry_count = 0; @@ -1330,17 +1344,17 @@ dri_fake_bo_exec(dri_bo *bo, int used,     bufmgr_fake->performed_rendering = 0; -   dri_fake_calculate_domains(bo); +   drm_intel_fake_calculate_domains(bo);     batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND;     /* we've ran out of RAM so blow the whole lot away and retry */   restart: -   ret = dri_fake_reloc_and_validate_buffer(bo); +   ret = drm_intel_fake_reloc_and_validate_buffer(bo);     if (bufmgr_fake->fail == 1) {        if (retry_count == 0) {           retry_count++; -         dri_fake_kick_all(bufmgr_fake); +         drm_intel_fake_kick_all_locked(bufmgr_fake);           bufmgr_fake->fail = 0;           goto restart;        } else /* dump out the memory here */ @@ -1351,8 +1365,10 @@ dri_fake_bo_exec(dri_bo *bo, int used,     if (bufmgr_fake->exec != NULL) {        int ret = bufmgr_fake->exec(bo, used, bufmgr_fake->exec_priv); -      if (ret != 0) +      if (ret != 0) { +	 pthread_mutex_unlock(&bufmgr_fake->lock);  	 return ret; +      }     } else {        batch.start = bo->offset;        batch.used = used; @@ -1364,13 +1380,14 @@ dri_fake_bo_exec(dri_bo *bo, int used,        if (drmCommandWrite(bufmgr_fake->fd, DRM_I915_BATCHBUFFER, &batch,  			  sizeof(batch))) {  	 drmMsg("DRM_I915_BATCHBUFFER: %d\n", -errno); +	 pthread_mutex_unlock(&bufmgr_fake->lock);  	 return -errno;        }     } -   dri_fake_fence_validated(bo->bufmgr); +   drm_intel_fake_fence_validated(bo->bufmgr); -   dri_bo_fake_post_submit(bo); +   drm_intel_bo_fake_post_submit(bo);     pthread_mutex_unlock(&bufmgr_fake->lock); @@ -1385,14 +1402,14 @@ dri_fake_bo_exec(dri_bo *bo, int used,   * a set smaller than the aperture.   */  static int -dri_fake_check_aperture_space(dri_bo **bo_array, int count) +drm_intel_fake_check_aperture_space(drm_intel_bo **bo_array, int count)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo_array[0]->bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bo_array[0]->bufmgr;     unsigned int sz = 0;     int i;     for (i = 0; i < count; i++) { -      dri_bo_fake *bo_fake = (dri_bo_fake *)bo_array[i]; +      drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *)bo_array[i];        if (bo_fake == NULL)  	 continue; @@ -1421,9 +1438,9 @@ dri_fake_check_aperture_space(dri_bo **bo_array, int count)   * own.   */  void -intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr) +drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     struct block *block, *tmp;     pthread_mutex_lock(&bufmgr_fake->lock); @@ -1435,7 +1452,7 @@ intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr)      * happening, so we'll need to wait anyway before letting anything get      * put on the card again.      */ -   dri_bufmgr_fake_wait_idle(bufmgr_fake); +   drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);     /* Check that we hadn't released the lock without having fenced the last      * set of buffers. @@ -1450,21 +1467,21 @@ intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr)     pthread_mutex_unlock(&bufmgr_fake->lock);  } -void intel_bufmgr_fake_set_last_dispatch(dri_bufmgr *bufmgr, +void drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr,  					 volatile unsigned int *last_dispatch)  { -   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; +   drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *)bufmgr;     bufmgr_fake->last_dispatch = (volatile int *)last_dispatch;  } -dri_bufmgr * -intel_bufmgr_fake_init(int fd, +drm_intel_bufmgr * +drm_intel_bufmgr_fake_init(int fd,  		       unsigned long low_offset, void *low_virtual,  		       unsigned long size,  		       volatile unsigned int *last_dispatch)  { -   dri_bufmgr_fake *bufmgr_fake; +   drm_intel_bufmgr_fake *bufmgr_fake;     bufmgr_fake = calloc(1, sizeof(*bufmgr_fake)); @@ -1484,16 +1501,16 @@ intel_bufmgr_fake_init(int fd,     bufmgr_fake->heap = mmInit(low_offset, size);     /* Hook in methods */ -   bufmgr_fake->bufmgr.bo_alloc = dri_fake_bo_alloc; -   bufmgr_fake->bufmgr.bo_reference = dri_fake_bo_reference; -   bufmgr_fake->bufmgr.bo_unreference = dri_fake_bo_unreference; -   bufmgr_fake->bufmgr.bo_map = dri_fake_bo_map; -   bufmgr_fake->bufmgr.bo_unmap = dri_fake_bo_unmap; -   bufmgr_fake->bufmgr.bo_wait_rendering = dri_fake_bo_wait_rendering; -   bufmgr_fake->bufmgr.bo_emit_reloc = dri_fake_emit_reloc; -   bufmgr_fake->bufmgr.destroy = dri_fake_destroy; -   bufmgr_fake->bufmgr.bo_exec = dri_fake_bo_exec; -   bufmgr_fake->bufmgr.check_aperture_space = dri_fake_check_aperture_space; +   bufmgr_fake->bufmgr.bo_alloc = drm_intel_fake_bo_alloc; +   bufmgr_fake->bufmgr.bo_reference = drm_intel_fake_bo_reference; +   bufmgr_fake->bufmgr.bo_unreference = drm_intel_fake_bo_unreference; +   bufmgr_fake->bufmgr.bo_map = drm_intel_fake_bo_map; +   bufmgr_fake->bufmgr.bo_unmap = drm_intel_fake_bo_unmap; +   bufmgr_fake->bufmgr.bo_wait_rendering = drm_intel_fake_bo_wait_rendering; +   bufmgr_fake->bufmgr.bo_emit_reloc = drm_intel_fake_emit_reloc; +   bufmgr_fake->bufmgr.destroy = drm_intel_fake_destroy; +   bufmgr_fake->bufmgr.bo_exec = drm_intel_fake_bo_exec; +   bufmgr_fake->bufmgr.check_aperture_space = drm_intel_fake_check_aperture_space;     bufmgr_fake->bufmgr.debug = 0;     bufmgr_fake->fd = fd; diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index af58ad8f..64d32d38 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -39,6 +39,7 @@  #endif  #include <xf86drm.h> +#include <fcntl.h>  #include <stdio.h>  #include <stdlib.h>  #include <string.h> @@ -47,6 +48,8 @@  #include <pthread.h>  #include <sys/ioctl.h>  #include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h>  #include "errno.h"  #include "intel_bufmgr.h" @@ -60,10 +63,10 @@        fprintf(stderr, __VA_ARGS__);			\  } while (0) -typedef struct _dri_bo_gem dri_bo_gem; +typedef struct _drm_intel_bo_gem drm_intel_bo_gem; -struct dri_gem_bo_bucket { -   dri_bo_gem *head, **tail; +struct drm_intel_gem_bo_bucket { +   drm_intel_bo_gem *head, **tail;     /**      * Limit on the number of entries in this bucket.      * @@ -77,9 +80,9 @@ struct dri_gem_bo_bucket {  /* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse   * is 1 << 16 pages, or 256MB.   */ -#define INTEL_GEM_BO_BUCKETS	16 -typedef struct _dri_bufmgr_gem { -    dri_bufmgr bufmgr; +#define DRM_INTEL_GEM_BO_BUCKETS	16 +typedef struct _drm_intel_bufmgr_gem { +    drm_intel_bufmgr bufmgr;      int fd; @@ -88,16 +91,18 @@ typedef struct _dri_bufmgr_gem {      pthread_mutex_t lock;      struct drm_i915_gem_exec_object *exec_objects; -    dri_bo **exec_bos; +    drm_intel_bo **exec_bos;      int exec_size;      int exec_count;      /** Array of lists of cached gem objects of power-of-two sizes */ -    struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS]; -} dri_bufmgr_gem; +    struct drm_intel_gem_bo_bucket cache_bucket[DRM_INTEL_GEM_BO_BUCKETS]; -struct _dri_bo_gem { -    dri_bo bo; +    uint64_t gtt_size; +} drm_intel_bufmgr_gem; + +struct _drm_intel_bo_gem { +    drm_intel_bo bo;      int refcount;      /** Boolean whether the mmap ioctl has been called for this buffer yet. */ @@ -126,17 +131,38 @@ struct _dri_bo_gem {      /** Array passed to the DRM containing relocation information. */      struct drm_i915_gem_relocation_entry *relocs;      /** Array of bos corresponding to relocs[i].target_handle */ -    dri_bo **reloc_target_bo; +    drm_intel_bo **reloc_target_bo;      /** Number of entries in relocs */      int reloc_count;      /** Mapped address for the buffer */      void *virtual;      /** free list */ -    dri_bo_gem *next; +    drm_intel_bo_gem *next; + +    /** +     * Boolean of whether this BO and its children have been included in +     * the current drm_intel_bufmgr_check_aperture_space() total. +     */ +    char included_in_check_aperture; + +    /** +     * Boolean of whether this buffer has been used as a relocation +     * target and had its size accounted for, and thus can't have any +     * further relocations added to it. +     */ +     char used_as_reloc_target; + +    /** +     * Size in bytes of this buffer and its relocation descendents. +     * +     * Used to avoid costly tree walking in drm_intel_bufmgr_check_aperture in +     * the common case. +     */ +    int reloc_tree_size;  }; -static void dri_gem_bo_reference_locked(dri_bo *bo); +static void drm_intel_gem_bo_reference_locked(drm_intel_bo *bo);  static int  logbase2(int n) @@ -152,8 +178,9 @@ logbase2(int n)     return log2;  } -static struct dri_gem_bo_bucket * -dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size) +static struct drm_intel_gem_bo_bucket * +drm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem, +				 unsigned long size)  {      int i; @@ -166,20 +193,20 @@ dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size)      /* We always allocate in units of pages */      i = ffs(size / 4096) - 1; -    if (i >= INTEL_GEM_BO_BUCKETS) +    if (i >= DRM_INTEL_GEM_BO_BUCKETS)  	return NULL;      return &bufmgr_gem->cache_bucket[i];  } -static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem) +static void drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem)  {      int i, j;      for (i = 0; i < bufmgr_gem->exec_count; i++) { -	dri_bo *bo = bufmgr_gem->exec_bos[i]; -	dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +	drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; +	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;  	if (bo_gem->relocs == NULL) {  	    DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, bo_gem->name); @@ -187,12 +214,13 @@ static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem)  	}  	for (j = 0; j < bo_gem->reloc_count; j++) { -	    dri_bo *target_bo = bo_gem->reloc_target_bo[j]; -	    dri_bo_gem *target_gem = (dri_bo_gem *)target_bo; +	    drm_intel_bo *target_bo = bo_gem->reloc_target_bo[j]; +	    drm_intel_bo_gem *target_gem = (drm_intel_bo_gem *)target_bo;  	    DBG("%2d: %d (%s)@0x%08llx -> %d (%s)@0x%08lx + 0x%08x\n",  		i, -		bo_gem->gem_handle, bo_gem->name, bo_gem->relocs[j].offset, +		bo_gem->gem_handle, bo_gem->name, +		(unsigned long long)bo_gem->relocs[j].offset,  		target_gem->gem_handle, target_gem->name, target_bo->offset,  		bo_gem->relocs[j].delta);  	} @@ -208,10 +236,10 @@ static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem)   * access flags.   */  static void -intel_add_validate_buffer(dri_bo *bo) +drm_intel_add_validate_buffer(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      int index;      if (bo_gem->validate_index != -1) @@ -242,7 +270,7 @@ intel_add_validate_buffer(dri_bo *bo)      bufmgr_gem->exec_objects[index].alignment = 0;      bufmgr_gem->exec_objects[index].offset = 0;      bufmgr_gem->exec_bos[index] = bo; -    dri_gem_bo_reference_locked(bo); +    drm_intel_gem_bo_reference_locked(bo);      bufmgr_gem->exec_count++;  } @@ -251,27 +279,28 @@ intel_add_validate_buffer(dri_bo *bo)  	sizeof(uint32_t))  static int -intel_setup_reloc_list(dri_bo *bo) +drm_intel_setup_reloc_list(drm_intel_bo *bo)  { -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;      bo_gem->relocs = malloc(bufmgr_gem->max_relocs *  			    sizeof(struct drm_i915_gem_relocation_entry)); -    bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs * sizeof(dri_bo *)); +    bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs * +				     sizeof(drm_intel_bo *));      return 0;  } -static dri_bo * -dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name, -		 unsigned long size, unsigned int alignment) +static drm_intel_bo * +drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, +		   unsigned long size, unsigned int alignment)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; -    dri_bo_gem *bo_gem; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; +    drm_intel_bo_gem *bo_gem;      unsigned int page_size = getpagesize();      int ret; -    struct dri_gem_bo_bucket *bucket; +    struct drm_intel_gem_bo_bucket *bucket;      int alloc_from_cache = 0;      unsigned long bo_size; @@ -279,7 +308,7 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,      bo_size = 1 << logbase2(size);      if (bo_size < page_size)  	bo_size = page_size; -    bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size); +    bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo_size);      /* If we don't have caching at this size, don't actually round the       * allocation up. @@ -334,6 +363,8 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,      bo_gem->name = name;      bo_gem->refcount = 1;      bo_gem->validate_index = -1; +    bo_gem->reloc_tree_size = bo_gem->bo.size; +    bo_gem->used_as_reloc_target = 0;      DBG("bo_create: buf %d (%s) %ldb\n",  	bo_gem->gem_handle, bo_gem->name, size); @@ -342,17 +373,17 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,  }  /** - * Returns a dri_bo wrapping the given buffer object handle. + * Returns a drm_intel_bo wrapping the given buffer object handle.   *   * This can be used when one application needs to pass a buffer object   * to another.   */ -dri_bo * -intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, -			      unsigned int handle) +drm_intel_bo * +drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, const char *name, +				  unsigned int handle)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; -    dri_bo_gem *bo_gem; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; +    drm_intel_bo_gem *bo_gem;      int ret;      struct drm_gem_open open_arg; @@ -385,10 +416,10 @@ intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,  }  static void -dri_gem_bo_reference(dri_bo *bo) +drm_intel_gem_bo_reference(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      pthread_mutex_lock(&bufmgr_gem->lock);      bo_gem->refcount++; @@ -398,16 +429,24 @@ dri_gem_bo_reference(dri_bo *bo)  static void  dri_gem_bo_reference_locked(dri_bo *bo)  { -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      bo_gem->refcount++;  }  static void -dri_gem_bo_free(dri_bo *bo) +drm_intel_gem_bo_reference_locked(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; + +    bo_gem->refcount++; +} + +static void +drm_intel_gem_bo_free(drm_intel_bo *bo) +{ +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_gem_close close;      int ret; @@ -426,20 +465,20 @@ dri_gem_bo_free(dri_bo *bo)  }  static void -dri_gem_bo_unreference_locked(dri_bo *bo) +drm_intel_gem_bo_unreference_locked(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      if (--bo_gem->refcount == 0) { -	struct dri_gem_bo_bucket *bucket; +	struct drm_intel_gem_bo_bucket *bucket;  	if (bo_gem->relocs != NULL) {  	    int i;  	    /* Unreference all the target buffers */  	    for (i = 0; i < bo_gem->reloc_count; i++) -		 dri_gem_bo_unreference_locked(bo_gem->reloc_target_bo[i]); +		 drm_intel_gem_bo_unreference_locked(bo_gem->reloc_target_bo[i]);  	    free(bo_gem->reloc_target_bo);  	    free(bo_gem->relocs);  	} @@ -447,7 +486,7 @@ dri_gem_bo_unreference_locked(dri_bo *bo)  	DBG("bo_unreference final: %d (%s)\n",  	    bo_gem->gem_handle, bo_gem->name); -	bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size); +	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);  	/* Put the buffer into our internal cache for reuse if we can. */  	if (bucket != NULL &&  	    (bucket->max_entries == -1 || @@ -465,26 +504,26 @@ dri_gem_bo_unreference_locked(dri_bo *bo)  	    bucket->tail = &bo_gem->next;  	    bucket->num_entries++;  	} else { -	    dri_gem_bo_free(bo); +	    drm_intel_gem_bo_free(bo);  	}      }  }  static void -dri_gem_bo_unreference(dri_bo *bo) +drm_intel_gem_bo_unreference(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;      pthread_mutex_lock(&bufmgr_gem->lock); -    dri_gem_bo_unreference_locked(bo); +    drm_intel_gem_bo_unreference_locked(bo);      pthread_mutex_unlock(&bufmgr_gem->lock);  }  static int -dri_gem_bo_map(dri_bo *bo, int write_enable) +drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_set_domain set_domain;      int ret; @@ -543,11 +582,89 @@ dri_gem_bo_map(dri_bo *bo, int write_enable)      return 0;  } +int +drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) +{ +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; +    struct drm_i915_gem_set_domain set_domain; +    int ret; + +    pthread_mutex_lock(&bufmgr_gem->lock); + +    /* Allow recursive mapping. Mesa may recursively map buffers with +     * nested display loops. +     */ +    if (!bo_gem->mapped) { + +	assert(bo->virtual == NULL); + +	DBG("bo_map_gtt: %d (%s)\n", bo_gem->gem_handle, bo_gem->name); + +	if (bo_gem->virtual == NULL) { +		struct drm_i915_gem_mmap_gtt mmap_arg; + +		memset(&mmap_arg, 0, sizeof(mmap_arg)); +		mmap_arg.handle = bo_gem->gem_handle; + +		/* Get the fake offset back... */ +		ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, +			    &mmap_arg); +		if (ret != 0) { +			fprintf(stderr, +				"%s:%d: Error preparing buffer map %d (%s): %s .\n", +				__FILE__, __LINE__, +				bo_gem->gem_handle, bo_gem->name, +				strerror(errno)); +			pthread_mutex_unlock(&bufmgr_gem->lock); +			return ret; +		} + +		/* and mmap it */ +		bo_gem->virtual = mmap(0, bo->size, PROT_READ | PROT_WRITE, +				       MAP_SHARED, bufmgr_gem->fd, +				       mmap_arg.offset); +		if (bo_gem->virtual == MAP_FAILED) { +			fprintf(stderr, +				"%s:%d: Error mapping buffer %d (%s): %s .\n", +				__FILE__, __LINE__, +				bo_gem->gem_handle, bo_gem->name, +				strerror(errno)); +			pthread_mutex_unlock(&bufmgr_gem->lock); +			return errno; +		} +	} + +	bo->virtual = bo_gem->virtual; +	bo_gem->mapped = 1; +	DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, +	    bo_gem->virtual); +    } + +    /* Now move it to the GTT domain so that the CPU caches are flushed */ +    set_domain.handle = bo_gem->gem_handle; +    set_domain.read_domains = I915_GEM_DOMAIN_GTT; +    set_domain.write_domain = I915_GEM_DOMAIN_GTT; +    do { +	    ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, +			&set_domain); +    } while (ret == -1 && errno == EINTR); + +    if (ret != 0) { +	    fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n", +		     __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno)); +    } + +    pthread_mutex_unlock(&bufmgr_gem->lock); + +    return 0; +} +  static int -dri_gem_bo_unmap(dri_bo *bo) +drm_intel_gem_bo_unmap(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_sw_finish sw_finish;      int ret; @@ -570,11 +687,11 @@ dri_gem_bo_unmap(dri_bo *bo)  }  static int -dri_gem_bo_subdata (dri_bo *bo, unsigned long offset, -		    unsigned long size, const void *data) +drm_intel_gem_bo_subdata (drm_intel_bo *bo, unsigned long offset, +			  unsigned long size, const void *data)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_pwrite pwrite;      int ret; @@ -596,11 +713,11 @@ dri_gem_bo_subdata (dri_bo *bo, unsigned long offset,  }  static int -dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset, -			unsigned long size, void *data) +drm_intel_gem_bo_get_subdata (drm_intel_bo *bo, unsigned long offset, +			      unsigned long size, void *data)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_pread pread;      int ret; @@ -622,17 +739,19 @@ dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset,  }  static void -dri_gem_bo_wait_rendering(dri_bo *bo) +drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_set_domain set_domain;      int ret;      set_domain.handle = bo_gem->gem_handle;      set_domain.read_domains = I915_GEM_DOMAIN_GTT;      set_domain.write_domain = 0; -    ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); +    do { +	ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); +    } while (ret == -1 && errno == EINTR);      if (ret != 0) {  	fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",  		 __FILE__, __LINE__, @@ -642,9 +761,9 @@ dri_gem_bo_wait_rendering(dri_bo *bo)  }  static void -dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr) +drm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;      int i;      free(bufmgr_gem->exec_objects); @@ -653,9 +772,9 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)      pthread_mutex_destroy(&bufmgr_gem->lock);      /* Free any cached buffer objects we were going to reuse */ -    for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) { -	struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i]; -	dri_bo_gem *bo_gem; +    for (i = 0; i < DRM_INTEL_GEM_BO_BUCKETS; i++) { +	struct drm_intel_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i]; +	drm_intel_bo_gem *bo_gem;  	while ((bo_gem = bucket->head) != NULL) {  	    bucket->head = bo_gem->next; @@ -663,7 +782,7 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)  		bucket->tail = &bucket->head;  	    bucket->num_entries--; -	    dri_gem_bo_free(&bo_gem->bo); +	    drm_intel_gem_bo_free(&bo_gem->bo);  	}      } @@ -680,18 +799,19 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)   * last known offset in target_bo.   */  static int -dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain, -		      uint32_t delta, uint32_t offset, dri_bo *target_bo) +drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, +			    drm_intel_bo *target_bo, uint32_t target_offset, +			    uint32_t read_domains, uint32_t write_domain)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; -    dri_bo_gem *target_bo_gem = (dri_bo_gem *)target_bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; +    drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;      pthread_mutex_lock(&bufmgr_gem->lock);      /* Create a new relocation list if needed */      if (bo_gem->relocs == NULL) -	intel_setup_reloc_list(bo); +	drm_intel_setup_reloc_list(bo);      /* Check overflow */      assert(bo_gem->reloc_count < bufmgr_gem->max_relocs); @@ -700,8 +820,17 @@ dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,      assert (offset <= bo->size - 4);      assert ((write_domain & (write_domain-1)) == 0); +    /* Make sure that we're not adding a reloc to something whose size has +     * already been accounted for. +     */ +    assert(!bo_gem->used_as_reloc_target); +    bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size; + +    /* Flag the target to disallow further relocations in it. */ +    target_bo_gem->used_as_reloc_target = 1; +      bo_gem->relocs[bo_gem->reloc_count].offset = offset; -    bo_gem->relocs[bo_gem->reloc_count].delta = delta; +    bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;      bo_gem->relocs[bo_gem->reloc_count].target_handle =  	target_bo_gem->gem_handle;      bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains; @@ -709,7 +838,7 @@ dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,      bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;      bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo; -    dri_gem_bo_reference_locked(target_bo); +    drm_intel_gem_bo_reference_locked(target_bo);      bo_gem->reloc_count++; @@ -724,61 +853,61 @@ dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,   * index values into the validation list.   */  static void -dri_gem_bo_process_reloc(dri_bo *bo) +drm_intel_gem_bo_process_reloc(drm_intel_bo *bo)  { -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      int i;      if (bo_gem->relocs == NULL)  	return;      for (i = 0; i < bo_gem->reloc_count; i++) { -	dri_bo *target_bo = bo_gem->reloc_target_bo[i]; +	drm_intel_bo *target_bo = bo_gem->reloc_target_bo[i];  	/* Continue walking the tree depth-first. */ -	dri_gem_bo_process_reloc(target_bo); +	drm_intel_gem_bo_process_reloc(target_bo);  	/* Add the target to the validate list */ -	intel_add_validate_buffer(target_bo); +	drm_intel_add_validate_buffer(target_bo);      }  }  static void -intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem) +drm_intel_update_buffer_offsets (drm_intel_bufmgr_gem *bufmgr_gem)  {      int i;      for (i = 0; i < bufmgr_gem->exec_count; i++) { -	dri_bo *bo = bufmgr_gem->exec_bos[i]; -	dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +	drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; +	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;  	/* Update the buffer offset */  	if (bufmgr_gem->exec_objects[i].offset != bo->offset) {  	    DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",  		bo_gem->gem_handle, bo_gem->name, bo->offset, -		bufmgr_gem->exec_objects[i].offset); +		(unsigned long long)bufmgr_gem->exec_objects[i].offset);  	    bo->offset = bufmgr_gem->exec_objects[i].offset;  	}      }  }  static int -dri_gem_bo_exec(dri_bo *bo, int used, -		drm_clip_rect_t *cliprects, int num_cliprects, -		int DR4) +drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, +		      drm_clip_rect_t *cliprects, int num_cliprects, +		      int DR4)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;      struct drm_i915_gem_execbuffer execbuf;      int ret, i;      pthread_mutex_lock(&bufmgr_gem->lock);      /* Update indices and set up the validate list. */ -    dri_gem_bo_process_reloc(bo); +    drm_intel_gem_bo_process_reloc(bo);      /* Add the batch buffer to the validation list.  There are no relocations       * pointing to it.       */ -    intel_add_validate_buffer(bo); +    drm_intel_add_validate_buffer(bo);      execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;      execbuf.buffer_count = bufmgr_gem->exec_count; @@ -791,23 +920,23 @@ dri_gem_bo_exec(dri_bo *bo, int used,      do {  	ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf); -    } while (ret == -EAGAIN); +    } while (ret != 0 && errno == EAGAIN); -    intel_update_buffer_offsets (bufmgr_gem); +    drm_intel_update_buffer_offsets (bufmgr_gem);      if (bufmgr_gem->bufmgr.debug) -	dri_gem_dump_validation_list(bufmgr_gem); +	drm_intel_gem_dump_validation_list(bufmgr_gem);      for (i = 0; i < bufmgr_gem->exec_count; i++) { -	dri_bo *bo = bufmgr_gem->exec_bos[i]; -	dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +	drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; +	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;  	/* Need to call swrast on next bo_map */  	bo_gem->swrast = 0;  	/* Disconnect the buffer from the validate list */  	bo_gem->validate_index = -1; -	dri_gem_bo_unreference_locked(bo); +	drm_intel_gem_bo_unreference_locked(bo);  	bufmgr_gem->exec_bos[i] = NULL;      }      bufmgr_gem->exec_count = 0; @@ -817,10 +946,10 @@ dri_gem_bo_exec(dri_bo *bo, int used,  }  static int -dri_gem_bo_pin(dri_bo *bo, uint32_t alignment) +drm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_pin pin;      int ret; @@ -836,10 +965,10 @@ dri_gem_bo_pin(dri_bo *bo, uint32_t alignment)  }  static int -dri_gem_bo_unpin(dri_bo *bo) +drm_intel_gem_bo_unpin(drm_intel_bo *bo)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_unpin unpin;      int ret; @@ -853,15 +982,17 @@ dri_gem_bo_unpin(dri_bo *bo)  }  static int -dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) +drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t *tiling_mode, +			    uint32_t stride)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_i915_gem_set_tiling set_tiling;      int ret;      set_tiling.handle = bo_gem->gem_handle;      set_tiling.tiling_mode = *tiling_mode; +    set_tiling.stride = stride;      ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);      if (ret != 0) { @@ -874,10 +1005,33 @@ dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode)  }  static int -dri_gem_bo_flink(dri_bo *bo, uint32_t *name) +drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t *tiling_mode, +			    uint32_t *swizzle_mode) +{ +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; +    struct drm_i915_gem_get_tiling get_tiling; +    int ret; + +    get_tiling.handle = bo_gem->gem_handle; + +    ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling); +    if (ret != 0) { +	*tiling_mode = I915_TILING_NONE; +	*swizzle_mode = I915_BIT_6_SWIZZLE_NONE; +	return -errno; +    } + +    *tiling_mode = get_tiling.tiling_mode; +    *swizzle_mode = get_tiling.swizzle_mode; +    return 0; +} + +static int +drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t *name)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; -    dri_bo_gem *bo_gem = (dri_bo_gem *)bo; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;      struct drm_gem_flink flink;      int ret; @@ -902,23 +1056,106 @@ dri_gem_bo_flink(dri_bo *bo, uint32_t *name)   * in flight at once.   */  void -intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr) +drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)  { -    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;      int i; -    for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) { +    for (i = 0; i < DRM_INTEL_GEM_BO_BUCKETS; i++) {  	bufmgr_gem->cache_bucket[i].max_entries = -1;      }  } -/* +/** + * Return the additional aperture space required by the tree of buffer objects + * rooted at bo. + */ +static int +drm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo) +{ +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; +    int i; +    int total = 0; + +    if (bo == NULL || bo_gem->included_in_check_aperture) +	return 0; + +    total += bo->size; +    bo_gem->included_in_check_aperture = 1; + +    for (i = 0; i < bo_gem->reloc_count; i++) +	total += drm_intel_gem_bo_get_aperture_space(bo_gem->reloc_target_bo[i]); + +    return total; +} + +/** + * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready + * for the next drm_intel_bufmgr_check_aperture_space() call. + */ +static void +drm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo) +{ +    drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; +    int i; + +    if (bo == NULL || !bo_gem->included_in_check_aperture) +	return; + +    bo_gem->included_in_check_aperture = 0; + +    for (i = 0; i < bo_gem->reloc_count; i++) +	drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->reloc_target_bo[i]); +} + +/** + * Return -1 if the batchbuffer should be flushed before attempting to + * emit rendering referencing the buffers pointed to by bo_array. + * + * This is required because if we try to emit a batchbuffer with relocations + * to a tree of buffers that won't simultaneously fit in the aperture, + * the rendering will return an error at a point where the software is not + * prepared to recover from it.   * + * However, we also want to emit the batchbuffer significantly before we reach + * the limit, as a series of batchbuffers each of which references buffers + * covering almost all of the aperture means that at each emit we end up + * waiting to evict a buffer from the last rendering, and we get synchronous + * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to + * get better parallelism.   */  static int -dri_gem_check_aperture_space(dri_bo **bo_array, int count) +drm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count)  { -    return 0; +    drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo_array[0]->bufmgr; +    unsigned int total = 0; +    unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4; +    int i; + +    for (i = 0; i < count; i++) { +	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo_array[i]; +	if (bo_gem != NULL) +		total += bo_gem->reloc_tree_size; +    } + +    if (total > threshold) { +	total = 0; +	for (i = 0; i < count; i++) +	    total += drm_intel_gem_bo_get_aperture_space(bo_array[i]); + +	for (i = 0; i < count; i++) +	    drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]); +    } + +    if (total > bufmgr_gem->gtt_size * 3 / 4) { +	DBG("check_space: overflowed available aperture, %dkb vs %dkb\n", +	    total / 1024, (int)bufmgr_gem->gtt_size / 1024); +	return -1; +    } else { +	DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024 , +	    (int)bufmgr_gem->gtt_size / 1024); +	return 0; +    }  }  /** @@ -927,11 +1164,12 @@ dri_gem_check_aperture_space(dri_bo **bo_array, int count)   *   * \param fd File descriptor of the opened DRM device.   */ -dri_bufmgr * -intel_bufmgr_gem_init(int fd, int batch_size) +drm_intel_bufmgr * +drm_intel_bufmgr_gem_init(int fd, int batch_size)  { -    dri_bufmgr_gem *bufmgr_gem; -    int i; +    drm_intel_bufmgr_gem *bufmgr_gem; +    struct drm_i915_gem_get_aperture aperture; +    int ret, i;      bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));      bufmgr_gem->fd = fd; @@ -941,6 +1179,19 @@ intel_bufmgr_gem_init(int fd, int batch_size)        return NULL;     } +    ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); + +    if (ret == 0) +	bufmgr_gem->gtt_size = aperture.aper_available_size; +    else { +	fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n", +		strerror(errno)); +	bufmgr_gem->gtt_size = 128 * 1024 * 1024; +	fprintf(stderr, "Assuming %dkB available aperture size.\n" +		"May lead to reduced performance or incorrect rendering.\n", +		(int)bufmgr_gem->gtt_size / 1024); +    } +      /* Let's go with one relocation per every 2 dwords (but round down a bit       * since a power of two will mean an extra page allocation for the reloc       * buffer). @@ -949,25 +1200,26 @@ intel_bufmgr_gem_init(int fd, int batch_size)       */      bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2; -    bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc; -    bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference; -    bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference; -    bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map; -    bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap; -    bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata; -    bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata; -    bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering; -    bufmgr_gem->bufmgr.bo_emit_reloc = dri_gem_bo_emit_reloc; -    bufmgr_gem->bufmgr.bo_pin = dri_gem_bo_pin; -    bufmgr_gem->bufmgr.bo_unpin = dri_gem_bo_unpin; -    bufmgr_gem->bufmgr.bo_set_tiling = dri_gem_bo_set_tiling; -    bufmgr_gem->bufmgr.bo_flink = dri_gem_bo_flink; -    bufmgr_gem->bufmgr.bo_exec = dri_gem_bo_exec; -    bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy; +    bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc; +    bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference; +    bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference; +    bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map; +    bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap; +    bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata; +    bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata; +    bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering; +    bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc; +    bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin; +    bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin; +    bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling; +    bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling; +    bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink; +    bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec; +    bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_destroy;      bufmgr_gem->bufmgr.debug = 0; -    bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space; +    bufmgr_gem->bufmgr.check_aperture_space = drm_intel_gem_check_aperture_space;      /* Initialize the linked lists for BO reuse cache. */ -    for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) +    for (i = 0; i < DRM_INTEL_GEM_BO_BUCKETS; i++)  	bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;      return &bufmgr_gem->bufmgr; diff --git a/libdrm/intel/intel_bufmgr_priv.h b/libdrm/intel/intel_bufmgr_priv.h index 7f39bfc2..76d31e47 100644 --- a/libdrm/intel/intel_bufmgr_priv.h +++ b/libdrm/intel/intel_bufmgr_priv.h @@ -39,7 +39,7 @@   *   * Contains public methods followed by private storage for the buffer manager.   */ -struct _dri_bufmgr { +struct _drm_intel_bufmgr {     /**      * Allocate a buffer object.      * @@ -48,17 +48,17 @@ struct _dri_bufmgr {      * bo_map() to be used by the CPU, and validated for use using bo_validate()      * to be used from the graphics device.      */ -   dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name, -		       unsigned long size, unsigned int alignment); +   drm_intel_bo *(*bo_alloc)(drm_intel_bufmgr *bufmgr, const char *name, +			     unsigned long size, unsigned int alignment);     /** Takes a reference on a buffer object */ -   void (*bo_reference)(dri_bo *bo); +   void (*bo_reference)(drm_intel_bo *bo);     /**      * Releases a reference on a buffer object, freeing the data if      * rerefences remain.      */ -   void (*bo_unreference)(dri_bo *bo); +   void (*bo_unreference)(drm_intel_bo *bo);     /**      * Maps the buffer into userspace. @@ -67,28 +67,28 @@ struct _dri_bufmgr {      * buffer to complete, first.  The resulting mapping is available at      * buf->virtual.      */ -   int (*bo_map)(dri_bo *buf, int write_enable); +   int (*bo_map)(drm_intel_bo *bo, int write_enable);     /** Reduces the refcount on the userspace mapping of the buffer object. */ -   int (*bo_unmap)(dri_bo *buf); +   int (*bo_unmap)(drm_intel_bo *bo);     /**      * Write data into an object.      *      * This is an optional function, if missing, -    * dri_bo will map/memcpy/unmap. +    * drm_intel_bo will map/memcpy/unmap.      */ -   int (*bo_subdata) (dri_bo *buf, unsigned long offset, -		      unsigned long size, const void *data); +   int (*bo_subdata)(drm_intel_bo *bo, unsigned long offset, +		     unsigned long size, const void *data);     /**      * Read data from an object      *      * This is an optional function, if missing, -    * dri_bo will map/memcpy/unmap. +    * drm_intel_bo will map/memcpy/unmap.      */ -   int (*bo_get_subdata) (dri_bo *bo, unsigned long offset, -			  unsigned long size, void *data); +   int (*bo_get_subdata)(drm_intel_bo *bo, unsigned long offset, +			 unsigned long size, void *data);     /**      * Waits for rendering to an object by the GPU to have completed. @@ -96,12 +96,12 @@ struct _dri_bufmgr {      * This is not required for any access to the BO by bo_map, bo_subdata, etc.      * It is merely a way for the driver to implement glFinish.      */ -   void (*bo_wait_rendering) (dri_bo *bo); +   void (*bo_wait_rendering)(drm_intel_bo *bo);     /**      * Tears down the buffer manager instance.      */ -   void (*destroy)(dri_bufmgr *bufmgr); +   void (*destroy)(drm_intel_bufmgr *bufmgr);      /**       * Add relocation entry in reloc_buf, which will be updated with the @@ -109,23 +109,23 @@ struct _dri_bufmgr {       *       * Relocations remain in place for the lifetime of the buffer object.       * -     * \param reloc_buf Buffer to write the relocation into. +     * \param bo Buffer to write the relocation into. +     * \param offset Byte offset within reloc_bo of the pointer to target_bo. +     * \param target_bo Buffer whose offset should be written into the +     *                  relocation entry. +     * \param target_offset Constant value to be added to target_bo's offset in +     *	                    relocation entry.       * \param read_domains GEM read domains which the buffer will be read into       *	      by the command that this relocation is part of.       * \param write_domains GEM read domains which the buffer will be dirtied       *	      in by the command that this relocation is part of. -     * \param delta Constant value to be added to the relocation target's -     *	       offset. -     * \param offset Byte offset within batch_buf of the relocated pointer. -     * \param target Buffer whose offset should be written into the relocation -     *	     entry.       */ -    int (*bo_emit_reloc)(dri_bo *reloc_buf, -			 uint32_t read_domains, uint32_t write_domain, -			 uint32_t delta, uint32_t offset, dri_bo *target); +    int (*bo_emit_reloc)(drm_intel_bo *bo, uint32_t offset, +			 drm_intel_bo *target_bo, uint32_t target_offset, +			 uint32_t read_domains, uint32_t write_domain);      /** Executes the command buffer pointed to by bo. */ -    int (*bo_exec)(dri_bo *bo, int used, +    int (*bo_exec)(drm_intel_bo *bo, int used,  		   drm_clip_rect_t *cliprects, int num_cliprects,  		   int DR4); @@ -135,29 +135,39 @@ struct _dri_bufmgr {       * \param buf Buffer to pin       * \param alignment Required alignment for aperture, in bytes       */ -    int (*bo_pin) (dri_bo *buf, uint32_t alignment); +    int (*bo_pin)(drm_intel_bo *bo, uint32_t alignment);      /**       * Unpin a buffer from the aperture, allowing it to be removed       *       * \param buf Buffer to unpin       */ -    int (*bo_unpin) (dri_bo *buf); +    int (*bo_unpin)(drm_intel_bo *bo);      /**       * Ask that the buffer be placed in tiling mode       *       * \param buf Buffer to set tiling mode for       * \param tiling_mode desired, and returned tiling mode       */ -    int (*bo_set_tiling) (dri_bo *bo, uint32_t *tiling_mode); +    int (*bo_set_tiling)(drm_intel_bo *bo, uint32_t *tiling_mode, +			 uint32_t stride); +    /** +     * Get the current tiling (and resulting swizzling) mode for the bo. +     * +     * \param buf Buffer to get tiling mode for +     * \param tiling_mode returned tiling mode +     * \param swizzle_mode returned swizzling mode +     */ +    int (*bo_get_tiling)(drm_intel_bo *bo, uint32_t *tiling_mode, +			 uint32_t *swizzle_mode);      /**       * Create a visible name for a buffer which can be used by other apps       *       * \param buf Buffer to create a name for       * \param name Returned name       */ -    int (*bo_flink) (dri_bo *buf, uint32_t *name); +    int (*bo_flink)(drm_intel_bo *bo, uint32_t *name); -    int (*check_aperture_space)(dri_bo **bo_array, int count); +    int (*check_aperture_space)(drm_intel_bo **bo_array, int count);      int debug; /**< Enables verbose debugging printouts */  };  | 
