Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #ifndef U_INLINES_H
  29. #define U_INLINES_H
  30.  
  31. #include "pipe/p_context.h"
  32. #include "pipe/p_defines.h"
  33. #include "pipe/p_shader_tokens.h"
  34. #include "pipe/p_state.h"
  35. #include "pipe/p_screen.h"
  36. #include "util/u_debug.h"
  37. #include "util/u_debug_describe.h"
  38. #include "util/u_debug_refcnt.h"
  39. #include "util/u_atomic.h"
  40. #include "util/u_box.h"
  41. #include "util/u_math.h"
  42.  
  43.  
  44. #ifdef __cplusplus
  45. extern "C" {
  46. #endif
  47.  
  48.  
  49. /*
  50.  * Reference counting helper functions.
  51.  */
  52.  
  53.  
  54. static INLINE void
  55. pipe_reference_init(struct pipe_reference *reference, unsigned count)
  56. {
  57.    p_atomic_set(&reference->count, count);
  58. }
  59.  
  60. static INLINE boolean
  61. pipe_is_referenced(struct pipe_reference *reference)
  62. {
  63.    return p_atomic_read(&reference->count) != 0;
  64. }
  65.  
  66. /**
  67.  * Update reference counting.
  68.  * The old thing pointed to, if any, will be unreferenced.
  69.  * Both 'ptr' and 'reference' may be NULL.
  70.  * \return TRUE if the object's refcount hits zero and should be destroyed.
  71.  */
  72. static INLINE boolean
  73. pipe_reference_described(struct pipe_reference *ptr,
  74.                          struct pipe_reference *reference,
  75.                          debug_reference_descriptor get_desc)
  76. {
  77.    boolean destroy = FALSE;
  78.  
  79.    if(ptr != reference) {
  80.       /* bump the reference.count first */
  81.       if (reference) {
  82.          assert(pipe_is_referenced(reference));
  83.          p_atomic_inc(&reference->count);
  84.          debug_reference(reference, get_desc, 1);
  85.       }
  86.  
  87.       if (ptr) {
  88.          assert(pipe_is_referenced(ptr));
  89.          if (p_atomic_dec_zero(&ptr->count)) {
  90.             destroy = TRUE;
  91.          }
  92.          debug_reference(ptr, get_desc, -1);
  93.       }
  94.    }
  95.  
  96.    return destroy;
  97. }
  98.  
  99. static INLINE boolean
  100. pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
  101. {
  102.    return pipe_reference_described(ptr, reference,
  103.                                    (debug_reference_descriptor)debug_describe_reference);
  104. }
  105.  
  106. static INLINE void
  107. pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
  108. {
  109.    struct pipe_surface *old_surf = *ptr;
  110.  
  111.    if (pipe_reference_described(&(*ptr)->reference, &surf->reference,
  112.                                 (debug_reference_descriptor)debug_describe_surface))
  113.       old_surf->context->surface_destroy(old_surf->context, old_surf);
  114.    *ptr = surf;
  115. }
  116.  
  117. /**
  118.  * Similar to pipe_surface_reference() but always set the pointer to NULL
  119.  * and pass in an explicit context.  The explicit context avoids the problem
  120.  * of using a deleted context's surface_destroy() method when freeing a surface
  121.  * that's shared by multiple contexts.
  122.  */
  123. static INLINE void
  124. pipe_surface_release(struct pipe_context *pipe, struct pipe_surface **ptr)
  125. {
  126.    if (pipe_reference_described(&(*ptr)->reference, NULL,
  127.                                 (debug_reference_descriptor)debug_describe_surface))
  128.       pipe->surface_destroy(pipe, *ptr);
  129.    *ptr = NULL;
  130. }
  131.  
  132.  
  133. static INLINE void
  134. pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
  135. {
  136.    struct pipe_resource *old_tex = *ptr;
  137.  
  138.    if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
  139.                                 (debug_reference_descriptor)debug_describe_resource))
  140.       old_tex->screen->resource_destroy(old_tex->screen, old_tex);
  141.    *ptr = tex;
  142. }
  143.  
  144. static INLINE void
  145. pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
  146. {
  147.    struct pipe_sampler_view *old_view = *ptr;
  148.  
  149.    if (pipe_reference_described(&(*ptr)->reference, &view->reference,
  150.                                 (debug_reference_descriptor)debug_describe_sampler_view))
  151.       old_view->context->sampler_view_destroy(old_view->context, old_view);
  152.    *ptr = view;
  153. }
  154.  
  155. /**
  156.  * Similar to pipe_sampler_view_reference() but always set the pointer to
  157.  * NULL and pass in an explicit context.  Passing an explicit context is a
  158.  * work-around for fixing a dangling context pointer problem when textures
  159.  * are shared by multiple contexts.  XXX fix this someday.
  160.  */
  161. static INLINE void
  162. pipe_sampler_view_release(struct pipe_context *ctx,
  163.                           struct pipe_sampler_view **ptr)
  164. {
  165.    struct pipe_sampler_view *old_view = *ptr;
  166.    if (*ptr && (*ptr)->context != ctx) {
  167.       debug_printf_once(("context mis-match in pipe_sampler_view_release()\n"));
  168.    }
  169.    if (pipe_reference_described(&(*ptr)->reference, NULL,
  170.                     (debug_reference_descriptor)debug_describe_sampler_view)) {
  171.       ctx->sampler_view_destroy(ctx, old_view);
  172.    }
  173.    *ptr = NULL;
  174. }
  175.  
  176.  
  177. static INLINE void
  178. pipe_so_target_reference(struct pipe_stream_output_target **ptr,
  179.                          struct pipe_stream_output_target *target)
  180. {
  181.    struct pipe_stream_output_target *old = *ptr;
  182.  
  183.    if (pipe_reference_described(&(*ptr)->reference, &target->reference,
  184.                      (debug_reference_descriptor)debug_describe_so_target))
  185.       old->context->stream_output_target_destroy(old->context, old);
  186.    *ptr = target;
  187. }
  188.  
  189. static INLINE void
  190. pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps,
  191.                    struct pipe_resource *pt, unsigned level, unsigned layer)
  192. {
  193.    pipe_resource_reference(&ps->texture, pt);
  194.    ps->format = pt->format;
  195.    ps->width = u_minify(pt->width0, level);
  196.    ps->height = u_minify(pt->height0, level);
  197.    ps->u.tex.level = level;
  198.    ps->u.tex.first_layer = ps->u.tex.last_layer = layer;
  199.    ps->context = ctx;
  200. }
  201.  
  202. static INLINE void
  203. pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps,
  204.                   struct pipe_resource *pt, unsigned level, unsigned layer)
  205. {
  206.    ps->texture = 0;
  207.    pipe_reference_init(&ps->reference, 1);
  208.    pipe_surface_reset(ctx, ps, pt, level, layer);
  209. }
  210.  
  211. /* Return true if the surfaces are equal. */
  212. static INLINE boolean
  213. pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2)
  214. {
  215.    return s1->texture == s2->texture &&
  216.           s1->format == s2->format &&
  217.           (s1->texture->target != PIPE_BUFFER ||
  218.            (s1->u.buf.first_element == s2->u.buf.first_element &&
  219.             s1->u.buf.last_element == s2->u.buf.last_element)) &&
  220.           (s1->texture->target == PIPE_BUFFER ||
  221.            (s1->u.tex.level == s2->u.tex.level &&
  222.             s1->u.tex.first_layer == s2->u.tex.first_layer &&
  223.             s1->u.tex.last_layer == s2->u.tex.last_layer));
  224. }
  225.  
  226. /*
  227.  * Convenience wrappers for screen buffer functions.
  228.  */
  229.  
  230. static INLINE struct pipe_resource *
  231. pipe_buffer_create( struct pipe_screen *screen,
  232.                     unsigned bind,
  233.                     unsigned usage,
  234.                     unsigned size )
  235. {
  236.    struct pipe_resource buffer;
  237.    memset(&buffer, 0, sizeof buffer);
  238.    buffer.target = PIPE_BUFFER;
  239.    buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
  240.    buffer.bind = bind;
  241.    buffer.usage = usage;
  242.    buffer.flags = 0;
  243.    buffer.width0 = size;
  244.    buffer.height0 = 1;
  245.    buffer.depth0 = 1;
  246.    buffer.array_size = 1;
  247.    return screen->resource_create(screen, &buffer);
  248. }
  249.  
  250. static INLINE void *
  251. pipe_buffer_map_range(struct pipe_context *pipe,
  252.                       struct pipe_resource *buffer,
  253.                       unsigned offset,
  254.                       unsigned length,
  255.                       unsigned usage,
  256.                       struct pipe_transfer **transfer)
  257. {
  258.    struct pipe_box box;
  259.    void *map;
  260.  
  261.    assert(offset < buffer->width0);
  262.    assert(offset + length <= buffer->width0);
  263.    assert(length);
  264.  
  265.    u_box_1d(offset, length, &box);
  266.  
  267.    map = pipe->transfer_map(pipe, buffer, 0, usage, &box, transfer);
  268.    if (map == NULL) {
  269.       return NULL;
  270.    }
  271.  
  272.    return map;
  273. }
  274.  
  275.  
  276. static INLINE void *
  277. pipe_buffer_map(struct pipe_context *pipe,
  278.                 struct pipe_resource *buffer,
  279.                 unsigned usage,
  280.                 struct pipe_transfer **transfer)
  281. {
  282.    return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, usage, transfer);
  283. }
  284.  
  285.  
  286. static INLINE void
  287. pipe_buffer_unmap(struct pipe_context *pipe,
  288.                   struct pipe_transfer *transfer)
  289. {
  290.    pipe->transfer_unmap(pipe, transfer);
  291. }
  292.  
  293. static INLINE void
  294. pipe_buffer_flush_mapped_range(struct pipe_context *pipe,
  295.                                struct pipe_transfer *transfer,
  296.                                unsigned offset,
  297.                                unsigned length)
  298. {
  299.    struct pipe_box box;
  300.    int transfer_offset;
  301.  
  302.    assert(length);
  303.    assert(transfer->box.x <= (int) offset);
  304.    assert((int) (offset + length) <= transfer->box.x + transfer->box.width);
  305.  
  306.    /* Match old screen->buffer_flush_mapped_range() behaviour, where
  307.     * offset parameter is relative to the start of the buffer, not the
  308.     * mapped range.
  309.     */
  310.    transfer_offset = offset - transfer->box.x;
  311.  
  312.    u_box_1d(transfer_offset, length, &box);
  313.  
  314.    pipe->transfer_flush_region(pipe, transfer, &box);
  315. }
  316.  
  317. static INLINE void
  318. pipe_buffer_write(struct pipe_context *pipe,
  319.                   struct pipe_resource *buf,
  320.                   unsigned offset,
  321.                   unsigned size,
  322.                   const void *data)
  323. {
  324.    struct pipe_box box;
  325.    unsigned usage = PIPE_TRANSFER_WRITE;
  326.  
  327.    if (offset == 0 && size == buf->width0) {
  328.       usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
  329.    } else {
  330.       usage |= PIPE_TRANSFER_DISCARD_RANGE;
  331.    }
  332.  
  333.    u_box_1d(offset, size, &box);
  334.  
  335.    pipe->transfer_inline_write( pipe,
  336.                                 buf,
  337.                                 0,
  338.                                 usage,
  339.                                 &box,
  340.                                 data,
  341.                                 size,
  342.                                 0);
  343. }
  344.  
  345. /**
  346.  * Special case for writing non-overlapping ranges.
  347.  *
  348.  * We can avoid GPU/CPU synchronization when writing range that has never
  349.  * been written before.
  350.  */
  351. static INLINE void
  352. pipe_buffer_write_nooverlap(struct pipe_context *pipe,
  353.                             struct pipe_resource *buf,
  354.                             unsigned offset, unsigned size,
  355.                             const void *data)
  356. {
  357.    struct pipe_box box;
  358.  
  359.    u_box_1d(offset, size, &box);
  360.  
  361.    pipe->transfer_inline_write(pipe,
  362.                                buf,
  363.                                0,
  364.                                (PIPE_TRANSFER_WRITE |
  365.                                 PIPE_TRANSFER_UNSYNCHRONIZED),
  366.                                &box,
  367.                                data,
  368.                                0, 0);
  369. }
  370.  
  371. static INLINE struct pipe_resource *
  372. pipe_buffer_create_with_data(struct pipe_context *pipe,
  373.                              unsigned bind,
  374.                              unsigned usage,
  375.                              unsigned size,
  376.                              void *ptr)
  377. {
  378.    struct pipe_resource *res = pipe_buffer_create(pipe->screen,
  379.                                                   bind, usage, size);
  380.    pipe_buffer_write_nooverlap(pipe, res, 0, size, ptr);
  381.    return res;
  382. }
  383.  
  384. static INLINE void
  385. pipe_buffer_read(struct pipe_context *pipe,
  386.                  struct pipe_resource *buf,
  387.                  unsigned offset,
  388.                  unsigned size,
  389.                  void *data)
  390. {
  391.    struct pipe_transfer *src_transfer;
  392.    ubyte *map;
  393.  
  394.    map = (ubyte *) pipe_buffer_map_range(pipe,
  395.                                          buf,
  396.                                          offset, size,
  397.                                          PIPE_TRANSFER_READ,
  398.                                          &src_transfer);
  399.    if (!map)
  400.       return;
  401.  
  402.    memcpy(data, map, size);
  403.    pipe_buffer_unmap(pipe, src_transfer);
  404. }
  405.  
  406. static INLINE void *
  407. pipe_transfer_map(struct pipe_context *context,
  408.                   struct pipe_resource *resource,
  409.                   unsigned level, unsigned layer,
  410.                   enum pipe_transfer_usage usage,
  411.                   unsigned x, unsigned y,
  412.                   unsigned w, unsigned h,
  413.                   struct pipe_transfer **transfer)
  414. {
  415.    struct pipe_box box;
  416.    u_box_2d_zslice(x, y, layer, w, h, &box);
  417.    return context->transfer_map(context,
  418.                                 resource,
  419.                                 level,
  420.                                 usage,
  421.                                 &box, transfer);
  422. }
  423.  
  424. static INLINE void *
  425. pipe_transfer_map_3d(struct pipe_context *context,
  426.                      struct pipe_resource *resource,
  427.                      unsigned level,
  428.                      enum pipe_transfer_usage usage,
  429.                      unsigned x, unsigned y, unsigned z,
  430.                      unsigned w, unsigned h, unsigned d,
  431.                      struct pipe_transfer **transfer)
  432. {
  433.    struct pipe_box box;
  434.    u_box_3d(x, y, z, w, h, d, &box);
  435.    return context->transfer_map(context,
  436.                                 resource,
  437.                                 level,
  438.                                 usage,
  439.                                 &box, transfer);
  440. }
  441.  
  442. static INLINE void
  443. pipe_transfer_unmap( struct pipe_context *context,
  444.                      struct pipe_transfer *transfer )
  445. {
  446.    context->transfer_unmap( context, transfer );
  447. }
  448.  
  449. static INLINE void
  450. pipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
  451.                          struct pipe_resource *buf)
  452. {
  453.    if (buf) {
  454.       struct pipe_constant_buffer cb;
  455.       cb.buffer = buf;
  456.       cb.buffer_offset = 0;
  457.       cb.buffer_size = buf->width0;
  458.       cb.user_buffer = NULL;
  459.       pipe->set_constant_buffer(pipe, shader, index, &cb);
  460.    } else {
  461.       pipe->set_constant_buffer(pipe, shader, index, NULL);
  462.    }
  463. }
  464.  
  465.  
  466. static INLINE boolean util_get_offset(
  467.    const struct pipe_rasterizer_state *templ,
  468.    unsigned fill_mode)
  469. {
  470.    switch(fill_mode) {
  471.    case PIPE_POLYGON_MODE_POINT:
  472.       return templ->offset_point;
  473.    case PIPE_POLYGON_MODE_LINE:
  474.       return templ->offset_line;
  475.    case PIPE_POLYGON_MODE_FILL:
  476.       return templ->offset_tri;
  477.    default:
  478.       assert(0);
  479.       return FALSE;
  480.    }
  481. }
  482.  
  483. static INLINE float
  484. util_get_min_point_size(const struct pipe_rasterizer_state *state)
  485. {
  486.    /* The point size should be clamped to this value at the rasterizer stage.
  487.     */
  488.    return !state->point_quad_rasterization &&
  489.           !state->point_smooth &&
  490.           !state->multisample ? 1.0f : 0.0f;
  491. }
  492.  
  493. static INLINE void
  494. util_query_clear_result(union pipe_query_result *result, unsigned type)
  495. {
  496.    switch (type) {
  497.    case PIPE_QUERY_OCCLUSION_PREDICATE:
  498.    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
  499.    case PIPE_QUERY_GPU_FINISHED:
  500.       result->b = FALSE;
  501.       break;
  502.    case PIPE_QUERY_OCCLUSION_COUNTER:
  503.    case PIPE_QUERY_TIMESTAMP:
  504.    case PIPE_QUERY_TIME_ELAPSED:
  505.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  506.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  507.       result->u64 = 0;
  508.       break;
  509.    case PIPE_QUERY_SO_STATISTICS:
  510.       memset(&result->so_statistics, 0, sizeof(result->so_statistics));
  511.       break;
  512.    case PIPE_QUERY_TIMESTAMP_DISJOINT:
  513.       memset(&result->timestamp_disjoint, 0, sizeof(result->timestamp_disjoint));
  514.       break;
  515.    case PIPE_QUERY_PIPELINE_STATISTICS:
  516.       memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics));
  517.       break;
  518.    default:
  519.       memset(result, 0, sizeof(*result));
  520.    }
  521. }
  522.  
  523. /** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
  524. static INLINE unsigned
  525. util_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target,
  526.                           unsigned nr_samples)
  527. {
  528.    switch (pipe_tex_target) {
  529.    case PIPE_TEXTURE_1D:
  530.       assert(nr_samples <= 1);
  531.       return TGSI_TEXTURE_1D;
  532.  
  533.    case PIPE_TEXTURE_2D:
  534.       return nr_samples > 1 ? TGSI_TEXTURE_2D_MSAA : TGSI_TEXTURE_2D;
  535.  
  536.    case PIPE_TEXTURE_RECT:
  537.       assert(nr_samples <= 1);
  538.       return TGSI_TEXTURE_RECT;
  539.  
  540.    case PIPE_TEXTURE_3D:
  541.       assert(nr_samples <= 1);
  542.       return TGSI_TEXTURE_3D;
  543.  
  544.    case PIPE_TEXTURE_CUBE:
  545.       assert(nr_samples <= 1);
  546.       return TGSI_TEXTURE_CUBE;
  547.  
  548.    case PIPE_TEXTURE_1D_ARRAY:
  549.       assert(nr_samples <= 1);
  550.       return TGSI_TEXTURE_1D_ARRAY;
  551.  
  552.    case PIPE_TEXTURE_2D_ARRAY:
  553.       return nr_samples > 1 ? TGSI_TEXTURE_2D_ARRAY_MSAA :
  554.                               TGSI_TEXTURE_2D_ARRAY;
  555.  
  556.    case PIPE_TEXTURE_CUBE_ARRAY:
  557.       return TGSI_TEXTURE_CUBE_ARRAY;
  558.  
  559.    default:
  560.       assert(0 && "unexpected texture target");
  561.       return TGSI_TEXTURE_UNKNOWN;
  562.    }
  563. }
  564.  
  565.  
  566. static INLINE void
  567. util_copy_constant_buffer(struct pipe_constant_buffer *dst,
  568.                           const struct pipe_constant_buffer *src)
  569. {
  570.    if (src) {
  571.       pipe_resource_reference(&dst->buffer, src->buffer);
  572.       dst->buffer_offset = src->buffer_offset;
  573.       dst->buffer_size = src->buffer_size;
  574.       dst->user_buffer = src->user_buffer;
  575.    }
  576.    else {
  577.       pipe_resource_reference(&dst->buffer, NULL);
  578.       dst->buffer_offset = 0;
  579.       dst->buffer_size = 0;
  580.       dst->user_buffer = NULL;
  581.    }
  582. }
  583.  
  584. static INLINE unsigned
  585. util_max_layer(const struct pipe_resource *r, unsigned level)
  586. {
  587.    switch (r->target) {
  588.    case PIPE_TEXTURE_CUBE:
  589.       return 6 - 1;
  590.    case PIPE_TEXTURE_3D:
  591.       return u_minify(r->depth0, level) - 1;
  592.    case PIPE_TEXTURE_1D_ARRAY:
  593.    case PIPE_TEXTURE_2D_ARRAY:
  594.    case PIPE_TEXTURE_CUBE_ARRAY:
  595.       return r->array_size - 1;
  596.    default:
  597.       return 0;
  598.    }
  599. }
  600.  
  601. #ifdef __cplusplus
  602. }
  603. #endif
  604.  
  605. #endif /* U_INLINES_H */
  606.