Home | History | Annotate | Download | only in radeon
      1 /*
      2  * Copyright  2008-2009 Maciej Cencora <m.cencora (at) 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 (at) gmail.com>
     25  *
     26  */
     27 #include "radeon_common.h"
     28 #include "radeon_queryobj.h"
     29 #include "radeon_debug.h"
     30 
     31 #include "main/imports.h"
     32 #include "main/simple_list.h"
     33 
     34 #include <inttypes.h>
     35 
     36 static void radeonQueryGetResult(struct gl_context *ctx, struct gl_query_object *q)
     37 {
     38 	struct radeon_query_object *query = (struct radeon_query_object *)q;
     39         uint32_t *result;
     40 	int i;
     41 
     42 	radeon_print(RADEON_STATE, RADEON_VERBOSE,
     43 			"%s: query id %d, result %d\n",
     44 			__FUNCTION__, query->Base.Id, (int) query->Base.Result);
     45 
     46 	radeon_bo_map(query->bo, GL_FALSE);
     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 += LE32_TO_CPU(result[i]);
     52 		radeon_print(RADEON_STATE, RADEON_TRACE, "result[%d] = %d\n", i, LE32_TO_CPU(result[i]));
     53 	}
     54 
     55 	radeon_bo_unmap(query->bo);
     56 }
     57 
     58 static struct gl_query_object * radeonNewQueryObject(struct gl_context *ctx, GLuint id)
     59 {
     60 	struct radeon_query_object *query;
     61 
     62 	query = calloc(1, 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 	radeon_print(RADEON_STATE, RADEON_VERBOSE,"%s: query id %d\n", __FUNCTION__, query->Base.Id);
     70 
     71 	return &query->Base;
     72 }
     73 
     74 static void radeonDeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
     75 {
     76 	struct radeon_query_object *query = (struct radeon_query_object *)q;
     77 
     78 	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id);
     79 
     80 	if (query->bo) {
     81 		radeon_bo_unref(query->bo);
     82 	}
     83 
     84 	free(query);
     85 }
     86 
     87 static void radeonWaitQuery(struct gl_context *ctx, struct gl_query_object *q)
     88 {
     89 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
     90 	struct radeon_query_object *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 	if (radeon_bo_is_referenced_by_cs(query->bo, radeon->cmdbuf.cs))
     94 		ctx->Driver.Flush(ctx);
     95 
     96 	radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset);
     97 
     98 	radeonQueryGetResult(ctx, q);
     99 
    100 	query->Base.Ready = GL_TRUE;
    101 }
    102 
    103 
    104 static void radeonBeginQuery(struct gl_context *ctx, struct gl_query_object *q)
    105 {
    106 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    107 	struct radeon_query_object *query = (struct radeon_query_object *)q;
    108 
    109 	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id);
    110 
    111 	assert(radeon->query.current == NULL);
    112 
    113 	if (radeon->dma.flush)
    114 		radeon->dma.flush(radeon->glCtx);
    115 
    116 	if (!query->bo) {
    117 		query->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, RADEON_QUERY_PAGE_SIZE, RADEON_QUERY_PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0);
    118 	}
    119 	query->curr_offset = 0;
    120 
    121 	radeon->query.current = query;
    122 
    123 	radeon->query.queryobj.dirty = GL_TRUE;
    124 	radeon->hw.is_dirty = GL_TRUE;
    125 }
    126 
    127 void radeonEmitQueryEnd(struct gl_context *ctx)
    128 {
    129 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    130 	struct radeon_query_object *query = radeon->query.current;
    131 
    132 	if (!query)
    133 		return;
    134 
    135 	if (query->emitted_begin == GL_FALSE)
    136 		return;
    137 
    138 	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset);
    139 
    140 	radeon_cs_space_check_with_bo(radeon->cmdbuf.cs,
    141 				      query->bo,
    142 				      0, RADEON_GEM_DOMAIN_GTT);
    143 
    144 	radeon->vtbl.emit_query_finish(radeon);
    145 }
    146 
    147 static void radeonEndQuery(struct gl_context *ctx, struct gl_query_object *q)
    148 {
    149 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    150 
    151 	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id);
    152 
    153 	if (radeon->dma.flush)
    154 		radeon->dma.flush(radeon->glCtx);
    155 	radeonEmitQueryEnd(ctx);
    156 
    157 	radeon->query.current = NULL;
    158 }
    159 
    160 static void radeonCheckQuery(struct gl_context *ctx, struct gl_query_object *q)
    161 {
    162 	radeon_print(RADEON_STATE, RADEON_TRACE, "%s: query id %d\n", __FUNCTION__, q->Id);
    163 \
    164 #ifdef DRM_RADEON_GEM_BUSY
    165 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    166 
    167 	struct radeon_query_object *query = (struct radeon_query_object *)q;
    168 	uint32_t domain;
    169 
    170 	/* Need to perform a flush, as per ARB_occlusion_query spec */
    171 	if (radeon_bo_is_referenced_by_cs(query->bo, radeon->cmdbuf.cs)) {
    172 		ctx->Driver.Flush(ctx);
    173 	}
    174 
    175 	if (radeon_bo_is_busy(query->bo, &domain) == 0) {
    176 		radeonQueryGetResult(ctx, q);
    177 		query->Base.Ready = GL_TRUE;
    178 	}
    179 #else
    180 	radeonWaitQuery(ctx, q);
    181 #endif
    182 }
    183 
    184 void radeonInitQueryObjFunctions(struct dd_function_table *functions)
    185 {
    186 	functions->NewQueryObject = radeonNewQueryObject;
    187 	functions->DeleteQuery = radeonDeleteQuery;
    188 	functions->BeginQuery = radeonBeginQuery;
    189 	functions->EndQuery = radeonEndQuery;
    190 	functions->CheckQuery = radeonCheckQuery;
    191 	functions->WaitQuery = radeonWaitQuery;
    192 }
    193 
    194 int radeon_check_query_active(struct gl_context *ctx, struct radeon_state_atom *atom)
    195 {
    196 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    197 	struct radeon_query_object *query = radeon->query.current;
    198 
    199 	if (!query || query->emitted_begin)
    200 		return 0;
    201 	return atom->cmd_size;
    202 }
    203 
    204 void radeon_emit_queryobj(struct gl_context *ctx, struct radeon_state_atom *atom)
    205 {
    206 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    207 	BATCH_LOCALS(radeon);
    208 	int dwords;
    209 
    210 	dwords = (*atom->check) (ctx, atom);
    211 
    212 	BEGIN_BATCH_NO_AUTOSTATE(dwords);
    213 	OUT_BATCH_TABLE(atom->cmd, dwords);
    214 	END_BATCH();
    215 
    216 	radeon->query.current->emitted_begin = GL_TRUE;
    217 }
    218