Subversion Repositories Kolibri OS

Rev

Rev 4358 | 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 = drmIoctl(winsys->fd, DRM_I915_GETPARAM, &gp);
  68.  
  69.    if (err) {
  70.       *value = 0;
  71.       return false;
  72.    }
  73.  
  74.    return true;
  75. }
  76.  
  77. static bool
  78. test_address_swizzling(struct intel_winsys *winsys)
  79. {
  80.    drm_intel_bo *bo;
  81.    uint32_t tiling = I915_TILING_X, swizzle;
  82.    unsigned long pitch;
  83.  
  84.    bo = drm_intel_bo_alloc_tiled(winsys->bufmgr,
  85.          "address swizzling test", 64, 64, 4, &tiling, &pitch, 0);
  86.    if (bo) {
  87.       drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
  88.       drm_intel_bo_unreference(bo);
  89.    }
  90.    else {
  91.       swizzle = I915_BIT_6_SWIZZLE_NONE;
  92.    }
  93.  
  94.    return (swizzle != I915_BIT_6_SWIZZLE_NONE);
  95. }
  96.  
  97. static bool
  98. init_info(struct intel_winsys *winsys)
  99. {
  100.    struct intel_winsys_info *info = &winsys->info;
  101.    int val;
  102.  
  103.    /* follow the classic driver here */
  104.    get_param(winsys, I915_PARAM_HAS_RELAXED_DELTA, &val);
  105.    if (!val) {
  106.       debug_error("kernel 2.6.39 required");
  107.       return false;
  108.    }
  109.  
  110.    info->devid = drm_intel_bufmgr_gem_get_devid(winsys->bufmgr);
  111.  
  112.    get_param(winsys, I915_PARAM_HAS_LLC, &val);
  113.    info->has_llc = val;
  114.  
  115.    get_param(winsys, I915_PARAM_HAS_GEN7_SOL_RESET, &val);
  116.    info->has_gen7_sol_reset = val;
  117.  
  118.    info->has_address_swizzling = test_address_swizzling(winsys);
  119.  
  120.    return true;
  121. }
  122.  
  123. struct intel_winsys *
  124. intel_winsys_create_for_fd(int fd)
  125. {
  126.    struct intel_winsys *winsys;
  127.  
  128.    winsys = CALLOC_STRUCT(intel_winsys);
  129.    if (!winsys)
  130.       return NULL;
  131.  
  132.    winsys->fd = fd;
  133.  
  134.    winsys->bufmgr = drm_intel_bufmgr_gem_init(winsys->fd, BATCH_SZ);
  135.    if (!winsys->bufmgr) {
  136.       debug_error("failed to create GEM buffer manager");
  137.       FREE(winsys);
  138.       return NULL;
  139.    }
  140.  
  141.    if (!init_info(winsys)) {
  142.       drm_intel_bufmgr_destroy(winsys->bufmgr);
  143.       FREE(winsys);
  144.       return NULL;
  145.    }
  146.  
  147.    drm_intel_bufmgr_gem_enable_fenced_relocs(winsys->bufmgr);
  148.  
  149.    return winsys;
  150. }
  151.  
  152. void
  153. intel_winsys_destroy(struct intel_winsys *winsys)
  154. {
  155. //   if (winsys->decode)
  156. //      drm_intel_decode_context_free(winsys->decode);
  157.  
  158.    drm_intel_bufmgr_destroy(winsys->bufmgr);
  159.    FREE(winsys);
  160. }
  161.  
  162. const struct intel_winsys_info *
  163. intel_winsys_get_info(const struct intel_winsys *winsys)
  164. {
  165.    return &winsys->info;
  166. }
  167.  
  168. void
  169. intel_winsys_enable_reuse(struct intel_winsys *winsys)
  170. {
  171.    drm_intel_bufmgr_gem_enable_reuse(winsys->bufmgr);
  172. }
  173.  
  174. struct intel_context *
  175. intel_winsys_create_context(struct intel_winsys *winsys)
  176. {
  177.    return (struct intel_context *)
  178.       drm_intel_gem_context_create(winsys->bufmgr);
  179. }
  180.  
  181. void
  182. intel_winsys_destroy_context(struct intel_winsys *winsys,
  183.                              struct intel_context *ctx)
  184. {
  185.    drm_intel_gem_context_destroy((drm_intel_context *) ctx);
  186. }
  187.  
  188. int
  189. intel_winsys_read_reg(struct intel_winsys *winsys,
  190.                       uint32_t reg, uint64_t *val)
  191. {
  192.    return drm_intel_reg_read(winsys->bufmgr, reg, val);
  193. }
  194.  
  195. struct intel_bo *
  196. intel_winsys_alloc_buffer(struct intel_winsys *winsys,
  197.                           const char *name,
  198.                           unsigned long size,
  199.                           unsigned long flags)
  200. {
  201.    const int alignment = 4096; /* always page-aligned */
  202.    drm_intel_bo *bo;
  203.  
  204.    if (flags == INTEL_ALLOC_FOR_RENDER) {
  205.       bo = drm_intel_bo_alloc_for_render(winsys->bufmgr,
  206.             name, size, alignment);
  207.    }
  208.    else {
  209.       assert(!flags);
  210.       bo = drm_intel_bo_alloc(winsys->bufmgr, name, size, alignment);
  211.    }
  212.  
  213.    return (struct intel_bo *) bo;
  214. }
  215.  
  216. struct intel_bo *
  217. intel_winsys_alloc_texture(struct intel_winsys *winsys,
  218.                            const char *name,
  219.                            int width, int height, int cpp,
  220.                            enum intel_tiling_mode tiling,
  221.                            unsigned long flags,
  222.                            unsigned long *pitch)
  223. {
  224.    uint32_t real_tiling = tiling;
  225.    drm_intel_bo *bo;
  226.  
  227.    bo = drm_intel_bo_alloc_tiled(winsys->bufmgr, name,
  228.          width, height, cpp, &real_tiling, pitch, flags);
  229.    if (!bo)
  230.       return NULL;
  231.  
  232.    if (real_tiling != tiling) {
  233.       assert(!"tiling mismatch");
  234.       drm_intel_bo_unreference(bo);
  235.       return NULL;
  236.    }
  237.  
  238.    return (struct intel_bo *) bo;
  239. }
  240.  
  241. struct intel_bo *
  242. intel_winsys_import_handle(struct intel_winsys *winsys,
  243.                            const char *name,
  244.                            const struct winsys_handle *handle,
  245.                            int width, int height, int cpp,
  246.                            enum intel_tiling_mode *tiling,
  247.                            unsigned long *pitch)
  248. {
  249.    uint32_t real_tiling, swizzle;
  250.    drm_intel_bo *bo;
  251.    int err;
  252.  
  253.    switch (handle->type) {
  254.    case DRM_API_HANDLE_TYPE_SHARED:
  255.       {
  256.          const uint32_t gem_name = handle->handle;
  257.          bo = drm_intel_bo_gem_create_from_name(winsys->bufmgr,
  258.                name, gem_name);
  259.       }
  260.       break;
  261. #if 0
  262.    case DRM_API_HANDLE_TYPE_FD:
  263.       {
  264.          const int fd = (int) handle->handle;
  265.          bo = drm_intel_bo_gem_create_from_prime(winsys->bufmgr,
  266.                fd, height * handle->stride);
  267.       }
  268.       break;
  269. #endif
  270.    default:
  271.       bo = NULL;
  272.       break;
  273.    }
  274.  
  275.    if (!bo)
  276.       return NULL;
  277.  
  278.    err = drm_intel_bo_get_tiling(bo, &real_tiling, &swizzle);
  279.    if (err) {
  280.       drm_intel_bo_unreference(bo);
  281.       return NULL;
  282.    }
  283.  
  284.    *tiling = real_tiling;
  285.    *pitch = handle->stride;
  286.  
  287.    return (struct intel_bo *) bo;
  288. }
  289.  
  290. int
  291. intel_winsys_export_handle(struct intel_winsys *winsys,
  292.                            struct intel_bo *bo,
  293.                            enum intel_tiling_mode tiling,
  294.                            unsigned long pitch,
  295.                            struct winsys_handle *handle)
  296. {
  297.    int err = 0;
  298.  
  299.    switch (handle->type) {
  300.    case DRM_API_HANDLE_TYPE_SHARED:
  301.       {
  302.          uint32_t name;
  303.  
  304.          err = drm_intel_bo_flink((drm_intel_bo *) bo, &name);
  305.          if (!err)
  306.             handle->handle = name;
  307.       }
  308.       break;
  309.    case DRM_API_HANDLE_TYPE_KMS:
  310.       handle->handle = ((drm_intel_bo *) bo)->handle;
  311.       break;
  312. #if 0
  313.    case DRM_API_HANDLE_TYPE_FD:
  314.       {
  315.          int fd;
  316.  
  317.          err = drm_intel_bo_gem_export_to_prime((drm_intel_bo *) bo, &fd);
  318.          if (!err)
  319.             handle->handle = fd;
  320.       }
  321.       break;
  322. #endif
  323.    default:
  324.       err = -EINVAL;
  325.       break;
  326.    }
  327.  
  328.    if (err)
  329.       return err;
  330.  
  331.    handle->stride = pitch;
  332.  
  333.    return 0;
  334. }
  335.  
  336. int
  337. intel_winsys_check_aperture_space(struct intel_winsys *winsys,
  338.                                   struct intel_bo **bo_array,
  339.                                   int count)
  340. {
  341.    return drm_intel_bufmgr_check_aperture_space((drm_intel_bo **) bo_array,
  342.                                                 count);
  343. }
  344.  
  345. #if 0
  346. void
  347. intel_winsys_decode_commands(struct intel_winsys *winsys,
  348.                              struct intel_bo *bo, int used)
  349. {
  350.    int err;
  351.  
  352.    if (!winsys->decode) {
  353.       winsys->decode = drm_intel_decode_context_alloc(winsys->info.devid);
  354.       if (!winsys->decode)
  355.          return;
  356.  
  357.       /* debug_printf()/debug_error() uses stderr by default */
  358.       drm_intel_decode_set_output_file(winsys->decode, stderr);
  359.    }
  360.  
  361.    err = intel_bo_map(bo, false);
  362.    if (err) {
  363.       debug_printf("failed to map buffer for decoding\n");
  364.       return;
  365.    }
  366.  
  367.    /* in dwords */
  368.    used /= 4;
  369.  
  370.    drm_intel_decode_set_batch_pointer(winsys->decode,
  371.          intel_bo_get_virtual(bo), intel_bo_get_offset(bo), used);
  372.  
  373.    drm_intel_decode(winsys->decode);
  374.  
  375.    intel_bo_unmap(bo);
  376. }
  377. #endif
  378.  
  379. void
  380. intel_bo_reference(struct intel_bo *bo)
  381. {
  382.    drm_intel_bo_reference((drm_intel_bo *) bo);
  383. }
  384.  
  385. void
  386. intel_bo_unreference(struct intel_bo *bo)
  387. {
  388.    drm_intel_bo_unreference((drm_intel_bo *) bo);
  389. }
  390.  
  391. unsigned long
  392. intel_bo_get_size(const struct intel_bo *bo)
  393. {
  394.    return ((drm_intel_bo *) bo)->size;
  395. }
  396.  
  397. unsigned long
  398. intel_bo_get_offset(const struct intel_bo *bo)
  399. {
  400.    return ((drm_intel_bo *) bo)->offset;
  401. }
  402.  
  403. void *
  404. intel_bo_get_virtual(const struct intel_bo *bo)
  405. {
  406.    return ((drm_intel_bo *) bo)->virtual;
  407. }
  408.  
  409. int
  410. intel_bo_map(struct intel_bo *bo, bool write_enable)
  411. {
  412.    return drm_intel_bo_map((drm_intel_bo *) bo, write_enable);
  413. }
  414.  
  415. int
  416. intel_bo_map_gtt(struct intel_bo *bo)
  417. {
  418.    return drm_intel_gem_bo_map_gtt((drm_intel_bo *) bo);
  419. }
  420.  
  421. int
  422. intel_bo_map_unsynchronized(struct intel_bo *bo)
  423. {
  424.    return drm_intel_gem_bo_map_unsynchronized((drm_intel_bo *) bo);
  425. }
  426.  
  427. void
  428. intel_bo_unmap(struct intel_bo *bo)
  429. {
  430.    int err;
  431.  
  432.    err = drm_intel_bo_unmap((drm_intel_bo *) bo);
  433.    assert(!err);
  434. }
  435.  
  436. int
  437. intel_bo_pwrite(struct intel_bo *bo, unsigned long offset,
  438.                 unsigned long size, const void *data)
  439. {
  440.    return drm_intel_bo_subdata((drm_intel_bo *) bo, offset, size, data);
  441. }
  442.  
  443. int
  444. intel_bo_pread(struct intel_bo *bo, unsigned long offset,
  445.                unsigned long size, void *data)
  446. {
  447.    return drm_intel_bo_get_subdata((drm_intel_bo *) bo, offset, size, data);
  448. }
  449.  
  450. int
  451. intel_bo_emit_reloc(struct intel_bo *bo, uint32_t offset,
  452.                     struct intel_bo *target_bo, uint32_t target_offset,
  453.                     uint32_t read_domains, uint32_t write_domain)
  454. {
  455.    return drm_intel_bo_emit_reloc((drm_intel_bo *) bo, offset,
  456.          (drm_intel_bo *) target_bo, target_offset,
  457.          read_domains, write_domain);
  458. }
  459.  
  460. int
  461. intel_bo_get_reloc_count(struct intel_bo *bo)
  462. {
  463.    return drm_intel_gem_bo_get_reloc_count((drm_intel_bo *) bo);
  464. }
  465.  
  466. void
  467. intel_bo_clear_relocs(struct intel_bo *bo, int start)
  468. {
  469.    return drm_intel_gem_bo_clear_relocs((drm_intel_bo *) bo, start);
  470. }
  471.  
  472. bool
  473. intel_bo_references(struct intel_bo *bo, struct intel_bo *target_bo)
  474. {
  475.    return drm_intel_bo_references((drm_intel_bo *) bo,
  476.          (drm_intel_bo *) target_bo);
  477. }
  478.  
  479. int
  480. intel_bo_exec(struct intel_bo *bo, int used,
  481.               struct intel_context *ctx, unsigned long flags)
  482. {
  483.    if (ctx) {
  484.       return drm_intel_gem_bo_context_exec((drm_intel_bo *) bo,
  485.             (drm_intel_context *) ctx, used, flags);
  486.    }
  487.    else {
  488.       return drm_intel_bo_mrb_exec((drm_intel_bo *) bo,
  489.             used, NULL, 0, 0, flags);
  490.    }
  491. }
  492.  
  493. int
  494. intel_bo_wait(struct intel_bo *bo, int64_t timeout)
  495. {
  496.    int err;
  497.  
  498.    err = drm_intel_gem_bo_wait((drm_intel_bo *) bo, timeout);
  499.    /* consider the bo idle on errors */
  500.    if (err && err != -ETIME)
  501.       err = 0;
  502.  
  503.    return err;
  504. }
  505.