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/compiler.h"
30 #include "util/u_inlines.h"
31 #include "util/u_memory.h"
32
33 #include "etnaviv_context.h"
34 #include "etnaviv_debug.h"
35 #include "etnaviv_emit.h"
36 #include "etnaviv_query_acc.h"
37 #include "etnaviv_screen.h"
38
39 /*
40 * Occlusion Query:
41 *
42 * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
43 * interpret results
44 */
45
46 static bool
occlusion_supports(unsigned query_type)47 occlusion_supports(unsigned query_type)
48 {
49 switch (query_type) {
50 case PIPE_QUERY_OCCLUSION_COUNTER:
51 FALLTHROUGH;
52 case PIPE_QUERY_OCCLUSION_PREDICATE:
53 FALLTHROUGH;
54 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
55 return true;
56 default:
57 return false;
58 }
59 }
60
61 static struct etna_acc_query *
occlusion_allocate(struct etna_context * ctx,ASSERTED unsigned query_type)62 occlusion_allocate(struct etna_context *ctx, ASSERTED unsigned query_type)
63 {
64 return CALLOC_STRUCT(etna_acc_query);
65 }
66
67 static void
occlusion_resume(struct etna_acc_query * aq,struct etna_context * ctx)68 occlusion_resume(struct etna_acc_query *aq, struct etna_context *ctx)
69 {
70 struct etna_resource *rsc = etna_resource(aq->prsc);
71 struct etna_reloc r = {
72 .bo = rsc->bo,
73 .flags = ETNA_RELOC_WRITE
74 };
75
76 if (aq->samples > 63) {
77 aq->samples = 63;
78 BUG("samples overflow");
79 }
80
81 r.offset = aq->samples * 8; /* 64bit value */
82
83 etna_set_state_reloc(ctx->stream, VIVS_GL_OCCLUSION_QUERY_ADDR, &r);
84 resource_written(ctx, aq->prsc);
85 }
86
87 static void
occlusion_suspend(struct etna_acc_query * aq,struct etna_context * ctx)88 occlusion_suspend(struct etna_acc_query *aq, struct etna_context *ctx)
89 {
90 /* 0x1DF5E76 is the value used by blob - but any random value will work */
91 etna_set_state(ctx->stream, VIVS_GL_OCCLUSION_QUERY_CONTROL, 0x1DF5E76);
92 resource_written(ctx, aq->prsc);
93 }
94
95 static bool
occlusion_result(struct etna_acc_query * aq,void * buf,union pipe_query_result * result)96 occlusion_result(struct etna_acc_query *aq, void *buf,
97 union pipe_query_result *result)
98 {
99 uint64_t sum = 0;
100 uint64_t *ptr = (uint64_t *)buf;
101
102 for (unsigned i = 0; i < aq->samples; i++)
103 sum += *(ptr + i);
104
105 if (aq->base.type == PIPE_QUERY_OCCLUSION_COUNTER)
106 result->u64 = sum;
107 else
108 result->b = !!sum;
109
110 return true;
111 }
112
113 const struct etna_acc_sample_provider occlusion_provider = {
114 .supports = occlusion_supports,
115 .allocate = occlusion_allocate,
116 .suspend = occlusion_suspend,
117 .resume = occlusion_resume,
118 .result = occlusion_result,
119 };
120