Home | History | Annotate | Download | only in drm
      1 #include "state_tracker/drm_driver.h"
      2 #include "i915_drm_winsys.h"
      3 #include "util/u_memory.h"
      4 
      5 #include "i915_drm.h"
      6 
      7 static char *i915_drm_type_to_name(enum i915_winsys_buffer_type type)
      8 {
      9    char *name;
     10 
     11    if (type == I915_NEW_TEXTURE) {
     12       name = "gallium3d_texture";
     13    } else if (type == I915_NEW_VERTEX) {
     14       name = "gallium3d_vertex";
     15    } else if (type == I915_NEW_SCANOUT) {
     16       name = "gallium3d_scanout";
     17    } else {
     18       assert(0);
     19       name = "gallium3d_unknown";
     20    }
     21 
     22    return name;
     23 }
     24 
     25 static struct i915_winsys_buffer *
     26 i915_drm_buffer_create(struct i915_winsys *iws,
     27                         unsigned size,
     28                         enum i915_winsys_buffer_type type)
     29 {
     30    struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer);
     31    struct i915_drm_winsys *idws = i915_drm_winsys(iws);
     32 
     33    if (!buf)
     34       return NULL;
     35 
     36    buf->magic = 0xDEAD1337;
     37    buf->flinked = FALSE;
     38    buf->flink = 0;
     39 
     40    buf->bo = drm_intel_bo_alloc(idws->gem_manager,
     41                                 i915_drm_type_to_name(type), size, 0);
     42 
     43    if (!buf->bo)
     44       goto err;
     45 
     46    return (struct i915_winsys_buffer *)buf;
     47 
     48 err:
     49    assert(0);
     50    FREE(buf);
     51    return NULL;
     52 }
     53 
     54 static struct i915_winsys_buffer *
     55 i915_drm_buffer_create_tiled(struct i915_winsys *iws,
     56                              unsigned *stride, unsigned height,
     57                              enum i915_winsys_buffer_tile *tiling,
     58                              enum i915_winsys_buffer_type type)
     59 {
     60    struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer);
     61    struct i915_drm_winsys *idws = i915_drm_winsys(iws);
     62    unsigned long pitch = 0;
     63    uint32_t tiling_mode = *tiling;
     64 
     65    if (!buf)
     66       return NULL;
     67 
     68    buf->magic = 0xDEAD1337;
     69    buf->flinked = FALSE;
     70    buf->flink = 0;
     71 
     72    buf->bo = drm_intel_bo_alloc_tiled(idws->gem_manager,
     73                                       i915_drm_type_to_name(type),
     74                                       *stride, height, 1,
     75                                       &tiling_mode, &pitch, 0);
     76 
     77    if (!buf->bo)
     78       goto err;
     79 
     80    *stride = pitch;
     81    *tiling = tiling_mode;
     82    return (struct i915_winsys_buffer *)buf;
     83 
     84 err:
     85    assert(0);
     86    FREE(buf);
     87    return NULL;
     88 }
     89 
     90 static struct i915_winsys_buffer *
     91 i915_drm_buffer_from_handle(struct i915_winsys *iws,
     92                             struct winsys_handle *whandle,
     93                             unsigned height,
     94                             enum i915_winsys_buffer_tile *tiling,
     95                             unsigned *stride)
     96 {
     97    struct i915_drm_winsys *idws = i915_drm_winsys(iws);
     98    struct i915_drm_buffer *buf;
     99    uint32_t tile = 0, swizzle = 0;
    100 
    101    if ((whandle->type != DRM_API_HANDLE_TYPE_SHARED) && (whandle->type != DRM_API_HANDLE_TYPE_FD))
    102       return NULL;
    103 
    104    if (whandle->offset != 0)
    105       return NULL;
    106 
    107    buf = CALLOC_STRUCT(i915_drm_buffer);
    108    if (!buf)
    109       return NULL;
    110 
    111    buf->magic = 0xDEAD1337;
    112 
    113    if (whandle->type == DRM_API_HANDLE_TYPE_SHARED)
    114        buf->bo = drm_intel_bo_gem_create_from_name(idws->gem_manager, "gallium3d_from_handle", whandle->handle);
    115    else if (whandle->type == DRM_API_HANDLE_TYPE_FD) {
    116        int fd = (int) whandle->handle;
    117        buf->bo = drm_intel_bo_gem_create_from_prime(idws->gem_manager, fd, height * whandle->stride);
    118    }
    119 
    120    buf->flinked = TRUE;
    121    buf->flink = whandle->handle;
    122 
    123    if (!buf->bo)
    124       goto err;
    125 
    126    drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle);
    127 
    128    *stride = whandle->stride;
    129    *tiling = tile;
    130 
    131    return (struct i915_winsys_buffer *)buf;
    132 
    133 err:
    134    FREE(buf);
    135    return NULL;
    136 }
    137 
    138 static boolean
    139 i915_drm_buffer_get_handle(struct i915_winsys *iws,
    140                             struct i915_winsys_buffer *buffer,
    141                             struct winsys_handle *whandle,
    142                             unsigned stride)
    143 {
    144    struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
    145 
    146    if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
    147       if (!buf->flinked) {
    148          if (drm_intel_bo_flink(buf->bo, &buf->flink))
    149             return FALSE;
    150          buf->flinked = TRUE;
    151       }
    152 
    153       whandle->handle = buf->flink;
    154    } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
    155       whandle->handle = buf->bo->handle;
    156    } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) {
    157       int fd;
    158 
    159       if (drm_intel_bo_gem_export_to_prime(buf->bo, &fd))
    160          return FALSE;
    161       whandle->handle = fd;
    162    } else {
    163       assert(!"unknown usage");
    164       return FALSE;
    165    }
    166 
    167    whandle->stride = stride;
    168    return TRUE;
    169 }
    170 
    171 static void *
    172 i915_drm_buffer_map(struct i915_winsys *iws,
    173                      struct i915_winsys_buffer *buffer,
    174                      boolean write)
    175 {
    176    struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
    177    drm_intel_bo *bo = intel_bo(buffer);
    178    int ret = 0;
    179 
    180    assert(bo);
    181 
    182    if (buf->map_count)
    183       goto out;
    184 
    185    ret = drm_intel_gem_bo_map_gtt(bo);
    186 
    187    buf->ptr = bo->virtual;
    188 
    189    assert(ret == 0);
    190 out:
    191    if (ret)
    192       return NULL;
    193 
    194    buf->map_count++;
    195    return buf->ptr;
    196 }
    197 
    198 static void
    199 i915_drm_buffer_unmap(struct i915_winsys *iws,
    200                        struct i915_winsys_buffer *buffer)
    201 {
    202    struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
    203 
    204    if (--buf->map_count)
    205       return;
    206 
    207    drm_intel_gem_bo_unmap_gtt(intel_bo(buffer));
    208 }
    209 
    210 static int
    211 i915_drm_buffer_write(struct i915_winsys *iws,
    212                        struct i915_winsys_buffer *buffer,
    213                        size_t offset,
    214                        size_t size,
    215                        const void *data)
    216 {
    217    struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
    218 
    219    return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
    220 }
    221 
    222 static void
    223 i915_drm_buffer_destroy(struct i915_winsys *iws,
    224                          struct i915_winsys_buffer *buffer)
    225 {
    226    drm_intel_bo_unreference(intel_bo(buffer));
    227 
    228 #ifdef DEBUG
    229    i915_drm_buffer(buffer)->magic = 0;
    230    i915_drm_buffer(buffer)->bo = NULL;
    231 #endif
    232 
    233    FREE(buffer);
    234 }
    235 
    236 static boolean
    237 i915_drm_buffer_is_busy(struct i915_winsys *iws,
    238                         struct i915_winsys_buffer *buffer)
    239 {
    240    struct i915_drm_buffer* i915_buffer = i915_drm_buffer(buffer);
    241    if (!i915_buffer)
    242       return FALSE;
    243    return drm_intel_bo_busy(i915_buffer->bo);
    244 }
    245 
    246 
    247 void
    248 i915_drm_winsys_init_buffer_functions(struct i915_drm_winsys *idws)
    249 {
    250    idws->base.buffer_create = i915_drm_buffer_create;
    251    idws->base.buffer_create_tiled = i915_drm_buffer_create_tiled;
    252    idws->base.buffer_from_handle = i915_drm_buffer_from_handle;
    253    idws->base.buffer_get_handle = i915_drm_buffer_get_handle;
    254    idws->base.buffer_map = i915_drm_buffer_map;
    255    idws->base.buffer_unmap = i915_drm_buffer_unmap;
    256    idws->base.buffer_write = i915_drm_buffer_write;
    257    idws->base.buffer_destroy = i915_drm_buffer_destroy;
    258    idws->base.buffer_is_busy = i915_drm_buffer_is_busy;
    259 }
    260