2 * Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com>
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
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
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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Maciej Cencora <m.cencora@gmail.com>
27 #include "radeon_common.h"
28 #include "radeon_queryobj.h"
29 #include "radeon_debug.h"
31 #include "main/imports.h"
35 static void radeonQueryGetResult(struct gl_context
*ctx
, struct gl_query_object
*q
)
37 struct radeon_query_object
*query
= (struct radeon_query_object
*)q
;
41 radeon_print(RADEON_STATE
, RADEON_VERBOSE
,
42 "%s: query id %d, result %d\n",
43 __func__
, query
->Base
.Id
, (int) query
->Base
.Result
);
45 radeon_bo_map(query
->bo
, GL_FALSE
);
46 result
= query
->bo
->ptr
;
48 query
->Base
.Result
= 0;
49 for (i
= 0; i
< query
->curr_offset
/sizeof(uint32_t); ++i
) {
50 query
->Base
.Result
+= LE32_TO_CPU(result
[i
]);
51 radeon_print(RADEON_STATE
, RADEON_TRACE
, "result[%d] = %d\n", i
, LE32_TO_CPU(result
[i
]));
54 radeon_bo_unmap(query
->bo
);
57 static struct gl_query_object
* radeonNewQueryObject(struct gl_context
*ctx
, GLuint id
)
59 struct radeon_query_object
*query
;
61 query
= calloc(1, sizeof(struct radeon_query_object
));
64 query
->Base
.Result
= 0;
65 query
->Base
.Active
= GL_FALSE
;
66 query
->Base
.Ready
= GL_TRUE
;
68 radeon_print(RADEON_STATE
, RADEON_VERBOSE
,"%s: query id %d\n", __func__
, query
->Base
.Id
);
73 static void radeonDeleteQuery(struct gl_context
*ctx
, struct gl_query_object
*q
)
75 struct radeon_query_object
*query
= (struct radeon_query_object
*)q
;
77 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s: query id %d\n", __func__
, q
->Id
);
80 radeon_bo_unref(query
->bo
);
86 static void radeonWaitQuery(struct gl_context
*ctx
, struct gl_query_object
*q
)
88 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
89 struct radeon_query_object
*query
= (struct radeon_query_object
*)q
;
91 /* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */
92 if (radeon_bo_is_referenced_by_cs(query
->bo
, radeon
->cmdbuf
.cs
))
93 ctx
->Driver
.Flush(ctx
);
95 radeon_print(RADEON_STATE
, RADEON_VERBOSE
, "%s: query id %d, bo %p, offset %d\n", __func__
, q
->Id
, query
->bo
, query
->curr_offset
);
97 radeonQueryGetResult(ctx
, q
);
99 query
->Base
.Ready
= GL_TRUE
;
103 static void radeonBeginQuery(struct gl_context
*ctx
, struct gl_query_object
*q
)
105 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
106 struct radeon_query_object
*query
= (struct radeon_query_object
*)q
;
108 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s: query id %d\n", __func__
, q
->Id
);
110 assert(radeon
->query
.current
== NULL
);
112 if (radeon
->dma
.flush
)
113 radeon
->dma
.flush(&radeon
->glCtx
);
116 query
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
, 0, RADEON_QUERY_PAGE_SIZE
, RADEON_QUERY_PAGE_SIZE
, RADEON_GEM_DOMAIN_GTT
, 0);
118 query
->curr_offset
= 0;
120 radeon
->query
.current
= query
;
122 radeon
->query
.queryobj
.dirty
= GL_TRUE
;
123 radeon
->hw
.is_dirty
= GL_TRUE
;
126 void radeonEmitQueryEnd(struct gl_context
*ctx
)
128 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
129 struct radeon_query_object
*query
= radeon
->query
.current
;
134 if (query
->emitted_begin
== GL_FALSE
)
137 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s: query id %d, bo %p, offset %d\n", __func__
, query
->Base
.Id
, query
->bo
, query
->curr_offset
);
139 radeon_cs_space_check_with_bo(radeon
->cmdbuf
.cs
,
141 0, RADEON_GEM_DOMAIN_GTT
);
143 radeon
->vtbl
.emit_query_finish(radeon
);
146 static void radeonEndQuery(struct gl_context
*ctx
, struct gl_query_object
*q
)
148 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
150 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s: query id %d\n", __func__
, q
->Id
);
152 if (radeon
->dma
.flush
)
153 radeon
->dma
.flush(&radeon
->glCtx
);
154 radeonEmitQueryEnd(ctx
);
156 radeon
->query
.current
= NULL
;
159 static void radeonCheckQuery(struct gl_context
*ctx
, struct gl_query_object
*q
)
161 radeon_print(RADEON_STATE
, RADEON_TRACE
, "%s: query id %d\n", __func__
, q
->Id
);
163 #ifdef DRM_RADEON_GEM_BUSY
164 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
166 struct radeon_query_object
*query
= (struct radeon_query_object
*)q
;
169 /* Need to perform a flush, as per ARB_occlusion_query spec */
170 if (radeon_bo_is_referenced_by_cs(query
->bo
, radeon
->cmdbuf
.cs
)) {
171 ctx
->Driver
.Flush(ctx
);
174 if (radeon_bo_is_busy(query
->bo
, &domain
) == 0) {
175 radeonQueryGetResult(ctx
, q
);
176 query
->Base
.Ready
= GL_TRUE
;
179 radeonWaitQuery(ctx
, q
);
183 void radeonInitQueryObjFunctions(struct dd_function_table
*functions
)
185 functions
->NewQueryObject
= radeonNewQueryObject
;
186 functions
->DeleteQuery
= radeonDeleteQuery
;
187 functions
->BeginQuery
= radeonBeginQuery
;
188 functions
->EndQuery
= radeonEndQuery
;
189 functions
->CheckQuery
= radeonCheckQuery
;
190 functions
->WaitQuery
= radeonWaitQuery
;
193 int radeon_check_query_active(struct gl_context
*ctx
, struct radeon_state_atom
*atom
)
195 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
196 struct radeon_query_object
*query
= radeon
->query
.current
;
198 if (!query
|| query
->emitted_begin
)
200 return atom
->cmd_size
;
203 void radeon_emit_queryobj(struct gl_context
*ctx
, struct radeon_state_atom
*atom
)
205 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
206 BATCH_LOCALS(radeon
);
209 dwords
= atom
->check(ctx
, atom
);
212 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
215 radeon
->query
.current
->emitted_begin
= GL_TRUE
;