Home | History | Annotate | Download | only in drm
      1 
      2 #include "i915_drm_winsys.h"
      3 #include "util/u_memory.h"
      4 
      5 #include "i915_drm.h"
      6 #include "i915/i915_debug.h"
      7 #include <xf86drm.h>
      8 #include <stdio.h>
      9 
     10 #define BATCH_RESERVED 16
     11 
     12 #define INTEL_DEFAULT_RELOCS 100
     13 #define INTEL_MAX_RELOCS 400
     14 
     15 #define INTEL_BATCH_NO_CLIPRECTS 0x1
     16 #define INTEL_BATCH_CLIPRECTS    0x2
     17 
     18 #undef INTEL_RUN_SYNC
     19 
     20 struct i915_drm_batchbuffer
     21 {
     22    struct i915_winsys_batchbuffer base;
     23 
     24    size_t actual_size;
     25 
     26    drm_intel_bo *bo;
     27 };
     28 
     29 static INLINE struct i915_drm_batchbuffer *
     30 i915_drm_batchbuffer(struct i915_winsys_batchbuffer *batch)
     31 {
     32    return (struct i915_drm_batchbuffer *)batch;
     33 }
     34 
     35 static void
     36 i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch)
     37 {
     38    struct i915_drm_winsys *idws = i915_drm_winsys(batch->base.iws);
     39 
     40    if (batch->bo)
     41       drm_intel_bo_unreference(batch->bo);
     42    batch->bo = drm_intel_bo_alloc(idws->gem_manager,
     43                                   "gallium3d_batchbuffer",
     44                                   batch->actual_size,
     45                                   4096);
     46 
     47    memset(batch->base.map, 0, batch->actual_size);
     48    batch->base.ptr = batch->base.map;
     49    batch->base.size = batch->actual_size - BATCH_RESERVED;
     50    batch->base.relocs = 0;
     51 }
     52 
     53 static struct i915_winsys_batchbuffer *
     54 i915_drm_batchbuffer_create(struct i915_winsys *iws)
     55 {
     56    struct i915_drm_winsys *idws = i915_drm_winsys(iws);
     57    struct i915_drm_batchbuffer *batch = CALLOC_STRUCT(i915_drm_batchbuffer);
     58 
     59    batch->actual_size = idws->max_batch_size;
     60 
     61    batch->base.map = MALLOC(batch->actual_size);
     62    batch->base.ptr = NULL;
     63    batch->base.size = 0;
     64 
     65    batch->base.relocs = 0;
     66 
     67    batch->base.iws = iws;
     68 
     69    i915_drm_batchbuffer_reset(batch);
     70 
     71    return &batch->base;
     72 }
     73 
     74 static boolean
     75 i915_drm_batchbuffer_validate_buffers(struct i915_winsys_batchbuffer *batch,
     76 				      struct i915_winsys_buffer **buffer,
     77 				      int num_of_buffers)
     78 {
     79    struct i915_drm_batchbuffer *drm_batch = i915_drm_batchbuffer(batch);
     80    drm_intel_bo *bos[num_of_buffers + 1];
     81    int i, ret;
     82 
     83    bos[0] = drm_batch->bo;
     84    for (i = 0; i < num_of_buffers; i++)
     85       bos[i+1] = intel_bo(buffer[i]);
     86 
     87    ret = drm_intel_bufmgr_check_aperture_space(bos, num_of_buffers);
     88    if (ret != 0)
     89       return FALSE;
     90 
     91    return TRUE;
     92 }
     93 
     94 static int
     95 i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch,
     96                             struct i915_winsys_buffer *buffer,
     97                             enum i915_winsys_buffer_usage usage,
     98                             unsigned pre_add, boolean fenced)
     99 {
    100    struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);
    101    unsigned write_domain = 0;
    102    unsigned read_domain = 0;
    103    unsigned offset;
    104    int ret = 0;
    105 
    106    switch (usage) {
    107    case I915_USAGE_SAMPLER:
    108       write_domain = 0;
    109       read_domain = I915_GEM_DOMAIN_SAMPLER;
    110       break;
    111    case I915_USAGE_RENDER:
    112       write_domain = I915_GEM_DOMAIN_RENDER;
    113       read_domain = I915_GEM_DOMAIN_RENDER;
    114       break;
    115    case I915_USAGE_2D_TARGET:
    116       write_domain = I915_GEM_DOMAIN_RENDER;
    117       read_domain = I915_GEM_DOMAIN_RENDER;
    118       break;
    119    case I915_USAGE_2D_SOURCE:
    120       write_domain = 0;
    121       read_domain = I915_GEM_DOMAIN_RENDER;
    122       break;
    123    case I915_USAGE_VERTEX:
    124       write_domain = 0;
    125       read_domain = I915_GEM_DOMAIN_VERTEX;
    126       break;
    127    default:
    128       assert(0);
    129       return -1;
    130    }
    131 
    132    offset = (unsigned)(batch->base.ptr - batch->base.map);
    133 
    134    if (fenced)
    135       ret = drm_intel_bo_emit_reloc_fence(batch->bo, offset,
    136 				    intel_bo(buffer), pre_add,
    137 				    read_domain,
    138 				    write_domain);
    139    else
    140       ret = drm_intel_bo_emit_reloc(batch->bo, offset,
    141 				    intel_bo(buffer), pre_add,
    142 				    read_domain,
    143 				    write_domain);
    144 
    145    ((uint32_t*)batch->base.ptr)[0] = intel_bo(buffer)->offset + pre_add;
    146    batch->base.ptr += 4;
    147 
    148    if (!ret)
    149       batch->base.relocs++;
    150 
    151    return ret;
    152 }
    153 
    154 static void
    155 i915_drm_throttle(struct i915_drm_winsys *idws)
    156 {
    157    drmIoctl(idws->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL);
    158 }
    159 
    160 static void
    161 i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch,
    162                             struct pipe_fence_handle **fence)
    163 {
    164    struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);
    165    unsigned used;
    166    int ret;
    167 
    168    /* MI_BATCH_BUFFER_END */
    169    i915_winsys_batchbuffer_dword_unchecked(ibatch, (0xA<<23));
    170 
    171    used = batch->base.ptr - batch->base.map;
    172    if (used & 4) {
    173       /* MI_NOOP */
    174       i915_winsys_batchbuffer_dword_unchecked(ibatch, 0);
    175       used += 4;
    176    }
    177 
    178    /* Do the sending to HW */
    179    ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map);
    180    if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd)
    181       ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0);
    182 
    183    i915_drm_throttle(i915_drm_winsys(ibatch->iws));
    184 
    185    if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) {
    186       i915_dump_batchbuffer(ibatch);
    187       assert(ret == 0);
    188    }
    189 
    190    if (i915_drm_winsys(ibatch->iws)->dump_raw_file) {
    191       FILE *file = fopen(i915_drm_winsys(ibatch->iws)->dump_raw_file, "a");
    192       if (file) {
    193 	 fwrite(batch->base.map, used, 1, file);
    194 	 fclose(file);
    195       }
    196    }
    197 
    198 #ifdef INTEL_RUN_SYNC
    199    drm_intel_bo_wait_rendering(batch->bo);
    200 #endif
    201 
    202    if (fence) {
    203       ibatch->iws->fence_reference(ibatch->iws, fence, NULL);
    204 
    205 #ifdef INTEL_RUN_SYNC
    206       /* we run synced to GPU so just pass null */
    207       (*fence) = i915_drm_fence_create(NULL);
    208 #else
    209       (*fence) = i915_drm_fence_create(batch->bo);
    210 #endif
    211    }
    212 
    213    i915_drm_batchbuffer_reset(batch);
    214 }
    215 
    216 static void
    217 i915_drm_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch)
    218 {
    219    struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);
    220 
    221    if (batch->bo)
    222       drm_intel_bo_unreference(batch->bo);
    223 
    224    FREE(batch->base.map);
    225    FREE(batch);
    226 }
    227 
    228 void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws)
    229 {
    230    idws->base.batchbuffer_create = i915_drm_batchbuffer_create;
    231    idws->base.validate_buffers = i915_drm_batchbuffer_validate_buffers;
    232    idws->base.batchbuffer_reloc = i915_drm_batchbuffer_reloc;
    233    idws->base.batchbuffer_flush = i915_drm_batchbuffer_flush;
    234    idws->base.batchbuffer_destroy = i915_drm_batchbuffer_destroy;
    235 }
    236