Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright 2009 Corbin Simpson |
||
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 | * on the rights to use, copy, modify, merge, publish, distribute, sub |
||
8 | * license, and/or sell copies of the Software, and to permit persons to whom |
||
9 | * the Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
18 | * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||
19 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
20 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
21 | * USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
||
22 | |||
23 | #include "util/u_memory.h" |
||
24 | #include "util/simple_list.h" |
||
25 | |||
26 | #include "r300_context.h" |
||
27 | #include "r300_screen.h" |
||
28 | #include "r300_emit.h" |
||
29 | |||
30 | #include |
||
31 | |||
32 | static struct pipe_query *r300_create_query(struct pipe_context *pipe, |
||
33 | unsigned query_type, |
||
34 | unsigned index) |
||
35 | { |
||
36 | struct r300_context *r300 = r300_context(pipe); |
||
37 | struct r300_screen *r300screen = r300->screen; |
||
38 | struct r300_query *q; |
||
39 | |||
40 | if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && |
||
41 | query_type != PIPE_QUERY_OCCLUSION_PREDICATE && |
||
42 | query_type != PIPE_QUERY_GPU_FINISHED) { |
||
43 | return NULL; |
||
44 | } |
||
45 | |||
46 | q = CALLOC_STRUCT(r300_query); |
||
47 | if (!q) |
||
48 | return NULL; |
||
49 | |||
50 | q->type = query_type; |
||
51 | |||
52 | if (query_type == PIPE_QUERY_GPU_FINISHED) { |
||
53 | return (struct pipe_query*)q; |
||
54 | } |
||
55 | |||
56 | if (r300screen->caps.family == CHIP_RV530) |
||
57 | q->num_pipes = r300screen->info.r300_num_z_pipes; |
||
58 | else |
||
59 | q->num_pipes = r300screen->info.r300_num_gb_pipes; |
||
60 | |||
61 | q->buf = r300->rws->buffer_create(r300->rws, 4096, 4096, TRUE, |
||
62 | RADEON_DOMAIN_GTT, 0); |
||
63 | if (!q->buf) { |
||
64 | FREE(q); |
||
65 | return NULL; |
||
66 | } |
||
67 | q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf); |
||
68 | |||
69 | return (struct pipe_query*)q; |
||
70 | } |
||
71 | |||
72 | static void r300_destroy_query(struct pipe_context* pipe, |
||
73 | struct pipe_query* query) |
||
74 | { |
||
75 | struct r300_query* q = r300_query(query); |
||
76 | |||
77 | pb_reference(&q->buf, NULL); |
||
78 | FREE(query); |
||
79 | } |
||
80 | |||
81 | void r300_resume_query(struct r300_context *r300, |
||
82 | struct r300_query *query) |
||
83 | { |
||
84 | r300->query_current = query; |
||
85 | r300_mark_atom_dirty(r300, &r300->query_start); |
||
86 | } |
||
87 | |||
88 | static boolean r300_begin_query(struct pipe_context* pipe, |
||
89 | struct pipe_query* query) |
||
90 | { |
||
91 | struct r300_context* r300 = r300_context(pipe); |
||
92 | struct r300_query* q = r300_query(query); |
||
93 | |||
94 | if (q->type == PIPE_QUERY_GPU_FINISHED) |
||
95 | return true; |
||
96 | |||
97 | if (r300->query_current != NULL) { |
||
98 | fprintf(stderr, "r300: begin_query: " |
||
99 | "Some other query has already been started.\n"); |
||
100 | assert(0); |
||
101 | return false; |
||
102 | } |
||
103 | |||
104 | q->num_results = 0; |
||
105 | r300_resume_query(r300, q); |
||
106 | return true; |
||
107 | } |
||
108 | |||
109 | void r300_stop_query(struct r300_context *r300) |
||
110 | { |
||
111 | r300_emit_query_end(r300); |
||
112 | r300->query_current = NULL; |
||
113 | } |
||
114 | |||
115 | static void r300_end_query(struct pipe_context* pipe, |
||
116 | struct pipe_query* query) |
||
117 | { |
||
118 | struct r300_context* r300 = r300_context(pipe); |
||
119 | struct r300_query *q = r300_query(query); |
||
120 | |||
121 | if (q->type == PIPE_QUERY_GPU_FINISHED) { |
||
122 | pb_reference(&q->buf, NULL); |
||
123 | r300_flush(pipe, RADEON_FLUSH_ASYNC, |
||
124 | (struct pipe_fence_handle**)&q->buf); |
||
125 | return; |
||
126 | } |
||
127 | |||
128 | if (q != r300->query_current) { |
||
129 | fprintf(stderr, "r300: end_query: Got invalid query.\n"); |
||
130 | assert(0); |
||
131 | return; |
||
132 | } |
||
133 | |||
134 | r300_stop_query(r300); |
||
135 | } |
||
136 | |||
137 | static boolean r300_get_query_result(struct pipe_context* pipe, |
||
138 | struct pipe_query* query, |
||
139 | boolean wait, |
||
140 | union pipe_query_result *vresult) |
||
141 | { |
||
142 | struct r300_context* r300 = r300_context(pipe); |
||
143 | struct r300_query *q = r300_query(query); |
||
144 | unsigned i; |
||
145 | uint32_t temp, *map; |
||
146 | |||
147 | if (q->type == PIPE_QUERY_GPU_FINISHED) { |
||
148 | if (wait) { |
||
149 | r300->rws->buffer_wait(q->buf, RADEON_USAGE_READWRITE); |
||
150 | vresult->b = TRUE; |
||
151 | } else { |
||
152 | vresult->b = !r300->rws->buffer_is_busy(q->buf, RADEON_USAGE_READWRITE); |
||
153 | } |
||
154 | return vresult->b; |
||
155 | } |
||
156 | |||
157 | map = r300->rws->buffer_map(q->cs_buf, r300->cs, |
||
158 | PIPE_TRANSFER_READ | |
||
159 | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0)); |
||
160 | if (!map) |
||
161 | return FALSE; |
||
162 | |||
163 | /* Sum up the results. */ |
||
164 | temp = 0; |
||
165 | for (i = 0; i < q->num_results; i++) { |
||
166 | /* Convert little endian values written by GPU to CPU byte order */ |
||
167 | temp += util_le32_to_cpu(*map); |
||
168 | map++; |
||
169 | } |
||
170 | |||
171 | r300->rws->buffer_unmap(q->cs_buf); |
||
172 | |||
173 | if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) { |
||
174 | vresult->b = temp != 0; |
||
175 | } else { |
||
176 | vresult->u64 = temp; |
||
177 | } |
||
178 | return TRUE; |
||
179 | } |
||
180 | |||
181 | static void r300_render_condition(struct pipe_context *pipe, |
||
182 | struct pipe_query *query, |
||
183 | boolean condition, |
||
184 | uint mode) |
||
185 | { |
||
186 | struct r300_context *r300 = r300_context(pipe); |
||
187 | union pipe_query_result result; |
||
188 | boolean wait; |
||
189 | |||
190 | r300->skip_rendering = FALSE; |
||
191 | |||
192 | if (query) { |
||
193 | wait = mode == PIPE_RENDER_COND_WAIT || |
||
194 | mode == PIPE_RENDER_COND_BY_REGION_WAIT; |
||
195 | |||
196 | if (r300_get_query_result(pipe, query, wait, &result)) { |
||
197 | if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE) { |
||
198 | r300->skip_rendering = condition == result.b; |
||
199 | } else { |
||
200 | r300->skip_rendering = condition == !!result.u64; |
||
201 | } |
||
202 | } |
||
203 | } |
||
204 | } |
||
205 | |||
206 | void r300_init_query_functions(struct r300_context* r300) |
||
207 | { |
||
208 | r300->context.create_query = r300_create_query; |
||
209 | r300->context.destroy_query = r300_destroy_query; |
||
210 | r300->context.begin_query = r300_begin_query; |
||
211 | r300->context.end_query = r300_end_query; |
||
212 | r300->context.get_query_result = r300_get_query_result; |
||
213 | r300->context.render_condition = r300_render_condition; |
||
214 | }> |