OSDN Git Service

i965/vec4: Fix confusion between SWIZZLE and BRW_SWIZZLE macros.
[android-x86/external-mesa.git] / src / mesa / state_tracker / st_cb_queryobj.c
1 /**************************************************************************
2  * 
3  * Copyright 2007 VMware, Inc.
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 VMWARE 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
39 #include "pipe/p_context.h"
40 #include "pipe/p_defines.h"
41 #include "pipe/p_screen.h"
42 #include "st_context.h"
43 #include "st_cb_queryobj.h"
44 #include "st_cb_bitmap.h"
45
46
47 static struct gl_query_object *
48 st_NewQueryObject(struct gl_context *ctx, GLuint id)
49 {
50    struct st_query_object *stq = ST_CALLOC_STRUCT(st_query_object);
51    if (stq) {
52       stq->base.Id = id;
53       stq->base.Ready = GL_TRUE;
54       stq->pq = NULL;
55       stq->type = PIPE_QUERY_TYPES; /* an invalid value */
56       return &stq->base;
57    }
58    return NULL;
59 }
60
61
62
63 static void
64 st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
65 {
66    struct pipe_context *pipe = st_context(ctx)->pipe;
67    struct st_query_object *stq = st_query_object(q);
68
69    if (stq->pq) {
70       pipe->destroy_query(pipe, stq->pq);
71       stq->pq = NULL;
72    }
73
74    if (stq->pq_begin) {
75       pipe->destroy_query(pipe, stq->pq_begin);
76       stq->pq_begin = NULL;
77    }
78
79    free(stq);
80 }
81
82
83 static void
84 st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
85 {
86    struct st_context *st = st_context(ctx);
87    struct pipe_context *pipe = st->pipe;
88    struct st_query_object *stq = st_query_object(q);
89    unsigned type;
90
91    st_flush_bitmap_cache(st_context(ctx));
92
93    /* convert GL query type to Gallium query type */
94    switch (q->Target) {
95    case GL_ANY_SAMPLES_PASSED:
96    case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
97       /* fall-through */
98    case GL_SAMPLES_PASSED_ARB:
99       type = PIPE_QUERY_OCCLUSION_COUNTER;
100       break;
101    case GL_PRIMITIVES_GENERATED:
102       type = PIPE_QUERY_PRIMITIVES_GENERATED;
103       break;
104    case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
105       type = PIPE_QUERY_PRIMITIVES_EMITTED;
106       break;
107    case GL_TIME_ELAPSED:
108       if (st->has_time_elapsed)
109          type = PIPE_QUERY_TIME_ELAPSED;
110       else
111          type = PIPE_QUERY_TIMESTAMP;
112       break;
113    default:
114       assert(0 && "unexpected query target in st_BeginQuery()");
115       return;
116    }
117
118    if (stq->type != type) {
119       /* free old query of different type */
120       if (stq->pq) {
121          pipe->destroy_query(pipe, stq->pq);
122          stq->pq = NULL;
123       }
124       if (stq->pq_begin) {
125          pipe->destroy_query(pipe, stq->pq_begin);
126          stq->pq_begin = NULL;
127       }
128       stq->type = PIPE_QUERY_TYPES; /* an invalid value */
129    }
130
131    if (q->Target == GL_TIME_ELAPSED &&
132        type == PIPE_QUERY_TIMESTAMP) {
133       /* Determine time elapsed by emitting two timestamp queries. */
134       if (!stq->pq_begin) {
135          stq->pq_begin = pipe->create_query(pipe, type);
136          stq->type = type;
137       }
138       pipe->end_query(pipe, stq->pq_begin);
139    } else {
140       if (!stq->pq) {
141          stq->pq = pipe->create_query(pipe, type);
142          stq->type = type;
143       }
144       pipe->begin_query(pipe, stq->pq);
145    }
146    assert(stq->type == type);
147 }
148
149
150 static void
151 st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
152 {
153    struct pipe_context *pipe = st_context(ctx)->pipe;
154    struct st_query_object *stq = st_query_object(q);
155
156    st_flush_bitmap_cache(st_context(ctx));
157
158    if ((q->Target == GL_TIMESTAMP ||
159         q->Target == GL_TIME_ELAPSED) &&
160        !stq->pq) {
161       stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
162       stq->type = PIPE_QUERY_TIMESTAMP;
163    }
164
165    pipe->end_query(pipe, stq->pq);
166 }
167
168
169 static boolean
170 get_query_result(struct pipe_context *pipe,
171                  struct st_query_object *stq,
172                  boolean wait)
173 {
174    if (!pipe->get_query_result(pipe,
175                                stq->pq,
176                                wait,
177                                (void *)&stq->base.Result)) {
178       return FALSE;
179    }
180
181    if (stq->base.Target == GL_TIME_ELAPSED &&
182        stq->type == PIPE_QUERY_TIMESTAMP) {
183       /* Calculate the elapsed time from the two timestamp queries */
184       GLuint64EXT Result0 = 0;
185       assert(stq->pq_begin);
186       pipe->get_query_result(pipe, stq->pq_begin, TRUE, (void *)&Result0);
187       stq->base.Result -= Result0;
188    } else {
189       assert(!stq->pq_begin);
190    }
191
192    return TRUE;
193 }
194
195
196 static void
197 st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
198 {
199    struct pipe_context *pipe = st_context(ctx)->pipe;
200    struct st_query_object *stq = st_query_object(q);
201
202    /* this function should only be called if we don't have a ready result */
203    assert(!stq->base.Ready);
204
205    while (!stq->base.Ready &&
206           !get_query_result(pipe, stq, TRUE))
207    {
208       /* nothing */
209    }
210                             
211    q->Ready = GL_TRUE;
212 }
213
214
215 static void
216 st_CheckQuery(struct gl_context *ctx, struct gl_query_object *q)
217 {
218    struct pipe_context *pipe = st_context(ctx)->pipe;
219    struct st_query_object *stq = st_query_object(q);
220    assert(!q->Ready);   /* we should not get called if Ready is TRUE */
221    q->Ready = get_query_result(pipe, stq, FALSE);
222 }
223
224
225 static uint64_t
226 st_GetTimestamp(struct gl_context *ctx)
227 {
228    struct pipe_screen *screen = st_context(ctx)->pipe->screen;
229
230    return screen->get_timestamp(screen);
231 }
232
233
234 void st_init_query_functions(struct dd_function_table *functions)
235 {
236    functions->NewQueryObject = st_NewQueryObject;
237    functions->DeleteQuery = st_DeleteQuery;
238    functions->BeginQuery = st_BeginQuery;
239    functions->EndQuery = st_EndQuery;
240    functions->WaitQuery = st_WaitQuery;
241    functions->CheckQuery = st_CheckQuery;
242    functions->GetTimestamp = st_GetTimestamp;
243 }