Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2012-2013 LunarG, Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include <string.h>
  29. #include <errno.h>
  30. #ifndef ETIME
  31. #define ETIME ETIMEDOUT
  32. #endif
  33.  
  34. #include <xf86drm.h>
  35. #include <i915_drm.h>
  36. #include <intel_bufmgr.h>
  37.  
  38. #include "state_tracker/drm_driver.h"
  39. #include "pipe/p_state.h"
  40. #include "util/u_inlines.h"
  41. #include "util/u_memory.h"
  42. #include "util/u_debug.h"
  43. #include "../intel_winsys.h"
  44.  
  45. #define BATCH_SZ (8192 * sizeof(uint32_t))
  46.  
  47. struct intel_winsys {
  48.    int fd;
  49.    drm_intel_bufmgr *bufmgr;
  50.    struct intel_winsys_info info;
  51.  
  52.    struct drm_intel_decode *decode;
  53. };
  54.  
  55. static bool
  56. get_param(struct intel_winsys *winsys, int param, int *value)
  57. {
  58.    struct drm_i915_getparam gp;
  59.    int err;
  60.  
  61.    *value = 0;
  62.  
  63.    memset(&gp, 0, sizeof(gp));
  64.    gp.param = param;
  65.    gp.value = value;
  66.  
  67.    err = drmCommandWriteRead(winsys->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
  68.    if (err) {
  69.       *value = 0;
  70.       return false;
  71.    }
  72.  
  73.    return true;
  74. }
  75.  
  76. static bool
  77. test_address_swizzling(struct intel_winsys *winsys)
  78. {
  79.    drm_intel_bo *bo;
  80.    uint32_t tiling = I915_TILING_X, swizzle;
  81.    unsigned long pitch;
  82.  
  83.    bo = drm_intel_bo_alloc_tiled(winsys->bufmgr,
  84.          "address swizzling test", 64, 64, 4, &tiling, &pitch, 0);
  85.    if (bo) {
  86.       drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
  87.       drm_intel_bo_unreference(bo);
  88.    }
  89.    else {
  90.       swizzle = I915_BIT_6_SWIZZLE_NONE;
  91.    }
  92.  
  93.    return (swizzle != I915_BIT_6_SWIZZLE_NONE);
  94. }
  95.  
  96. static bool
  97. init_info(struct intel_winsys *winsys)
  98. {
  99.    struct intel_winsys_info *info = &winsys->info;
  100.    int val;
  101.  
  102.    /* follow the classic driver here */
  103.    get_param(winsys, I915_PARAM_HAS_RELAXED_DELTA, &val);
  104.    if (!val) {
  105.       debug_error("kernel 2.6.39 required");
  106.       return false;
  107.    }
  108.  
  109.    info->devid = drm_intel_bufmgr_gem_get_devid(winsys->bufmgr);
  110.  
  111.    get_param(winsys, I915_PARAM_HAS_LLC, &val);
  112.    info->has_llc = val;
  113.  
  114.    get_param(winsys, I915_PARAM_HAS_GEN7_SOL_RESET, &val);
  115.    info->has_gen7_sol_reset = val;
  116.  
  117.    info->has_address_swizzling = test_address_swizzling(winsys);
  118.  
  119.    return true;
  120. }
  121.  
  122. struct intel_winsys *
  123. intel_winsys_create_for_fd(int fd)
  124. {
  125.    struct intel_winsys *winsys;
  126.  
  127.    winsys = CALLOC_STRUCT(intel_winsys);
  128.    if (!winsys)
  129.       return NULL;
  130.  
  131.    winsys->fd = fd;
  132.  
  133.    winsys->bufmgr = drm_intel_bufmgr_gem_init(winsys->fd, BATCH_SZ);
  134.    if (!winsys->bufmgr) {
  135.       debug_error("failed to create GEM buffer manager");
  136.       FREE(winsys);
  137.       return NULL;
  138.    }
  139.  
  140.    if (!init_info(winsys)) {
  141.       drm_intel_bufmgr_destroy(winsys->bufmgr);
  142.       FREE(winsys);
  143.       return NULL;
  144.    }
  145.  
  146.    drm_intel_bufmgr_gem_enable_fenced_relocs(winsys->bufmgr);
  147.  
  148.    return winsys;
  149. }
  150.  
  151. void
  152. intel_winsys_destroy(struct intel_winsys *winsys)
  153. {
  154.    if (winsys->decode)
  155.       drm_intel_decode_context_free(winsys->decode);
  156.  
  157.    drm_intel_bufmgr_destroy(winsys->bufmgr);
  158.    FREE(winsys);
  159. }
  160.  
  161. const struct intel_winsys_info *
  162. intel_winsys_get_info(const struct intel_winsys *winsys)
  163. {
  164.    return &winsys->info;
  165. }
  166.  
  167. void
  168. intel_winsys_enable_reuse(struct intel_winsys *winsys)
  169. {
  170.    drm_intel_bufmgr_gem_enable_reuse(winsys->bufmgr);
  171. }
  172.  
  173. struct intel_context *
  174. intel_winsys_create_context(struct intel_winsys *winsys)
  175. {
  176.    return (struct intel_context *)
  177.       drm_intel_gem_context_create(winsys->bufmgr);
  178. }
  179.  
  180. void
  181. intel_winsys_destroy_context(struct intel_winsys *winsys,
  182.                              struct intel_context *ctx)
  183. {
  184.    drm_intel_gem_context_destroy((drm_intel_context *) ctx);
  185. }
  186.  
  187. int
  188. intel_winsys_read_reg(struct intel_winsys *winsys,
  189.                       uint32_t reg, uint64_t *val)
  190. {
  191.    return drm_intel_reg_read(winsys->bufmgr, reg, val);
  192. }
  193.  
  194. struct intel_bo *
  195. intel_winsys_alloc_buffer(struct intel_winsys *winsys,
  196.                           const char *name,
  197.                           unsigned long size,
  198.                           unsigned long flags)
  199. {
  200.    const int alignment = 4096; /* always page-aligned */
  201.    drm_intel_bo *bo;
  202.  
  203.    if (flags == INTEL_ALLOC_FOR_RENDER) {
  204.       bo = drm_intel_bo_alloc_for_render(winsys->bufmgr,
  205.             name, size, alignment);
  206.    }
  207.    else {
  208.       assert(!flags);
  209.       bo = drm_intel_bo_alloc(winsys->bufmgr, name, size, alignment);
  210.    }
  211.  
  212.    return (struct intel_bo *) bo;
  213. }
  214.  
  215. struct intel_bo *
  216. intel_winsys_alloc_texture(struct intel_winsys *winsys,
  217.                            const char *name,
  218.                            int width, int height, int cpp,
  219.                            enum intel_tiling_mode tiling,
  220.                            unsigned long flags,
  221.                            unsigned long *pitch)
  222. {
  223.    uint32_t real_tiling = tiling;
  224.    drm_intel_bo *bo;
  225.  
  226.    bo = drm_intel_bo_alloc_tiled(winsys->bufmgr, name,
  227.          width, height, cpp, &real_tiling, pitch, flags);
  228.    if (!bo)
  229.       return NULL;
  230.  
  231.    if (real_tiling != tiling) {
  232.       assert(!"tiling mismatch");
  233.       drm_intel_bo_unreference(bo);
  234.       return NULL;
  235.    }
  236.  
  237.    return (struct intel_bo *) bo;
  238. }
  239.  
  240. struct intel_bo *
  241. intel_winsys_import_handle(struct intel_winsys *winsys,
  242.                            const char *name,
  243.                            const struct winsys_handle *handle,
  244.                            int width, int height, int cpp,
  245.                            enum intel_tiling_mode *tiling,
  246.                            unsigned long *pitch)
  247. {
  248.    uint32_t real_tiling, swizzle;
  249.    drm_intel_bo *bo;
  250.    int err;
  251.  
  252.    switch (handle->type) {
  253.    case DRM_API_HANDLE_TYPE_SHARED:
  254.       {
  255.          const uint32_t gem_name = handle->handle;
  256.          bo = drm_intel_bo_gem_create_from_name(winsys->bufmgr,
  257.                name, gem_name);
  258.       }
  259.       break;
  260. #if 0
  261.    case DRM_API_HANDLE_TYPE_FD:
  262.       {
  263.          const int fd = (int) handle->handle;
  264.          bo = drm_intel_bo_gem_create_from_prime(winsys->bufmgr,
  265.                fd, height * handle->stride);
  266.       }
  267.       break;
  268. #endif
  269.    default:
  270.       bo = NULL;
  271.       break;
  272.    }
  273.  
  274.    if (!bo)
  275.       return NULL;
  276.  
  277.    err = drm_intel_bo_get_tiling(bo, &real_tiling, &swizzle);
  278.    if (err) {
  279.       drm_intel_bo_unreference(bo);
  280.       return NULL;
  281.    }
  282.  
  283.    *tiling = real_tiling;
  284.    *pitch = handle->stride;
  285.  
  286.    return (struct intel_bo *) bo;
  287. }
  288.  
  289. int
  290. intel_winsys_export_handle(struct intel_winsys *winsys,
  291.                            struct intel_bo *bo,
  292.                            enum intel_tiling_mode tiling,
  293.                            unsigned long pitch,
  294.                            struct winsys_handle *handle)
  295. {
  296.    int err = 0;
  297.  
  298.    switch (handle->type) {
  299.    case DRM_API_HANDLE_TYPE_SHARED:
  300.       {
  301.          uint32_t name;
  302.  
  303.          err = drm_intel_bo_flink((drm_intel_bo *) bo, &name);
  304.          if (!err)
  305.             handle->handle = name;
  306.       }
  307.       break;
  308.    case DRM_API_HANDLE_TYPE_KMS:
  309.       handle->handle = ((drm_intel_bo *) bo)->handle;
  310.       break;
  311. #if 0
  312.    case DRM_API_HANDLE_TYPE_FD:
  313.       {
  314.          int fd;
  315.  
  316.          err = drm_intel_bo_gem_export_to_prime((drm_intel_bo *) bo, &fd);
  317.          if (!err)
  318.             handle->handle = fd;
  319.       }
  320.       break;
  321. #endif
  322.    default:
  323.       err = -EINVAL;
  324.       break;
  325.    }
  326.  
  327.    if (err)
  328.       return err;
  329.  
  330.    handle->stride = pitch;
  331.  
  332.    return 0;
  333. }
  334.  
  335. int
  336. intel_winsys_check_aperture_space(struct intel_winsys *winsys,
  337.                                   struct intel_bo **bo_array,
  338.                                   int count)
  339. {
  340.    return drm_intel_bufmgr_check_aperture_space((drm_intel_bo **) bo_array,
  341.                                                 count);
  342. }
  343.  
  344. void
  345. intel_winsys_decode_commands(struct intel_winsys *winsys,
  346.                              struct intel_bo *bo, int used)
  347. {
  348.    int err;
  349.  
  350.    if (!winsys->decode) {
  351.       winsys->decode = drm_intel_decode_context_alloc(winsys->info.devid);
  352.       if (!winsys->decode)
  353.          return;
  354.  
  355.       /* debug_printf()/debug_error() uses stderr by default */
  356.       drm_intel_decode_set_output_file(winsys->decode, stderr);
  357.    }
  358.  
  359.    err = intel_bo_map(bo, false);
  360.    if (err) {
  361.       debug_printf("failed to map buffer for decoding\n");
  362.       return;
  363.    }
  364.  
  365.    /* in dwords */
  366.    used /= 4;
  367.  
  368.    drm_intel_decode_set_batch_pointer(winsys->decode,
  369.          intel_bo_get_virtual(bo), intel_bo_get_offset(bo), used);
  370.  
  371.    drm_intel_decode(winsys->decode);
  372.  
  373.    intel_bo_unmap(bo);
  374. }
  375.  
  376. void
  377. intel_bo_reference(struct intel_bo *bo)
  378. {
  379.    drm_intel_bo_reference((drm_intel_bo *) bo);
  380. }
  381.  
  382. void
  383. intel_bo_unreference(struct intel_bo *bo)
  384. {
  385.    drm_intel_bo_unreference((drm_intel_bo *) bo);
  386. }
  387.  
  388. unsigned long
  389. intel_bo_get_size(const struct intel_bo *bo)
  390. {
  391.    return ((drm_intel_bo *) bo)->size;
  392. }
  393.  
  394. unsigned long
  395. intel_bo_get_offset(const struct intel_bo *bo)
  396. {
  397.    return ((drm_intel_bo *) bo)->offset;
  398. }
  399.  
  400. void *
  401. intel_bo_get_virtual(const struct intel_bo *bo)
  402. {
  403.    return ((drm_intel_bo *) bo)->virtual;
  404. }
  405.  
  406. int
  407. intel_bo_map(struct intel_bo *bo, bool write_enable)
  408. {
  409.    return drm_intel_bo_map((drm_intel_bo *) bo, write_enable);
  410. }
  411.  
  412. int
  413. intel_bo_map_gtt(struct intel_bo *bo)
  414. {
  415.    return drm_intel_gem_bo_map_gtt((drm_intel_bo *) bo);
  416. }
  417.  
  418. int
  419. intel_bo_map_unsynchronized(struct intel_bo *bo)
  420. {
  421.    return drm_intel_gem_bo_map_unsynchronized((drm_intel_bo *) bo);
  422. }
  423.  
  424. void
  425. intel_bo_unmap(struct intel_bo *bo)
  426. {
  427.    int err;
  428.  
  429.    err = drm_intel_bo_unmap((drm_intel_bo *) bo);
  430.    assert(!err);
  431. }
  432.  
  433. int
  434. intel_bo_pwrite(struct intel_bo *bo, unsigned long offset,
  435.                 unsigned long size, const void *data)
  436. {
  437.    return drm_intel_bo_subdata((drm_intel_bo *) bo, offset, size, data);
  438. }
  439.  
  440. int
  441. intel_bo_pread(struct intel_bo *bo, unsigned long offset,
  442.                unsigned long size, void *data)
  443. {
  444.    return drm_intel_bo_get_subdata((drm_intel_bo *) bo, offset, size, data);
  445. }
  446.  
  447. int
  448. intel_bo_emit_reloc(struct intel_bo *bo, uint32_t offset,
  449.                     struct intel_bo *target_bo, uint32_t target_offset,
  450.                     uint32_t read_domains, uint32_t write_domain)
  451. {
  452.    return drm_intel_bo_emit_reloc((drm_intel_bo *) bo, offset,
  453.          (drm_intel_bo *) target_bo, target_offset,
  454.          read_domains, write_domain);
  455. }
  456.  
  457. int
  458. intel_bo_get_reloc_count(struct intel_bo *bo)
  459. {
  460.    return drm_intel_gem_bo_get_reloc_count((drm_intel_bo *) bo);
  461. }
  462.  
  463. void
  464. intel_bo_clear_relocs(struct intel_bo *bo, int start)
  465. {
  466.    return drm_intel_gem_bo_clear_relocs((drm_intel_bo *) bo, start);
  467. }
  468.  
  469. bool
  470. intel_bo_references(struct intel_bo *bo, struct intel_bo *target_bo)
  471. {
  472.    return drm_intel_bo_references((drm_intel_bo *) bo,
  473.          (drm_intel_bo *) target_bo);
  474. }
  475.  
  476. int
  477. intel_bo_exec(struct intel_bo *bo, int used,
  478.               struct intel_context *ctx, unsigned long flags)
  479. {
  480.    if (ctx) {
  481.       return drm_intel_gem_bo_context_exec((drm_intel_bo *) bo,
  482.             (drm_intel_context *) ctx, used, flags);
  483.    }
  484.    else {
  485.       return drm_intel_bo_mrb_exec((drm_intel_bo *) bo,
  486.             used, NULL, 0, 0, flags);
  487.    }
  488. }
  489.  
  490. int
  491. intel_bo_wait(struct intel_bo *bo, int64_t timeout)
  492. {
  493.    int err;
  494.  
  495.    err = drm_intel_gem_bo_wait((drm_intel_bo *) bo, timeout);
  496.    /* consider the bo idle on errors */
  497.    if (err && err != -ETIME)
  498.       err = 0;
  499.  
  500.    return err;
  501. }
  502.