1 /*
2  * Copyright (c) 2017 Etnaviv Project
3  * Copyright (C) 2017 Zodiac Inflight Innovations
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * 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 NON-INFRINGEMENT. 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  *    Rob Clark <robclark@freedesktop.org>
26  *    Christian Gmeiner <christian.gmeiner@gmail.com>
27  */
28 
29 #include "util/u_inlines.h"
30 #include "util/u_memory.h"
31 
32 #include "etnaviv_context.h"
33 #include "etnaviv_debug.h"
34 #include "etnaviv_emit.h"
35 #include "etnaviv_query_acc.h"
36 #include "etnaviv_screen.h"
37 
38 /*
39  * Occlusion Query:
40  *
41  * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
42  * interpret results
43  */
44 
45 static bool
occlusion_supports(unsigned query_type)46 occlusion_supports(unsigned query_type)
47 {
48    switch (query_type) {
49    case PIPE_QUERY_OCCLUSION_COUNTER:
50       /* fallthrough */
51    case PIPE_QUERY_OCCLUSION_PREDICATE:
52       /* fallthrough */
53    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
54       return true;
55    default:
56       return false;
57    }
58 }
59 
60 static struct etna_acc_query *
occlusion_allocate(struct etna_context * ctx,ASSERTED unsigned query_type)61 occlusion_allocate(struct etna_context *ctx, ASSERTED unsigned query_type)
62 {
63    return CALLOC_STRUCT(etna_acc_query);
64 }
65 
66 static void
occlusion_resume(struct etna_acc_query * aq,struct etna_context * ctx)67 occlusion_resume(struct etna_acc_query *aq, struct etna_context *ctx)
68 {
69    struct etna_resource *rsc = etna_resource(aq->prsc);
70    struct etna_reloc r = {
71       .bo = rsc->bo,
72       .flags = ETNA_RELOC_WRITE
73    };
74 
75    if (aq->samples > 63) {
76       aq->samples = 63;
77       BUG("samples overflow");
78    }
79 
80    r.offset = aq->samples * 8; /* 64bit value */
81 
82    etna_set_state_reloc(ctx->stream, VIVS_GL_OCCLUSION_QUERY_ADDR, &r);
83    resource_written(ctx, aq->prsc);
84 }
85 
86 static void
occlusion_suspend(struct etna_acc_query * aq,struct etna_context * ctx)87 occlusion_suspend(struct etna_acc_query *aq, struct etna_context *ctx)
88 {
89    /* 0x1DF5E76 is the value used by blob - but any random value will work */
90    etna_set_state(ctx->stream, VIVS_GL_OCCLUSION_QUERY_CONTROL, 0x1DF5E76);
91    resource_written(ctx, aq->prsc);
92 }
93 
94 static bool
occlusion_result(struct etna_acc_query * aq,void * buf,union pipe_query_result * result)95 occlusion_result(struct etna_acc_query *aq, void *buf,
96                  union pipe_query_result *result)
97 {
98    uint64_t sum = 0;
99    uint64_t *ptr = (uint64_t *)buf;
100 
101    for (unsigned i = 0; i < aq->samples; i++)
102       sum += *(ptr + i);
103 
104    if (aq->base.type == PIPE_QUERY_OCCLUSION_COUNTER)
105       result->u64 = sum;
106    else
107       result->b = !!sum;
108 
109    return true;
110 }
111 
112 const struct etna_acc_sample_provider occlusion_provider = {
113    .supports = occlusion_supports,
114    .allocate = occlusion_allocate,
115    .suspend = occlusion_suspend,
116    .resume = occlusion_resume,
117    .result = occlusion_result,
118 };
119