1848b8605Smrg/* 2848b8605Smrg * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 8848b8605Smrg * license, and/or sell copies of the Software, and to permit persons to whom 9848b8605Smrg * the Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19848b8605Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20848b8605Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21848b8605Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22848b8605Smrg 23848b8605Smrg#include "util/u_memory.h" 24b8e80941Smrg#include "util/simple_list.h" 25848b8605Smrg 26848b8605Smrg#include "r300_context.h" 27848b8605Smrg#include "r300_screen.h" 28848b8605Smrg#include "r300_emit.h" 29848b8605Smrg 30848b8605Smrg#include <stdio.h> 31848b8605Smrg 32848b8605Smrgstatic struct pipe_query *r300_create_query(struct pipe_context *pipe, 33848b8605Smrg unsigned query_type, 34848b8605Smrg unsigned index) 35848b8605Smrg{ 36848b8605Smrg struct r300_context *r300 = r300_context(pipe); 37848b8605Smrg struct r300_screen *r300screen = r300->screen; 38848b8605Smrg struct r300_query *q; 39848b8605Smrg 40848b8605Smrg if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && 41848b8605Smrg query_type != PIPE_QUERY_OCCLUSION_PREDICATE && 42b8e80941Smrg query_type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE && 43848b8605Smrg query_type != PIPE_QUERY_GPU_FINISHED) { 44848b8605Smrg return NULL; 45848b8605Smrg } 46848b8605Smrg 47848b8605Smrg q = CALLOC_STRUCT(r300_query); 48848b8605Smrg if (!q) 49848b8605Smrg return NULL; 50848b8605Smrg 51848b8605Smrg q->type = query_type; 52848b8605Smrg 53848b8605Smrg if (query_type == PIPE_QUERY_GPU_FINISHED) { 54848b8605Smrg return (struct pipe_query*)q; 55848b8605Smrg } 56848b8605Smrg 57848b8605Smrg if (r300screen->caps.family == CHIP_RV530) 58848b8605Smrg q->num_pipes = r300screen->info.r300_num_z_pipes; 59848b8605Smrg else 60848b8605Smrg q->num_pipes = r300screen->info.r300_num_gb_pipes; 61848b8605Smrg 62b8e80941Smrg q->buf = r300->rws->buffer_create(r300->rws, 63b8e80941Smrg r300screen->info.gart_page_size, 64b8e80941Smrg r300screen->info.gart_page_size, 65b8e80941Smrg RADEON_DOMAIN_GTT, 66b8e80941Smrg RADEON_FLAG_NO_INTERPROCESS_SHARING); 67848b8605Smrg if (!q->buf) { 68848b8605Smrg FREE(q); 69848b8605Smrg return NULL; 70848b8605Smrg } 71848b8605Smrg return (struct pipe_query*)q; 72848b8605Smrg} 73848b8605Smrg 74848b8605Smrgstatic void r300_destroy_query(struct pipe_context* pipe, 75848b8605Smrg struct pipe_query* query) 76848b8605Smrg{ 77848b8605Smrg struct r300_query* q = r300_query(query); 78848b8605Smrg 79848b8605Smrg pb_reference(&q->buf, NULL); 80848b8605Smrg FREE(query); 81848b8605Smrg} 82848b8605Smrg 83848b8605Smrgvoid r300_resume_query(struct r300_context *r300, 84848b8605Smrg struct r300_query *query) 85848b8605Smrg{ 86848b8605Smrg r300->query_current = query; 87848b8605Smrg r300_mark_atom_dirty(r300, &r300->query_start); 88848b8605Smrg} 89848b8605Smrg 90b8e80941Smrgstatic boolean r300_begin_query(struct pipe_context* pipe, 91b8e80941Smrg struct pipe_query* query) 92848b8605Smrg{ 93848b8605Smrg struct r300_context* r300 = r300_context(pipe); 94848b8605Smrg struct r300_query* q = r300_query(query); 95848b8605Smrg 96848b8605Smrg if (q->type == PIPE_QUERY_GPU_FINISHED) 97b8e80941Smrg return true; 98848b8605Smrg 99848b8605Smrg if (r300->query_current != NULL) { 100848b8605Smrg fprintf(stderr, "r300: begin_query: " 101848b8605Smrg "Some other query has already been started.\n"); 102848b8605Smrg assert(0); 103b8e80941Smrg return false; 104848b8605Smrg } 105848b8605Smrg 106848b8605Smrg q->num_results = 0; 107848b8605Smrg r300_resume_query(r300, q); 108b8e80941Smrg return true; 109848b8605Smrg} 110848b8605Smrg 111848b8605Smrgvoid r300_stop_query(struct r300_context *r300) 112848b8605Smrg{ 113848b8605Smrg r300_emit_query_end(r300); 114848b8605Smrg r300->query_current = NULL; 115848b8605Smrg} 116848b8605Smrg 117b8e80941Smrgstatic bool r300_end_query(struct pipe_context* pipe, 118848b8605Smrg struct pipe_query* query) 119848b8605Smrg{ 120848b8605Smrg struct r300_context* r300 = r300_context(pipe); 121848b8605Smrg struct r300_query *q = r300_query(query); 122848b8605Smrg 123848b8605Smrg if (q->type == PIPE_QUERY_GPU_FINISHED) { 124848b8605Smrg pb_reference(&q->buf, NULL); 125b8e80941Smrg r300_flush(pipe, PIPE_FLUSH_ASYNC, 126848b8605Smrg (struct pipe_fence_handle**)&q->buf); 127b8e80941Smrg return true; 128848b8605Smrg } 129848b8605Smrg 130848b8605Smrg if (q != r300->query_current) { 131848b8605Smrg fprintf(stderr, "r300: end_query: Got invalid query.\n"); 132848b8605Smrg assert(0); 133b8e80941Smrg return false; 134848b8605Smrg } 135848b8605Smrg 136848b8605Smrg r300_stop_query(r300); 137b8e80941Smrg 138b8e80941Smrg return true; 139848b8605Smrg} 140848b8605Smrg 141848b8605Smrgstatic boolean r300_get_query_result(struct pipe_context* pipe, 142848b8605Smrg struct pipe_query* query, 143848b8605Smrg boolean wait, 144848b8605Smrg union pipe_query_result *vresult) 145848b8605Smrg{ 146848b8605Smrg struct r300_context* r300 = r300_context(pipe); 147848b8605Smrg struct r300_query *q = r300_query(query); 148848b8605Smrg unsigned i; 149848b8605Smrg uint32_t temp, *map; 150848b8605Smrg 151848b8605Smrg if (q->type == PIPE_QUERY_GPU_FINISHED) { 152848b8605Smrg if (wait) { 153b8e80941Smrg r300->rws->buffer_wait(q->buf, PIPE_TIMEOUT_INFINITE, 154b8e80941Smrg RADEON_USAGE_READWRITE); 155848b8605Smrg vresult->b = TRUE; 156848b8605Smrg } else { 157b8e80941Smrg vresult->b = r300->rws->buffer_wait(q->buf, 0, RADEON_USAGE_READWRITE); 158848b8605Smrg } 159848b8605Smrg return vresult->b; 160848b8605Smrg } 161848b8605Smrg 162b8e80941Smrg map = r300->rws->buffer_map(q->buf, r300->cs, 163848b8605Smrg PIPE_TRANSFER_READ | 164848b8605Smrg (!wait ? PIPE_TRANSFER_DONTBLOCK : 0)); 165848b8605Smrg if (!map) 166848b8605Smrg return FALSE; 167848b8605Smrg 168848b8605Smrg /* Sum up the results. */ 169848b8605Smrg temp = 0; 170848b8605Smrg for (i = 0; i < q->num_results; i++) { 171848b8605Smrg /* Convert little endian values written by GPU to CPU byte order */ 172848b8605Smrg temp += util_le32_to_cpu(*map); 173848b8605Smrg map++; 174848b8605Smrg } 175848b8605Smrg 176b8e80941Smrg if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE || 177b8e80941Smrg q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) { 178848b8605Smrg vresult->b = temp != 0; 179848b8605Smrg } else { 180848b8605Smrg vresult->u64 = temp; 181848b8605Smrg } 182848b8605Smrg return TRUE; 183848b8605Smrg} 184848b8605Smrg 185848b8605Smrgstatic void r300_render_condition(struct pipe_context *pipe, 186848b8605Smrg struct pipe_query *query, 187848b8605Smrg boolean condition, 188b8e80941Smrg enum pipe_render_cond_flag mode) 189848b8605Smrg{ 190848b8605Smrg struct r300_context *r300 = r300_context(pipe); 191848b8605Smrg union pipe_query_result result; 192848b8605Smrg boolean wait; 193848b8605Smrg 194848b8605Smrg r300->skip_rendering = FALSE; 195848b8605Smrg 196848b8605Smrg if (query) { 197848b8605Smrg wait = mode == PIPE_RENDER_COND_WAIT || 198848b8605Smrg mode == PIPE_RENDER_COND_BY_REGION_WAIT; 199848b8605Smrg 200848b8605Smrg if (r300_get_query_result(pipe, query, wait, &result)) { 201b8e80941Smrg if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE || 202b8e80941Smrg r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) { 203848b8605Smrg r300->skip_rendering = condition == result.b; 204848b8605Smrg } else { 205848b8605Smrg r300->skip_rendering = condition == !!result.u64; 206848b8605Smrg } 207848b8605Smrg } 208848b8605Smrg } 209848b8605Smrg} 210848b8605Smrg 211b8e80941Smrgstatic void 212b8e80941Smrgr300_set_active_query_state(struct pipe_context *pipe, boolean enable) 213b8e80941Smrg{ 214b8e80941Smrg} 215b8e80941Smrg 216848b8605Smrgvoid r300_init_query_functions(struct r300_context* r300) 217848b8605Smrg{ 218848b8605Smrg r300->context.create_query = r300_create_query; 219848b8605Smrg r300->context.destroy_query = r300_destroy_query; 220848b8605Smrg r300->context.begin_query = r300_begin_query; 221848b8605Smrg r300->context.end_query = r300_end_query; 222848b8605Smrg r300->context.get_query_result = r300_get_query_result; 223b8e80941Smrg r300->context.set_active_query_state = r300_set_active_query_state; 224848b8605Smrg r300->context.render_condition = r300_render_condition; 225848b8605Smrg} 226