st/mesa: implement glBitmap unpacking from a PBO, for the cache path
[mesa.git] / src / mesa / state_tracker / st_cb_queryobj.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 /**
30 * glBegin/EndQuery interface to pipe
31 *
32 * \author Brian Paul
33 */
34
35
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/mfeatures.h"
39
40 #include "pipe/p_context.h"
41 #include "pipe/p_defines.h"
42 #include "pipe/p_screen.h"
43 #include "st_context.h"
44 #include "st_cb_queryobj.h"
45 #include "st_cb_bitmap.h"
46
47
48 static struct gl_query_object *
49 st_NewQueryObject(struct gl_context *ctx, GLuint id)
50 {
51 struct st_query_object *stq = ST_CALLOC_STRUCT(st_query_object);
52 if (stq) {
53 stq->base.Id = id;
54 stq->base.Ready = GL_TRUE;
55 stq->pq = NULL;
56 stq->type = PIPE_QUERY_TYPES; /* an invalid value */
57 return &stq->base;
58 }
59 return NULL;
60 }
61
62
63
64 static void
65 st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
66 {
67 struct pipe_context *pipe = st_context(ctx)->pipe;
68 struct st_query_object *stq = st_query_object(q);
69
70 if (stq->pq) {
71 pipe->destroy_query(pipe, stq->pq);
72 stq->pq = NULL;
73 }
74
75 if (stq->pq_begin) {
76 pipe->destroy_query(pipe, stq->pq_begin);
77 stq->pq_begin = NULL;
78 }
79
80 free(stq);
81 }
82
83
84 static void
85 st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
86 {
87 struct st_context *st = st_context(ctx);
88 struct pipe_context *pipe = st->pipe;
89 struct st_query_object *stq = st_query_object(q);
90 unsigned type;
91
92 st_flush_bitmap_cache(st_context(ctx));
93
94 /* convert GL query type to Gallium query type */
95 switch (q->Target) {
96 case GL_ANY_SAMPLES_PASSED:
97 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
98 /* fall-through */
99 case GL_SAMPLES_PASSED_ARB:
100 type = PIPE_QUERY_OCCLUSION_COUNTER;
101 break;
102 case GL_PRIMITIVES_GENERATED:
103 type = PIPE_QUERY_PRIMITIVES_GENERATED;
104 break;
105 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
106 type = PIPE_QUERY_PRIMITIVES_EMITTED;
107 break;
108 case GL_TIME_ELAPSED:
109 if (st->has_time_elapsed)
110 type = PIPE_QUERY_TIME_ELAPSED;
111 else
112 type = PIPE_QUERY_TIMESTAMP;
113 break;
114 default:
115 assert(0 && "unexpected query target in st_BeginQuery()");
116 return;
117 }
118
119 if (stq->type != type) {
120 /* free old query of different type */
121 if (stq->pq) {
122 pipe->destroy_query(pipe, stq->pq);
123 stq->pq = NULL;
124 }
125 if (stq->pq_begin) {
126 pipe->destroy_query(pipe, stq->pq_begin);
127 stq->pq_begin = NULL;
128 }
129 stq->type = PIPE_QUERY_TYPES; /* an invalid value */
130 }
131
132 if (q->Target == GL_TIME_ELAPSED &&
133 type == PIPE_QUERY_TIMESTAMP) {
134 /* Determine time elapsed by emitting two timestamp queries. */
135 if (!stq->pq_begin) {
136 stq->pq_begin = pipe->create_query(pipe, type);
137 stq->type = type;
138 }
139 pipe->end_query(pipe, stq->pq_begin);
140 } else {
141 if (!stq->pq) {
142 stq->pq = pipe->create_query(pipe, type);
143 stq->type = type;
144 }
145 pipe->begin_query(pipe, stq->pq);
146 }
147 assert(stq->type == type);
148 }
149
150
151 static void
152 st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
153 {
154 struct pipe_context *pipe = st_context(ctx)->pipe;
155 struct st_query_object *stq = st_query_object(q);
156
157 st_flush_bitmap_cache(st_context(ctx));
158
159 if ((q->Target == GL_TIMESTAMP ||
160 q->Target == GL_TIME_ELAPSED) &&
161 !stq->pq) {
162 stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
163 stq->type = PIPE_QUERY_TIMESTAMP;
164 }
165
166 pipe->end_query(pipe, stq->pq);
167 }
168
169
170 static boolean
171 get_query_result(struct pipe_context *pipe,
172 struct st_query_object *stq,
173 boolean wait)
174 {
175 if (!pipe->get_query_result(pipe,
176 stq->pq,
177 wait,
178 (void *)&stq->base.Result)) {
179 return FALSE;
180 }
181
182 if (stq->base.Target == GL_TIME_ELAPSED &&
183 stq->type == PIPE_QUERY_TIMESTAMP) {
184 /* Calculate the elapsed time from the two timestamp queries */
185 GLuint64EXT Result0 = 0;
186 assert(stq->pq_begin);
187 pipe->get_query_result(pipe, stq->pq_begin, TRUE, (void *)&Result0);
188 stq->base.Result -= Result0;
189 } else {
190 assert(!stq->pq_begin);
191 }
192
193 return TRUE;
194 }
195
196
197 static void
198 st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
199 {
200 struct pipe_context *pipe = st_context(ctx)->pipe;
201 struct st_query_object *stq = st_query_object(q);
202
203 /* this function should only be called if we don't have a ready result */
204 assert(!stq->base.Ready);
205
206 while (!stq->base.Ready &&
207 !get_query_result(pipe, stq, TRUE))
208 {
209 /* nothing */
210 }
211
212 q->Ready = GL_TRUE;
213 }
214
215
216 static void
217 st_CheckQuery(struct gl_context *ctx, struct gl_query_object *q)
218 {
219 struct pipe_context *pipe = st_context(ctx)->pipe;
220 struct st_query_object *stq = st_query_object(q);
221 assert(!q->Ready); /* we should not get called if Ready is TRUE */
222 q->Ready = get_query_result(pipe, stq, FALSE);
223 }
224
225
226 static uint64_t
227 st_GetTimestamp(struct gl_context *ctx)
228 {
229 struct pipe_screen *screen = st_context(ctx)->pipe->screen;
230
231 return screen->get_timestamp(screen);
232 }
233
234
235 void st_init_query_functions(struct dd_function_table *functions)
236 {
237 functions->NewQueryObject = st_NewQueryObject;
238 functions->DeleteQuery = st_DeleteQuery;
239 functions->BeginQuery = st_BeginQuery;
240 functions->EndQuery = st_EndQuery;
241 functions->WaitQuery = st_WaitQuery;
242 functions->CheckQuery = st_CheckQuery;
243 functions->GetTimestamp = st_GetTimestamp;
244 }