radeon_queryobj.c revision 9ad76e9479c9c3cb8b2947d5144de33bb31197b8
1/* 2 * Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com> 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 * 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: 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 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 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Maciej Cencora <m.cencora@gmail.com> 25 * 26 */ 27#include "radeon_common.h" 28#include "radeon_queryobj.h" 29 30#include "main/imports.h" 31#include "main/simple_list.h" 32 33#define DDEBUG 0 34 35#define PAGE_SIZE 4096 36 37static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q) 38{ 39 struct radeon_query_object *query = (struct radeon_query_object *)q; 40 uint32_t *result; 41 int i; 42 43 if (DDEBUG) fprintf(stderr, "%s: query id %d, result %d\n", __FUNCTION__, query->Base.Id, (int) query->Base.Result); 44 45 radeon_bo_map(query->bo, GL_FALSE); 46 47 result = query->bo->ptr; 48 49 query->Base.Result = 0; 50 for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) { 51 query->Base.Result += result[i]; 52 if (DDEBUG) fprintf(stderr, "result[%d] = %d\n", i, result[i]); 53 } 54 55 radeon_bo_unmap(query->bo); 56} 57 58static struct gl_query_object * radeonNewQueryObject(GLcontext *ctx, GLuint id) 59{ 60 struct radeon_query_object *query; 61 62 query = _mesa_calloc(sizeof(struct radeon_query_object)); 63 64 query->Base.Id = id; 65 query->Base.Result = 0; 66 query->Base.Active = GL_FALSE; 67 query->Base.Ready = GL_TRUE; 68 69 if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, query->Base.Id); 70 71 return &query->Base; 72} 73 74static void radeonDeleteQuery(GLcontext *ctx, struct gl_query_object *q) 75{ 76 struct radeon_query_object *query = (struct radeon_query_object *)q; 77 78 if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); 79 80 if (query->bo) { 81 radeon_bo_unref(query->bo); 82 } 83 84 _mesa_free(query); 85} 86 87static void radeonWaitQuery(GLcontext *ctx, struct gl_query_object *q) 88{ 89 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 90 struct radeon_query_object *tmp, *query = (struct radeon_query_object *)q; 91 92 /* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */ 93 { 94 GLboolean found = GL_FALSE; 95 foreach(tmp, &radeon->query.not_flushed_head) { 96 if (tmp == query) { 97 found = GL_TRUE; 98 break; 99 } 100 } 101 102 if (found) 103 ctx->Driver.Flush(ctx); 104 } 105 106 if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset); 107 108 radeonQueryGetResult(ctx, q); 109 110 query->Base.Ready = GL_TRUE; 111} 112 113 114static void radeonBeginQuery(GLcontext *ctx, struct gl_query_object *q) 115{ 116 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 117 struct radeon_query_object *query = (struct radeon_query_object *)q; 118 119 if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); 120 121 assert(radeon->query.current == NULL); 122 123 if (radeon->dma.flush) 124 radeon->dma.flush(radeon->glCtx); 125 126 if (!query->bo) { 127 query->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, PAGE_SIZE, PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0); 128 } 129 query->curr_offset = 0; 130 131 radeon->query.current = query; 132 133 radeon->query.queryobj.dirty = GL_TRUE; 134 insert_at_tail(&radeon->query.not_flushed_head, query); 135 136} 137 138void radeonEmitQueryEnd(GLcontext *ctx) 139{ 140 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 141 struct radeon_query_object *query = radeon->query.current; 142 143 if (!query) 144 return; 145 146 if (query->emitted_begin == GL_FALSE) 147 return; 148 149 if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset); 150 151 radeon_cs_space_check_with_bo(radeon->cmdbuf.cs, 152 query->bo, 153 0, RADEON_GEM_DOMAIN_GTT); 154 155 radeon->vtbl.emit_query_finish(radeon); 156} 157 158static void radeonEndQuery(GLcontext *ctx, struct gl_query_object *q) 159{ 160 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 161 162 if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); 163 164 if (radeon->dma.flush) 165 radeon->dma.flush(radeon->glCtx); 166 radeonEmitQueryEnd(ctx); 167 168 radeon->query.current = NULL; 169} 170 171/** 172 * TODO: 173 * should check if bo is idle, bo there's no interface to do it 174 * just wait for result now 175 */ 176static void radeonCheckQuery(GLcontext *ctx, struct gl_query_object *q) 177{ 178 if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); 179 180 radeonWaitQuery(ctx, q); 181} 182 183void radeonInitQueryObjFunctions(struct dd_function_table *functions) 184{ 185 functions->NewQueryObject = radeonNewQueryObject; 186 functions->DeleteQuery = radeonDeleteQuery; 187 functions->BeginQuery = radeonBeginQuery; 188 functions->EndQuery = radeonEndQuery; 189 functions->CheckQuery = radeonCheckQuery; 190 functions->WaitQuery = radeonWaitQuery; 191} 192 193int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom) 194{ 195 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 196 struct radeon_query_object *query = radeon->query.current; 197 198 if (!query || query->emitted_begin) 199 return 0; 200 return atom->cmd_size; 201} 202 203void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom) 204{ 205 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 206 BATCH_LOCALS(radeon); 207 int dwords; 208 209 dwords = (*atom->check) (ctx, atom); 210 211 BEGIN_BATCH_NO_AUTOSTATE(dwords); 212 OUT_BATCH_TABLE(atom->cmd, dwords); 213 END_BATCH(); 214 215 radeon->query.current->emitted_begin = GL_TRUE; 216} 217