Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | 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/u_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 | { |
||
35 | struct r300_context *r300 = r300_context(pipe); |
||
36 | struct r300_screen *r300screen = r300->screen; |
||
37 | struct r300_query *q; |
||
38 | |||
39 | if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && |
||
40 | query_type != PIPE_QUERY_OCCLUSION_PREDICATE && |
||
41 | query_type != PIPE_QUERY_GPU_FINISHED) { |
||
42 | return NULL; |
||
43 | } |
||
44 | |||
45 | q = CALLOC_STRUCT(r300_query); |
||
46 | if (!q) |
||
47 | return NULL; |
||
48 | |||
49 | q->type = query_type; |
||
50 | |||
51 | if (query_type == PIPE_QUERY_GPU_FINISHED) { |
||
52 | return (struct pipe_query*)q; |
||
53 | } |
||
54 | |||
55 | if (r300screen->caps.family == CHIP_RV530) |
||
56 | q->num_pipes = r300screen->info.r300_num_z_pipes; |
||
57 | else |
||
58 | q->num_pipes = r300screen->info.r300_num_gb_pipes; |
||
59 | |||
60 | q->buf = r300->rws->buffer_create(r300->rws, 4096, 4096, TRUE, |
||
61 | RADEON_DOMAIN_GTT); |
||
62 | if (!q->buf) { |
||
63 | FREE(q); |
||
64 | return NULL; |
||
65 | } |
||
66 | q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf); |
||
67 | |||
68 | return (struct pipe_query*)q; |
||
69 | } |
||
70 | |||
71 | static void r300_destroy_query(struct pipe_context* pipe, |
||
72 | struct pipe_query* query) |
||
73 | { |
||
74 | struct r300_query* q = r300_query(query); |
||
75 | |||
76 | pb_reference(&q->buf, NULL); |
||
77 | FREE(query); |
||
78 | } |
||
79 | |||
80 | void r300_resume_query(struct r300_context *r300, |
||
81 | struct r300_query *query) |
||
82 | { |
||
83 | r300->query_current = query; |
||
84 | r300_mark_atom_dirty(r300, &r300->query_start); |
||
85 | } |
||
86 | |||
87 | static void r300_begin_query(struct pipe_context* pipe, |
||
88 | struct pipe_query* query) |
||
89 | { |
||
90 | struct r300_context* r300 = r300_context(pipe); |
||
91 | struct r300_query* q = r300_query(query); |
||
92 | |||
93 | if (q->type == PIPE_QUERY_GPU_FINISHED) |
||
94 | return; |
||
95 | |||
96 | if (r300->query_current != NULL) { |
||
97 | fprintf(stderr, "r300: begin_query: " |
||
98 | "Some other query has already been started.\n"); |
||
99 | assert(0); |
||
100 | return; |
||
101 | } |
||
102 | |||
103 | q->num_results = 0; |
||
104 | r300_resume_query(r300, q); |
||
105 | } |
||
106 | |||
107 | void r300_stop_query(struct r300_context *r300) |
||
108 | { |
||
109 | r300_emit_query_end(r300); |
||
110 | r300->query_current = NULL; |
||
111 | } |
||
112 | |||
113 | static void r300_end_query(struct pipe_context* pipe, |
||
114 | struct pipe_query* query) |
||
115 | { |
||
116 | struct r300_context* r300 = r300_context(pipe); |
||
117 | struct r300_query *q = r300_query(query); |
||
118 | |||
119 | if (q->type == PIPE_QUERY_GPU_FINISHED) { |
||
120 | pb_reference(&q->buf, NULL); |
||
121 | r300_flush(pipe, RADEON_FLUSH_ASYNC, |
||
122 | (struct pipe_fence_handle**)&q->buf); |
||
123 | return; |
||
124 | } |
||
125 | |||
126 | if (q != r300->query_current) { |
||
127 | fprintf(stderr, "r300: end_query: Got invalid query.\n"); |
||
128 | assert(0); |
||
129 | return; |
||
130 | } |
||
131 | |||
132 | r300_stop_query(r300); |
||
133 | } |
||
134 | |||
135 | static boolean r300_get_query_result(struct pipe_context* pipe, |
||
136 | struct pipe_query* query, |
||
137 | boolean wait, |
||
138 | union pipe_query_result *vresult) |
||
139 | { |
||
140 | struct r300_context* r300 = r300_context(pipe); |
||
141 | struct r300_query *q = r300_query(query); |
||
142 | unsigned i; |
||
143 | uint32_t temp, *map; |
||
144 | |||
145 | if (q->type == PIPE_QUERY_GPU_FINISHED) { |
||
146 | if (wait) { |
||
147 | r300->rws->buffer_wait(q->buf, RADEON_USAGE_READWRITE); |
||
148 | vresult->b = TRUE; |
||
149 | } else { |
||
150 | vresult->b = !r300->rws->buffer_is_busy(q->buf, RADEON_USAGE_READWRITE); |
||
151 | } |
||
152 | return vresult->b; |
||
153 | } |
||
154 | |||
155 | map = r300->rws->buffer_map(q->cs_buf, r300->cs, |
||
156 | PIPE_TRANSFER_READ | |
||
157 | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0)); |
||
158 | if (!map) |
||
159 | return FALSE; |
||
160 | |||
161 | /* Sum up the results. */ |
||
162 | temp = 0; |
||
163 | for (i = 0; i < q->num_results; i++) { |
||
164 | /* Convert little endian values written by GPU to CPU byte order */ |
||
165 | temp += util_le32_to_cpu(*map); |
||
166 | map++; |
||
167 | } |
||
168 | |||
169 | r300->rws->buffer_unmap(q->cs_buf); |
||
170 | |||
171 | if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) { |
||
172 | vresult->b = temp != 0; |
||
173 | } else { |
||
174 | vresult->u64 = temp; |
||
175 | } |
||
176 | return TRUE; |
||
177 | } |
||
178 | |||
179 | static void r300_render_condition(struct pipe_context *pipe, |
||
180 | struct pipe_query *query, |
||
181 | boolean condition, |
||
182 | uint mode) |
||
183 | { |
||
184 | struct r300_context *r300 = r300_context(pipe); |
||
185 | union pipe_query_result result; |
||
186 | boolean wait; |
||
187 | |||
188 | r300->skip_rendering = FALSE; |
||
189 | |||
190 | if (query) { |
||
191 | wait = mode == PIPE_RENDER_COND_WAIT || |
||
192 | mode == PIPE_RENDER_COND_BY_REGION_WAIT; |
||
193 | |||
194 | if (r300_get_query_result(pipe, query, wait, &result)) { |
||
195 | if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE) { |
||
196 | r300->skip_rendering = condition == result.b; |
||
197 | } else { |
||
198 | r300->skip_rendering = condition == !!result.u64; |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | } |
||
203 | |||
204 | void r300_init_query_functions(struct r300_context* r300) |
||
205 | { |
||
206 | r300->context.create_query = r300_create_query; |
||
207 | r300->context.destroy_query = r300_destroy_query; |
||
208 | r300->context.begin_query = r300_begin_query; |
||
209 | r300->context.end_query = r300_end_query; |
||
210 | r300->context.get_query_result = r300_get_query_result; |
||
211 | r300->context.render_condition = r300_render_condition; |
||
212 | }> |