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 "intel_reg.h" /* for MI_xxx */
  29. #include "intel_winsys.h"
  30.  
  31. #include "ilo_cp.h"
  32.  
  33. /* the size of the private space */
  34. static const int ilo_cp_private = 2;
  35.  
  36. /**
  37.  * Dump the contents of the parser bo.  This can only be called in the flush
  38.  * callback.
  39.  */
  40. void
  41. ilo_cp_dump(struct ilo_cp *cp)
  42. {
  43.    ilo_printf("dumping %d bytes\n", cp->used * 4);
  44.    if (cp->used)
  45.       intel_winsys_decode_commands(cp->winsys, cp->bo, cp->used * 4);
  46. }
  47.  
  48. /**
  49.  * Save the command parser state for rewind.
  50.  *
  51.  * Note that this cannot rewind a flush, and the caller must make sure
  52.  * that does not happend.
  53.  */
  54. void
  55. ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp)
  56. {
  57.    jmp->id = pointer_to_intptr(cp->bo);
  58.  
  59.    jmp->size = cp->size;
  60.    jmp->used = cp->used;
  61.    jmp->stolen = cp->stolen;
  62.    /* save reloc count to rewind ilo_cp_write_bo() */
  63.    jmp->reloc_count = intel_bo_get_reloc_count(cp->bo);
  64. }
  65.  
  66. /**
  67.  * Rewind to the saved state.
  68.  */
  69. void
  70. ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp)
  71. {
  72.    if (jmp->id != pointer_to_intptr(cp->bo)) {
  73.       assert(!"invalid use of CP longjmp");
  74.       return;
  75.    }
  76.  
  77.    cp->size = jmp->size;
  78.    cp->used = jmp->used;
  79.    cp->stolen = jmp->stolen;
  80.    intel_bo_clear_relocs(cp->bo, jmp->reloc_count);
  81. }
  82.  
  83. /**
  84.  * Clear the parser buffer.
  85.  */
  86. static void
  87. ilo_cp_clear_buffer(struct ilo_cp *cp)
  88. {
  89.    cp->cmd_cur = 0;
  90.    cp->cmd_end = 0;
  91.  
  92.    cp->used = 0;
  93.    cp->stolen = 0;
  94.  
  95.    /*
  96.     * Recalculate cp->size.  This is needed not only because cp->stolen is
  97.     * reset above, but also that ilo_cp_private are added to cp->size in
  98.     * ilo_cp_end_buffer().
  99.     */
  100.    cp->size = cp->bo_size - ilo_cp_private;
  101. }
  102.  
  103. /**
  104.  * Add MI_BATCH_BUFFER_END to the private space of the parser buffer.
  105.  */
  106. static void
  107. ilo_cp_end_buffer(struct ilo_cp *cp)
  108. {
  109.    /* make the private space available */
  110.    cp->size += ilo_cp_private;
  111.  
  112.    assert(cp->used + 2 <= cp->size);
  113.  
  114.    cp->ptr[cp->used++] = MI_BATCH_BUFFER_END;
  115.  
  116.    /*
  117.     * From the Sandy Bridge PRM, volume 1 part 1, page 107:
  118.     *
  119.     *     "The batch buffer must be QWord aligned and a multiple of QWords in
  120.     *      length."
  121.     */
  122.    if (cp->used & 1)
  123.       cp->ptr[cp->used++] = MI_NOOP;
  124. }
  125.  
  126. /**
  127.  * Upload the parser buffer to the bo.
  128.  */
  129. static int
  130. ilo_cp_upload_buffer(struct ilo_cp *cp)
  131. {
  132.    int err;
  133.  
  134.    if (!cp->sys) {
  135.       intel_bo_unmap(cp->bo);
  136.       return 0;
  137.    }
  138.  
  139.    err = intel_bo_pwrite(cp->bo, 0, cp->used * 4, cp->ptr);
  140.    if (likely(!err && cp->stolen)) {
  141.       const int offset = cp->bo_size - cp->stolen;
  142.  
  143.       err = intel_bo_pwrite(cp->bo, offset * 4,
  144.             cp->stolen * 4, &cp->ptr[offset]);
  145.    }
  146.  
  147.    return err;
  148. }
  149.  
  150. /**
  151.  * Reallocate the parser bo.
  152.  */
  153. static void
  154. ilo_cp_realloc_bo(struct ilo_cp *cp)
  155. {
  156.    struct intel_bo *bo;
  157.  
  158.    /*
  159.     * allocate the new bo before unreferencing the old one so that they
  160.     * won't point at the same address, which is needed for jmpbuf
  161.     */
  162.    bo = intel_winsys_alloc_buffer(cp->winsys,
  163.          "batch buffer", cp->bo_size * 4, 0);
  164.    if (unlikely(!bo)) {
  165.       /* reuse the old one */
  166.       bo = cp->bo;
  167.       intel_bo_reference(bo);
  168.    }
  169.  
  170.    if (cp->bo)
  171.       intel_bo_unreference(cp->bo);
  172.    cp->bo = bo;
  173.  
  174.    if (!cp->sys) {
  175.       intel_bo_map(cp->bo, true);
  176.       cp->ptr = intel_bo_get_virtual(cp->bo);
  177.    }
  178. }
  179.  
  180. /**
  181.  * Execute the parser bo.
  182.  */
  183. static int
  184. ilo_cp_exec_bo(struct ilo_cp *cp)
  185. {
  186.    const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW);
  187.    struct intel_context *ctx;
  188.    unsigned long flags;
  189.    int err;
  190.  
  191.    switch (cp->ring) {
  192.    case ILO_CP_RING_RENDER:
  193.       ctx = cp->render_ctx;
  194.       flags = INTEL_EXEC_RENDER;
  195.       break;
  196.    case ILO_CP_RING_BLT:
  197.       ctx = NULL;
  198.       flags = INTEL_EXEC_BLT;
  199.       break;
  200.    default:
  201.       ctx = NULL;
  202.       flags = 0;
  203.       break;
  204.    }
  205.  
  206.    flags |= cp->one_off_flags;
  207.  
  208.    if (likely(do_exec))
  209.       err = intel_bo_exec(cp->bo, cp->used * 4, ctx, flags);
  210.    else
  211.       err = 0;
  212.  
  213.    cp->one_off_flags = 0;
  214.  
  215.    return err;
  216. }
  217.  
  218. /**
  219.  * Flush the command parser and execute the commands.  When the parser buffer
  220.  * is empty, the callback is not invoked.
  221.  */
  222. void
  223. ilo_cp_flush(struct ilo_cp *cp)
  224. {
  225.    int err;
  226.  
  227.    ilo_cp_set_owner(cp, NULL, 0);
  228.  
  229.    /* sanity check */
  230.    assert(cp->bo_size == cp->size + cp->stolen + ilo_cp_private);
  231.  
  232.    if (!cp->used) {
  233.       /* return the space stolen and etc. */
  234.       ilo_cp_clear_buffer(cp);
  235.  
  236.       return;
  237.    }
  238.  
  239.    ilo_cp_end_buffer(cp);
  240.  
  241.    /* upload and execute */
  242.    err = ilo_cp_upload_buffer(cp);
  243.    if (likely(!err))
  244.       err = ilo_cp_exec_bo(cp);
  245.  
  246.    if (likely(!err && cp->flush_callback))
  247.       cp->flush_callback(cp, cp->flush_callback_data);
  248.  
  249.    ilo_cp_clear_buffer(cp);
  250.    ilo_cp_realloc_bo(cp);
  251. }
  252.  
  253. /**
  254.  * Destroy the command parser.
  255.  */
  256. void
  257. ilo_cp_destroy(struct ilo_cp *cp)
  258. {
  259.    if (cp->bo) {
  260.       if (!cp->sys)
  261.          intel_bo_unmap(cp->bo);
  262.  
  263.       intel_bo_unreference(cp->bo);
  264.    }
  265.  
  266.    if (cp->render_ctx)
  267.       intel_winsys_destroy_context(cp->winsys, cp->render_ctx);
  268.  
  269.    FREE(cp->sys);
  270.    FREE(cp);
  271. }
  272.  
  273. /**
  274.  * Create a command parser.
  275.  */
  276. struct ilo_cp *
  277. ilo_cp_create(struct intel_winsys *winsys, bool direct_map)
  278. {
  279.    struct ilo_cp *cp;
  280.  
  281.    cp = CALLOC_STRUCT(ilo_cp);
  282.    if (!cp)
  283.       return NULL;
  284.  
  285.    cp->winsys = winsys;
  286.    cp->render_ctx = intel_winsys_create_context(winsys);
  287.  
  288.    cp->ring = ILO_CP_RING_RENDER;
  289.    cp->no_implicit_flush = false;
  290.  
  291.    cp->bo_size = 8192;
  292.  
  293.    if (!direct_map) {
  294.       cp->sys = MALLOC(cp->bo_size * 4);
  295.       if (!cp->sys) {
  296.          FREE(cp);
  297.          return NULL;
  298.       }
  299.  
  300.       cp->ptr = cp->sys;
  301.    }
  302.  
  303.    ilo_cp_realloc_bo(cp);
  304.    if (!cp->bo) {
  305.       FREE(cp->sys);
  306.       FREE(cp);
  307.       return NULL;
  308.    }
  309.  
  310.    ilo_cp_clear_buffer(cp);
  311.  
  312.    return cp;
  313. }
  314.