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. #ifndef ILO_CP_H
  29. #define ILO_CP_H
  30.  
  31. #include "intel_winsys.h"
  32.  
  33. #include "ilo_common.h"
  34.  
  35. struct ilo_cp;
  36.  
  37. enum ilo_cp_ring {
  38.    ILO_CP_RING_RENDER,
  39.    ILO_CP_RING_BLT,
  40.  
  41.    ILO_CP_RING_COUNT,
  42. };
  43.  
  44. typedef void (*ilo_cp_callback)(struct ilo_cp *cp, void *data);
  45.  
  46. struct ilo_cp_owner {
  47.    ilo_cp_callback release_callback;
  48.    void *release_data;
  49. };
  50.  
  51. /**
  52.  * Command parser.
  53.  */
  54. struct ilo_cp {
  55.    struct intel_winsys *winsys;
  56.    struct intel_context *render_ctx;
  57.  
  58.    ilo_cp_callback flush_callback;
  59.    void *flush_callback_data;
  60.  
  61.    const struct ilo_cp_owner *owner;
  62.    int owner_reserve;
  63.  
  64.    enum ilo_cp_ring ring;
  65.    bool no_implicit_flush;
  66.    unsigned one_off_flags;
  67.  
  68.    int bo_size;
  69.    struct intel_bo *bo;
  70.    uint32_t *sys;
  71.  
  72.    uint32_t *ptr;
  73.    int size, used, stolen;
  74.  
  75.    int cmd_cur, cmd_end;
  76. };
  77.  
  78. /**
  79.  * Jump buffer to save command parser state for rewind.
  80.  */
  81. struct ilo_cp_jmp_buf {
  82.    intptr_t id;
  83.    int size, used, stolen;
  84.    int reloc_count;
  85. };
  86.  
  87. struct ilo_cp *
  88. ilo_cp_create(struct intel_winsys *winsys, bool direct_map);
  89.  
  90. void
  91. ilo_cp_destroy(struct ilo_cp *cp);
  92.  
  93. void
  94. ilo_cp_flush(struct ilo_cp *cp);
  95.  
  96. void
  97. ilo_cp_dump(struct ilo_cp *cp);
  98.  
  99. void
  100. ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp);
  101.  
  102. void
  103. ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp);
  104.  
  105. /**
  106.  * Return true if the parser buffer is empty.
  107.  */
  108. static inline bool
  109. ilo_cp_empty(struct ilo_cp *cp)
  110. {
  111.    return !cp->used;
  112. }
  113.  
  114. /**
  115.  * Return the remaining space (in dwords) in the parser buffer.
  116.  */
  117. static inline int
  118. ilo_cp_space(struct ilo_cp *cp)
  119. {
  120.    return cp->size - cp->used;
  121. }
  122.  
  123. /**
  124.  * Internal function called by functions that flush implicitly.
  125.  */
  126. static inline void
  127. ilo_cp_implicit_flush(struct ilo_cp *cp)
  128. {
  129.    if (cp->no_implicit_flush) {
  130.       assert(!"unexpected command parser flush");
  131.       /* discard the commands */
  132.       cp->used = 0;
  133.    }
  134.  
  135.    ilo_cp_flush(cp);
  136. }
  137.  
  138. /**
  139.  * Set the ring buffer.
  140.  */
  141. static inline void
  142. ilo_cp_set_ring(struct ilo_cp *cp, enum ilo_cp_ring ring)
  143. {
  144.    if (cp->ring != ring) {
  145.       ilo_cp_implicit_flush(cp);
  146.       cp->ring = ring;
  147.    }
  148. }
  149.  
  150. /**
  151.  * Assert that no function should flush implicitly.
  152.  */
  153. static inline void
  154. ilo_cp_assert_no_implicit_flush(struct ilo_cp *cp, bool enable)
  155. {
  156.    cp->no_implicit_flush = enable;
  157. }
  158.  
  159. /**
  160.  * Set one-off flags.  They will be cleared after flushing.
  161.  */
  162. static inline void
  163. ilo_cp_set_one_off_flags(struct ilo_cp *cp, unsigned flags)
  164. {
  165.    cp->one_off_flags |= flags;
  166. }
  167.  
  168. /**
  169.  * Set flush callback.  The callback is invoked after the bo has been
  170.  * successfully executed, and before the bo is reallocated.
  171.  */
  172. static inline void
  173. ilo_cp_set_flush_callback(struct ilo_cp *cp, ilo_cp_callback callback,
  174.                           void *data)
  175. {
  176.    cp->flush_callback = callback;
  177.    cp->flush_callback_data = data;
  178. }
  179.  
  180. /**
  181.  * Set the parser owner.  If this is a new owner, the previous owner is
  182.  * notified and the space it reserved is reclaimed.
  183.  *
  184.  * \return true if this is a new owner
  185.  */
  186. static inline bool
  187. ilo_cp_set_owner(struct ilo_cp *cp, const struct ilo_cp_owner *owner,
  188.                  int reserve)
  189. {
  190.    const bool new_owner = (cp->owner != owner);
  191.  
  192.    /* release current owner */
  193.    if (new_owner && cp->owner) {
  194.       const bool no_implicit_flush = cp->no_implicit_flush;
  195.  
  196.       /* reclaim the reserved space */
  197.       cp->size += cp->owner_reserve;
  198.       cp->owner_reserve = 0;
  199.  
  200.       /* invoke the release callback */
  201.       cp->no_implicit_flush = true;
  202.       cp->owner->release_callback(cp, cp->owner->release_data);
  203.       cp->no_implicit_flush = no_implicit_flush;
  204.  
  205.       cp->owner = NULL;
  206.    }
  207.  
  208.    if (cp->owner_reserve != reserve) {
  209.       const int extra = reserve - cp->owner_reserve;
  210.  
  211.       if (cp->used > cp->size - extra) {
  212.          ilo_cp_implicit_flush(cp);
  213.          assert(cp->used <= cp->size - reserve);
  214.  
  215.          cp->size -= reserve;
  216.          cp->owner_reserve = reserve;
  217.       }
  218.       else {
  219.          cp->size -= extra;
  220.          cp->owner_reserve += extra;
  221.       }
  222.    }
  223.  
  224.    /* set owner last because of the possible flush above */
  225.    cp->owner = owner;
  226.  
  227.    return new_owner;
  228. }
  229.  
  230. /**
  231.  * Begin writing a command.
  232.  */
  233. static inline void
  234. ilo_cp_begin(struct ilo_cp *cp, int cmd_size)
  235. {
  236.    if (cp->used + cmd_size > cp->size) {
  237.       ilo_cp_implicit_flush(cp);
  238.       assert(cp->used + cmd_size <= cp->size);
  239.    }
  240.  
  241.    assert(cp->cmd_cur == cp->cmd_end);
  242.    cp->cmd_cur = cp->used;
  243.    cp->cmd_end = cp->cmd_cur + cmd_size;
  244.    cp->used = cp->cmd_end;
  245. }
  246.  
  247. /**
  248.  * Begin writing data to a space stolen from the top of the parser buffer.
  249.  *
  250.  * \param desc informative description of the data to be written
  251.  * \param data_size in dwords
  252.  * \param align in dwords
  253.  * \param bo_offset in bytes to the stolen space
  254.  */
  255. static inline void
  256. ilo_cp_steal(struct ilo_cp *cp, const char *desc,
  257.              int data_size, int align, uint32_t *bo_offset)
  258. {
  259.    int pad, steal;
  260.  
  261.    if (!align)
  262.       align = 1;
  263.  
  264.    pad = (cp->bo_size - cp->stolen - data_size) % align;
  265.    steal = data_size + pad;
  266.  
  267.    /* flush if there is not enough space after stealing */
  268.    if (cp->used > cp->size - steal) {
  269.       ilo_cp_implicit_flush(cp);
  270.  
  271.       pad = (cp->bo_size - cp->stolen - data_size) % align;
  272.       steal = data_size + steal;
  273.  
  274.       assert(cp->used <= cp->size - steal);
  275.    }
  276.  
  277.    cp->size -= steal;
  278.    cp->stolen += steal;
  279.  
  280.    assert(cp->cmd_cur == cp->cmd_end);
  281.    cp->cmd_cur = cp->bo_size - cp->stolen;
  282.    cp->cmd_end = cp->cmd_cur + data_size;
  283.  
  284.    /* offset in cp->bo */
  285.    if (bo_offset)
  286.       *bo_offset = cp->cmd_cur * 4;
  287. }
  288.  
  289. /**
  290.  * Write a dword to the parser buffer.  This function must be enclosed by
  291.  * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
  292.  */
  293. static inline void
  294. ilo_cp_write(struct ilo_cp *cp, uint32_t val)
  295. {
  296.    assert(cp->cmd_cur < cp->cmd_end);
  297.    cp->ptr[cp->cmd_cur++] = val;
  298. }
  299.  
  300. /**
  301.  * Write multiple dwords to the parser buffer.
  302.  */
  303. static inline void
  304. ilo_cp_write_multi(struct ilo_cp *cp, const void *vals, int num_vals)
  305. {
  306.    assert(cp->cmd_cur + num_vals <= cp->cmd_end);
  307.    memcpy(cp->ptr + cp->cmd_cur, vals, num_vals * 4);
  308.    cp->cmd_cur += num_vals;
  309. }
  310.  
  311. /**
  312.  * Write a bo to the parser buffer.  In addition to writing the offset of the
  313.  * bo to the buffer, it also emits a relocation.
  314.  */
  315. static inline void
  316. ilo_cp_write_bo(struct ilo_cp *cp, uint32_t val, struct intel_bo *bo,
  317.                 uint32_t read_domains, uint32_t write_domain)
  318. {
  319.    if (bo) {
  320.       intel_bo_emit_reloc(cp->bo, cp->cmd_cur * 4,
  321.             bo, val, read_domains, write_domain);
  322.  
  323.       ilo_cp_write(cp, val + intel_bo_get_offset(bo));
  324.    }
  325.    else {
  326.       ilo_cp_write(cp, val);
  327.    }
  328. }
  329.  
  330. /**
  331.  * End a command.  Every ilo_cp_begin() or ilo_cp_steal() must have a
  332.  * matching ilo_cp_end().
  333.  */
  334. static inline void
  335. ilo_cp_end(struct ilo_cp *cp)
  336. {
  337.    assert(cp->cmd_cur == cp->cmd_end);
  338. }
  339.  
  340. /**
  341.  * A variant of ilo_cp_steal() where the data are written via the returned
  342.  * pointer.
  343.  *
  344.  * \return ptr pointer where the data are written to.  It is valid until any
  345.  *             change is made to the parser.
  346.  */
  347. static inline void *
  348. ilo_cp_steal_ptr(struct ilo_cp *cp, const char *desc,
  349.                  int data_size, int align, uint32_t *bo_offset)
  350. {
  351.    void *ptr;
  352.  
  353.    ilo_cp_steal(cp, desc, data_size, align, bo_offset);
  354.  
  355.    ptr = &cp->ptr[cp->cmd_cur];
  356.    cp->cmd_cur = cp->cmd_end;
  357.  
  358.    ilo_cp_end(cp);
  359.  
  360.    return ptr;
  361. }
  362.  
  363. #endif /* ILO_CP_H */
  364.