"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/nouveau/nv30/nv30_query.c" (16 Sep 2020, 7943 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "nv30_query.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright 2012 Red Hat Inc.
    3  *
    4  * Permission is hereby granted, free of charge, to any person obtaining a
    5  * copy of this software and associated documentation files (the "Software"),
    6  * to deal in the Software without restriction, including without limitation
    7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    8  * and/or sell copies of the Software, and to permit persons to whom the
    9  * Software is furnished to do so, subject to the following conditions:
   10  *
   11  * The above copyright notice and this permission notice shall be included in
   12  * all copies or substantial portions of the Software.
   13  *
   14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   20  * OTHER DEALINGS IN THE SOFTWARE.
   21  *
   22  * Authors: Ben Skeggs
   23  *
   24  */
   25 
   26 #include "nv_object.xml.h"
   27 #include "nv30/nv30-40_3d.xml.h"
   28 #include "nv30/nv30_screen.h"
   29 #include "nv30/nv30_context.h"
   30 
   31 #define LIST_FIRST_ENTRY(__type, __item, __field) \
   32    LIST_ENTRY(__type, (__item)->next, __field)
   33 
   34 struct nv30_query_object {
   35    struct list_head list;
   36    struct nouveau_heap *hw;
   37 };
   38 
   39 static volatile void *
   40 nv30_ntfy(struct nv30_screen *screen, struct nv30_query_object *qo)
   41 {
   42    struct nv04_notify *query = screen->query->data;
   43    struct nouveau_bo *notify = screen->notify;
   44    volatile void *ntfy = NULL;
   45 
   46    if (qo && qo->hw)
   47       ntfy = (char *)notify->map + query->offset + qo->hw->start;
   48 
   49    return ntfy;
   50 }
   51 
   52 static void
   53 nv30_query_object_del(struct nv30_screen *screen, struct nv30_query_object **po)
   54 {
   55    struct nv30_query_object *qo = *po; *po = NULL;
   56    if (qo) {
   57       volatile uint32_t *ntfy = nv30_ntfy(screen, qo);
   58       while (ntfy[3] & 0xff000000) {
   59       }
   60       nouveau_heap_free(&qo->hw);
   61       list_del(&qo->list);
   62       FREE(qo);
   63    }
   64 }
   65 
   66 static struct nv30_query_object *
   67 nv30_query_object_new(struct nv30_screen *screen)
   68 {
   69    struct nv30_query_object *oq, *qo = CALLOC_STRUCT(nv30_query_object);
   70    volatile uint32_t *ntfy;
   71 
   72    if (!qo)
   73       return NULL;
   74 
   75    /* allocate a new hw query object, if no hw objects left we need to
   76     * spin waiting for one to become free
   77     */
   78    while (nouveau_heap_alloc(screen->query_heap, 32, NULL, &qo->hw)) {
   79       oq = LIST_FIRST_ENTRY(struct nv30_query_object, &screen->queries, list);
   80       nv30_query_object_del(screen, &oq);
   81    }
   82 
   83    list_addtail(&qo->list, &screen->queries);
   84 
   85    ntfy = nv30_ntfy(screen, qo);
   86    ntfy[0] = 0x00000000;
   87    ntfy[1] = 0x00000000;
   88    ntfy[2] = 0x00000000;
   89    ntfy[3] = 0x01000000;
   90    return qo;
   91 }
   92 
   93 struct nv30_query {
   94    struct nv30_query_object *qo[2];
   95    unsigned type;
   96    uint32_t report;
   97    uint32_t enable;
   98    uint64_t result;
   99 };
  100 
  101 static inline struct nv30_query *
  102 nv30_query(struct pipe_query *pipe)
  103 {
  104    return (struct nv30_query *)pipe;
  105 }
  106 
  107 static struct pipe_query *
  108 nv30_query_create(struct pipe_context *pipe, unsigned type, unsigned index)
  109 {
  110    struct nv30_query *q = CALLOC_STRUCT(nv30_query);
  111    if (!q)
  112       return NULL;
  113 
  114    q->type = type;
  115 
  116    switch (q->type) {
  117    case PIPE_QUERY_TIMESTAMP:
  118    case PIPE_QUERY_TIME_ELAPSED:
  119       q->enable = 0x0000;
  120       q->report = 1;
  121       break;
  122    case PIPE_QUERY_OCCLUSION_COUNTER:
  123    case PIPE_QUERY_OCCLUSION_PREDICATE:
  124    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
  125       q->enable = NV30_3D_QUERY_ENABLE;
  126       q->report = 1;
  127       break;
  128    case NV30_QUERY_ZCULL_0:
  129    case NV30_QUERY_ZCULL_1:
  130    case NV30_QUERY_ZCULL_2:
  131    case NV30_QUERY_ZCULL_3:
  132       q->enable = 0x1804;
  133       q->report = 2 + (q->type - NV30_QUERY_ZCULL_0);
  134       break;
  135    default:
  136       FREE(q);
  137       return NULL;
  138    }
  139 
  140    return (struct pipe_query *)q;
  141 }
  142 
  143 static void
  144 nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
  145 {
  146    FREE(pq);
  147 }
  148 
  149 static bool
  150 nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
  151 {
  152    struct nv30_context *nv30 = nv30_context(pipe);
  153    struct nv30_query *q = nv30_query(pq);
  154    struct nouveau_pushbuf *push = nv30->base.pushbuf;
  155 
  156    switch (q->type) {
  157    case PIPE_QUERY_TIME_ELAPSED:
  158       q->qo[0] = nv30_query_object_new(nv30->screen);
  159       if (q->qo[0]) {
  160          BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
  161          PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start);
  162       }
  163       break;
  164    case PIPE_QUERY_TIMESTAMP:
  165       return true;
  166    default:
  167       BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1);
  168       PUSH_DATA (push, q->report);
  169       break;
  170    }
  171 
  172    if (q->enable) {
  173       BEGIN_NV04(push, SUBC_3D(q->enable), 1);
  174       PUSH_DATA (push, 1);
  175    }
  176    return true;
  177 }
  178 
  179 static bool
  180 nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
  181 {
  182    struct nv30_context *nv30 = nv30_context(pipe);
  183    struct nv30_screen *screen = nv30->screen;
  184    struct nv30_query *q = nv30_query(pq);
  185    struct nouveau_pushbuf *push = nv30->base.pushbuf;
  186 
  187    q->qo[1] = nv30_query_object_new(screen);
  188    if (q->qo[1]) {
  189       BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
  190       PUSH_DATA (push, (q->report << 24) | q->qo[1]->hw->start);
  191    }
  192 
  193    if (q->enable) {
  194       BEGIN_NV04(push, SUBC_3D(q->enable), 1);
  195       PUSH_DATA (push, 0);
  196    }
  197    PUSH_KICK (push);
  198    return true;
  199 }
  200 
  201 static bool
  202 nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
  203                   bool wait, union pipe_query_result *result)
  204 {
  205    struct nv30_screen *screen = nv30_screen(pipe->screen);
  206    struct nv30_query *q = nv30_query(pq);
  207    volatile uint32_t *ntfy0 = nv30_ntfy(screen, q->qo[0]);
  208    volatile uint32_t *ntfy1 = nv30_ntfy(screen, q->qo[1]);
  209 
  210    if (ntfy1) {
  211       while (ntfy1[3] & 0xff000000) {
  212          if (!wait)
  213             return false;
  214       }
  215 
  216       switch (q->type) {
  217       case PIPE_QUERY_TIMESTAMP:
  218          q->result = *(uint64_t *)&ntfy1[0];
  219          break;
  220       case PIPE_QUERY_TIME_ELAPSED:
  221          q->result = *(uint64_t *)&ntfy1[0] - *(uint64_t *)&ntfy0[0];
  222          break;
  223       default:
  224          q->result = ntfy1[2];
  225          break;
  226       }
  227 
  228       nv30_query_object_del(screen, &q->qo[0]);
  229       nv30_query_object_del(screen, &q->qo[1]);
  230    }
  231 
  232    if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
  233        q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE)
  234       result->b = !!q->result;
  235    else
  236       result->u64 = q->result;
  237    return true;
  238 }
  239 
  240 static void
  241 nv40_query_render_condition(struct pipe_context *pipe,
  242                             struct pipe_query *pq,
  243                             bool condition, enum pipe_render_cond_flag mode)
  244 {
  245    struct nv30_context *nv30 = nv30_context(pipe);
  246    struct nv30_query *q = nv30_query(pq);
  247    struct nouveau_pushbuf *push = nv30->base.pushbuf;
  248 
  249    nv30->render_cond_query = pq;
  250    nv30->render_cond_mode = mode;
  251    nv30->render_cond_cond = condition;
  252 
  253    if (!pq) {
  254       BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
  255       PUSH_DATA (push, 0x01000000);
  256       return;
  257    }
  258 
  259    if (mode == PIPE_RENDER_COND_WAIT ||
  260        mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
  261       BEGIN_NV04(push, SUBC_3D(0x0110), 1);
  262       PUSH_DATA (push, 0);
  263    }
  264 
  265    BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
  266    PUSH_DATA (push, 0x02000000 | q->qo[1]->hw->start);
  267 }
  268 
  269 static void
  270 nv30_set_active_query_state(struct pipe_context *pipe, bool enable)
  271 {
  272 }
  273 
  274 void
  275 nv30_query_init(struct pipe_context *pipe)
  276 {
  277    struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
  278 
  279    pipe->create_query = nv30_query_create;
  280    pipe->destroy_query = nv30_query_destroy;
  281    pipe->begin_query = nv30_query_begin;
  282    pipe->end_query = nv30_query_end;
  283    pipe->get_query_result = nv30_query_result;
  284    pipe->set_active_query_state = nv30_set_active_query_state;
  285    if (eng3d->oclass >= NV40_3D_CLASS)
  286       pipe->render_condition = nv40_query_render_condition;
  287 }