1d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson/*
2d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
3d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson *
4d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * Permission is hereby granted, free of charge, to any person obtaining a
5d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * copy of this software and associated documentation files (the "Software"),
6d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * to deal in the Software without restriction, including without limitation
7d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * on the rights to use, copy, modify, merge, publish, distribute, sub
8d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * license, and/or sell copies of the Software, and to permit persons to whom
9d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * the Software is furnished to do so, subject to the following conditions:
10d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson *
11d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * The above copyright notice and this permission notice (including the next
12d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * paragraph) shall be included in all copies or substantial portions of the
13d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * Software.
14d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson *
15d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
236a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "util/u_memory.h"
246a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "util/u_simple_list.h"
25d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
266a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "r300_context.h"
276a448a525baf81173f92ee8c3074b98baa54397bCorbin Simpson#include "r300_screen.h"
281ddb22675c123fc955ad3ab46bba45d3330d2ec4Nicolai Hähnle#include "r300_emit.h"
291ddb22675c123fc955ad3ab46bba45d3330d2ec4Nicolai Hähnle
304b8d3480764daf45cbbc03d76cd8b7c81937f532Marek Olšák#include <stdio.h>
314b8d3480764daf45cbbc03d76cd8b7c81937f532Marek Olšák
32c1bee7bdea470b6b5dcebef9aacc8fe4feca687cDave Airliestatic struct pipe_query *r300_create_query(struct pipe_context *pipe,
33d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson                                            unsigned query_type)
34d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson{
35c1bee7bdea470b6b5dcebef9aacc8fe4feca687cDave Airlie    struct r300_context *r300 = r300_context(pipe);
36b71bfc4400e1d7c15a2bebbbd3b26a8770fbf546Marek Olšák    struct r300_screen *r300screen = r300->screen;
37cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    struct r300_query *q;
38cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák
39014b3aa07d252d71a85234cfd2255b3b561b5c16Marek Olšák    if (query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
40c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
41c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        query_type != PIPE_QUERY_GPU_FINISHED) {
42a6cc91487446f8e1e72e4f67823a359c0b3a41d6Corbin Simpson        return NULL;
43a6cc91487446f8e1e72e4f67823a359c0b3a41d6Corbin Simpson    }
44a381ee82663f10ff3cdcfad331258d03d4188894Corbin Simpson
45a381ee82663f10ff3cdcfad331258d03d4188894Corbin Simpson    q = CALLOC_STRUCT(r300_query);
46cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    if (!q)
47cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák        return NULL;
48d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
49d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson    q->type = query_type;
50d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
51c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    if (query_type == PIPE_QUERY_GPU_FINISHED) {
52c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        return (struct pipe_query*)q;
53c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    }
54c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák
55b71bfc4400e1d7c15a2bebbbd3b26a8770fbf546Marek Olšák    if (r300screen->caps.family == CHIP_FAMILY_RV530)
5628a336dc38c478b809544e7404c4d1fddd873333Marek Olšák        q->num_pipes = r300screen->info.r300_num_z_pipes;
57c1bee7bdea470b6b5dcebef9aacc8fe4feca687cDave Airlie    else
5828a336dc38c478b809544e7404c4d1fddd873333Marek Olšák        q->num_pipes = r300screen->info.r300_num_gb_pipes;
59c1bee7bdea470b6b5dcebef9aacc8fe4feca687cDave Airlie
60671af44b1962a7a138185a4cfb992f6b349de10aMarek Olšák    q->buf = r300->rws->buffer_create(r300->rws, 4096, 4096,
6193f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                      PIPE_BIND_CUSTOM, RADEON_DOMAIN_GTT);
62c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    if (!q->buf) {
63c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        FREE(q);
64c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        return NULL;
65c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    }
666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf);
67fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson
68d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson    return (struct pipe_query*)q;
69d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson}
70d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
71d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpsonstatic void r300_destroy_query(struct pipe_context* pipe,
72fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson                               struct pipe_query* query)
73d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson{
74cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    struct r300_query* q = r300_query(query);
75a381ee82663f10ff3cdcfad331258d03d4188894Corbin Simpson
76d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    pb_reference(&q->buf, NULL);
77fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson    FREE(query);
78d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson}
79d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
80cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšákvoid r300_resume_query(struct r300_context *r300,
81cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák                       struct r300_query *query)
82cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák{
83cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    r300->query_current = query;
8466d45567b4e2c6f2585789b68667e6c00b7567e1Marek Olšák    r300_mark_atom_dirty(r300, &r300->query_start);
85cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák}
86cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák
87d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpsonstatic void r300_begin_query(struct pipe_context* pipe,
88fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson                             struct pipe_query* query)
89d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson{
90d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson    struct r300_context* r300 = r300_context(pipe);
91cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    struct r300_query* q = r300_query(query);
92d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
93c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    if (q->type == PIPE_QUERY_GPU_FINISHED)
94c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        return;
95c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák
9600704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák    if (r300->query_current != NULL) {
9700704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák        fprintf(stderr, "r300: begin_query: "
9800704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák                "Some other query has already been started.\n");
9900704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák        assert(0);
10000704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák        return;
10100704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák    }
10247791697ab6eb6965f0ba8ba3f20373b3753ca2aDave Airlie
103cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    q->num_results = 0;
104cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    r300_resume_query(r300, q);
105cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák}
106fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson
107cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšákvoid r300_stop_query(struct r300_context *r300)
108cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák{
109cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    r300_emit_query_end(r300);
110cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    r300->query_current = NULL;
111d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson}
112d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
113d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpsonstatic void r300_end_query(struct pipe_context* pipe,
11451d1cf55da6f8b8a215814589a189b6e5e537fe5Dave Airlie	                   struct pipe_query* query)
115d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson{
116d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson    struct r300_context* r300 = r300_context(pipe);
117cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    struct r300_query *q = r300_query(query);
11847791697ab6eb6965f0ba8ba3f20373b3753ca2aDave Airlie
119c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    if (q->type == PIPE_QUERY_GPU_FINISHED) {
120c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        pb_reference(&q->buf, NULL);
121c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        r300_flush(pipe, RADEON_FLUSH_ASYNC,
122c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák                   (struct pipe_fence_handle**)&q->buf);
123c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        return;
124c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    }
125c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák
126cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    if (q != r300->query_current) {
12700704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák        fprintf(stderr, "r300: end_query: Got invalid query.\n");
12800704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák        assert(0);
12900704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák        return;
13000704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák    }
13100704370e42eb9c828dc1699a033b8da9a2521b0Marek Olšák
132cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    r300_stop_query(r300);
133d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson}
134d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
135d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpsonstatic boolean r300_get_query_result(struct pipe_context* pipe,
136fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson                                     struct pipe_query* query,
137d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson                                     boolean wait,
1384445e170bee23a3607ece0e010adef7058ac6a11Marek Olšák                                     union pipe_query_result *vresult)
139d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson{
140a381ee82663f10ff3cdcfad331258d03d4188894Corbin Simpson    struct r300_context* r300 = r300_context(pipe);
141cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    struct r300_query *q = r300_query(query);
14220112cca262c926de887dff7d7f108b046ea781aMarek Olšák    unsigned i;
143cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    uint32_t temp, *map;
144fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson
145c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    if (q->type == PIPE_QUERY_GPU_FINISHED) {
146c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        if (wait) {
147c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák            r300->rws->buffer_wait(q->buf, RADEON_USAGE_READWRITE);
1486d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák            vresult->b = TRUE;
149c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        } else {
1506d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák            vresult->b = !r300->rws->buffer_is_busy(q->buf, RADEON_USAGE_READWRITE);
151c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák        }
1526d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák        return vresult->b;
153c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák    }
154c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák
1550a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    map = r300->rws->buffer_map(q->cs_buf, r300->cs,
15620112cca262c926de887dff7d7f108b046ea781aMarek Olšák                                PIPE_TRANSFER_READ |
15720112cca262c926de887dff7d7f108b046ea781aMarek Olšák                                (!wait ? PIPE_TRANSFER_DONTBLOCK : 0));
158c1bee7bdea470b6b5dcebef9aacc8fe4feca687cDave Airlie    if (!map)
159c1bee7bdea470b6b5dcebef9aacc8fe4feca687cDave Airlie        return FALSE;
1605241b9568c1f97eb9aca8be5eb7a3ef659d9917fMarek Olšák
161cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    /* Sum up the results. */
162cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    temp = 0;
163cf3778bae03460325960d2aec0cd4cdf325299ebMarek Olšák    for (i = 0; i < q->num_results; i++) {
1640be1f797709528546f17f82e67b86181fa0c61e1Michel Dänzer        /* Convert little endian values written by GPU to CPU byte order */
1650be1f797709528546f17f82e67b86181fa0c61e1Michel Dänzer        temp += util_le32_to_cpu(*map);
1660086a84e2df92d48d3fb3361daaa1359d920fb31Corbin Simpson        map++;
1670086a84e2df92d48d3fb3361daaa1359d920fb31Corbin Simpson    }
168fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson
1690a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    r300->rws->buffer_unmap(q->cs_buf);
170fbd758c55e6dc443f877bd87d5e6c54c86f61a33Corbin Simpson
171014b3aa07d252d71a85234cfd2255b3b561b5c16Marek Olšák    if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
1726d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák        vresult->b = temp != 0;
1736d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák    } else {
1746d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák        vresult->u64 = temp;
175014b3aa07d252d71a85234cfd2255b3b561b5c16Marek Olšák    }
176d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson    return TRUE;
177d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson}
178d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson
179655fe281556679669699052f37412a6243771619Marek Olšákstatic void r300_render_condition(struct pipe_context *pipe,
180655fe281556679669699052f37412a6243771619Marek Olšák                                  struct pipe_query *query,
181655fe281556679669699052f37412a6243771619Marek Olšák                                  uint mode)
182655fe281556679669699052f37412a6243771619Marek Olšák{
183655fe281556679669699052f37412a6243771619Marek Olšák    struct r300_context *r300 = r300_context(pipe);
1846d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák    union pipe_query_result result;
185655fe281556679669699052f37412a6243771619Marek Olšák    boolean wait;
186655fe281556679669699052f37412a6243771619Marek Olšák
187d18792f93d6dcdf7ef971522bdfba1ceeb0c6668Marek Olšák    r300->skip_rendering = FALSE;
188d18792f93d6dcdf7ef971522bdfba1ceeb0c6668Marek Olšák
189655fe281556679669699052f37412a6243771619Marek Olšák    if (query) {
190655fe281556679669699052f37412a6243771619Marek Olšák        wait = mode == PIPE_RENDER_COND_WAIT ||
191655fe281556679669699052f37412a6243771619Marek Olšák               mode == PIPE_RENDER_COND_BY_REGION_WAIT;
192655fe281556679669699052f37412a6243771619Marek Olšák
1936d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák        if (r300_get_query_result(pipe, query, wait, &result)) {
1946d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák            if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
1956d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák                r300->skip_rendering = !result.b;
1966d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák            } else {
1976d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák                r300->skip_rendering = !result.u64;
1986d73382afc1d2a5e5815d0e6e7f39e0bf8138002Marek Olšák	    }
199655fe281556679669699052f37412a6243771619Marek Olšák        }
200655fe281556679669699052f37412a6243771619Marek Olšák    }
201655fe281556679669699052f37412a6243771619Marek Olšák}
202655fe281556679669699052f37412a6243771619Marek Olšák
203c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšákvoid r300_init_query_functions(struct r300_context* r300)
204c5ae81652d7d153accc42002fc80f95e399410f7Marek Olšák{
20570b86fb273ee9c3b6fea750bc14eae43328ba677Marek Olšák    r300->context.create_query = r300_create_query;
20670b86fb273ee9c3b6fea750bc14eae43328ba677Marek Olšák    r300->context.destroy_query = r300_destroy_query;
20770b86fb273ee9c3b6fea750bc14eae43328ba677Marek Olšák    r300->context.begin_query = r300_begin_query;
20870b86fb273ee9c3b6fea750bc14eae43328ba677Marek Olšák    r300->context.end_query = r300_end_query;
20970b86fb273ee9c3b6fea750bc14eae43328ba677Marek Olšák    r300->context.get_query_result = r300_get_query_result;
21070b86fb273ee9c3b6fea750bc14eae43328ba677Marek Olšák    r300->context.render_condition = r300_render_condition;
211d559796d6f13579ecf921a63d9f0c6c6342dc230Corbin Simpson}
212