1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "util/u_memory.h" 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "r300_context.h" 26bf215546Sopenharmony_ci#include "r300_screen.h" 27bf215546Sopenharmony_ci#include "r300_emit.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include <stdio.h> 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cistatic struct pipe_query *r300_create_query(struct pipe_context *pipe, 32bf215546Sopenharmony_ci unsigned query_type, 33bf215546Sopenharmony_ci unsigned index) 34bf215546Sopenharmony_ci{ 35bf215546Sopenharmony_ci struct r300_context *r300 = r300_context(pipe); 36bf215546Sopenharmony_ci struct r300_screen *r300screen = r300->screen; 37bf215546Sopenharmony_ci struct r300_query *q; 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && 40bf215546Sopenharmony_ci query_type != PIPE_QUERY_OCCLUSION_PREDICATE && 41bf215546Sopenharmony_ci query_type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE && 42bf215546Sopenharmony_ci query_type != PIPE_QUERY_GPU_FINISHED) { 43bf215546Sopenharmony_ci return NULL; 44bf215546Sopenharmony_ci } 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci q = CALLOC_STRUCT(r300_query); 47bf215546Sopenharmony_ci if (!q) 48bf215546Sopenharmony_ci return NULL; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci q->type = query_type; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci if (query_type == PIPE_QUERY_GPU_FINISHED) { 53bf215546Sopenharmony_ci return (struct pipe_query*)q; 54bf215546Sopenharmony_ci } 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci if (r300screen->caps.family == CHIP_RV530) 57bf215546Sopenharmony_ci q->num_pipes = r300screen->info.r300_num_z_pipes; 58bf215546Sopenharmony_ci else 59bf215546Sopenharmony_ci q->num_pipes = r300screen->info.r300_num_gb_pipes; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci q->buf = r300->rws->buffer_create(r300->rws, 62bf215546Sopenharmony_ci r300screen->info.gart_page_size, 63bf215546Sopenharmony_ci r300screen->info.gart_page_size, 64bf215546Sopenharmony_ci RADEON_DOMAIN_GTT, 65bf215546Sopenharmony_ci RADEON_FLAG_NO_INTERPROCESS_SHARING); 66bf215546Sopenharmony_ci if (!q->buf) { 67bf215546Sopenharmony_ci FREE(q); 68bf215546Sopenharmony_ci return NULL; 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci return (struct pipe_query*)q; 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic void r300_destroy_query(struct pipe_context* pipe, 74bf215546Sopenharmony_ci struct pipe_query* query) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct r300_query* q = r300_query(query); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci pb_reference(&q->buf, NULL); 79bf215546Sopenharmony_ci FREE(query); 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_civoid r300_resume_query(struct r300_context *r300, 83bf215546Sopenharmony_ci struct r300_query *query) 84bf215546Sopenharmony_ci{ 85bf215546Sopenharmony_ci r300->query_current = query; 86bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->query_start); 87bf215546Sopenharmony_ci} 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_cistatic bool r300_begin_query(struct pipe_context* pipe, 90bf215546Sopenharmony_ci struct pipe_query* query) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct r300_context* r300 = r300_context(pipe); 93bf215546Sopenharmony_ci struct r300_query* q = r300_query(query); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (q->type == PIPE_QUERY_GPU_FINISHED) 96bf215546Sopenharmony_ci return true; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci if (r300->query_current != NULL) { 99bf215546Sopenharmony_ci fprintf(stderr, "r300: begin_query: " 100bf215546Sopenharmony_ci "Some other query has already been started.\n"); 101bf215546Sopenharmony_ci assert(0); 102bf215546Sopenharmony_ci return false; 103bf215546Sopenharmony_ci } 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci q->num_results = 0; 106bf215546Sopenharmony_ci r300_resume_query(r300, q); 107bf215546Sopenharmony_ci return true; 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_civoid r300_stop_query(struct r300_context *r300) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci r300_emit_query_end(r300); 113bf215546Sopenharmony_ci r300->query_current = NULL; 114bf215546Sopenharmony_ci} 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_cistatic bool r300_end_query(struct pipe_context* pipe, 117bf215546Sopenharmony_ci struct pipe_query* query) 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci struct r300_context* r300 = r300_context(pipe); 120bf215546Sopenharmony_ci struct r300_query *q = r300_query(query); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci if (q->type == PIPE_QUERY_GPU_FINISHED) { 123bf215546Sopenharmony_ci pb_reference(&q->buf, NULL); 124bf215546Sopenharmony_ci r300_flush(pipe, PIPE_FLUSH_ASYNC, 125bf215546Sopenharmony_ci (struct pipe_fence_handle**)&q->buf); 126bf215546Sopenharmony_ci return true; 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (q != r300->query_current) { 130bf215546Sopenharmony_ci fprintf(stderr, "r300: end_query: Got invalid query.\n"); 131bf215546Sopenharmony_ci assert(0); 132bf215546Sopenharmony_ci return false; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci r300_stop_query(r300); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci return true; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cistatic bool r300_get_query_result(struct pipe_context* pipe, 141bf215546Sopenharmony_ci struct pipe_query* query, 142bf215546Sopenharmony_ci bool wait, 143bf215546Sopenharmony_ci union pipe_query_result *vresult) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci struct r300_context* r300 = r300_context(pipe); 146bf215546Sopenharmony_ci struct r300_query *q = r300_query(query); 147bf215546Sopenharmony_ci unsigned i; 148bf215546Sopenharmony_ci uint32_t temp, *map; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci if (q->type == PIPE_QUERY_GPU_FINISHED) { 151bf215546Sopenharmony_ci if (wait) { 152bf215546Sopenharmony_ci r300->rws->buffer_wait(r300->rws, q->buf, PIPE_TIMEOUT_INFINITE, 153bf215546Sopenharmony_ci RADEON_USAGE_READWRITE); 154bf215546Sopenharmony_ci vresult->b = TRUE; 155bf215546Sopenharmony_ci } else { 156bf215546Sopenharmony_ci vresult->b = r300->rws->buffer_wait(r300->rws, q->buf, 0, RADEON_USAGE_READWRITE); 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci return vresult->b; 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci map = r300->rws->buffer_map(r300->rws, q->buf, &r300->cs, 162bf215546Sopenharmony_ci PIPE_MAP_READ | 163bf215546Sopenharmony_ci (!wait ? PIPE_MAP_DONTBLOCK : 0)); 164bf215546Sopenharmony_ci if (!map) 165bf215546Sopenharmony_ci return FALSE; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci /* Sum up the results. */ 168bf215546Sopenharmony_ci temp = 0; 169bf215546Sopenharmony_ci for (i = 0; i < q->num_results; i++) { 170bf215546Sopenharmony_ci /* Convert little endian values written by GPU to CPU byte order */ 171bf215546Sopenharmony_ci temp += util_le32_to_cpu(*map); 172bf215546Sopenharmony_ci map++; 173bf215546Sopenharmony_ci } 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE || 176bf215546Sopenharmony_ci q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) { 177bf215546Sopenharmony_ci vresult->b = temp != 0; 178bf215546Sopenharmony_ci } else { 179bf215546Sopenharmony_ci vresult->u64 = temp; 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci return TRUE; 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_cistatic void r300_render_condition(struct pipe_context *pipe, 185bf215546Sopenharmony_ci struct pipe_query *query, 186bf215546Sopenharmony_ci bool condition, 187bf215546Sopenharmony_ci enum pipe_render_cond_flag mode) 188bf215546Sopenharmony_ci{ 189bf215546Sopenharmony_ci struct r300_context *r300 = r300_context(pipe); 190bf215546Sopenharmony_ci union pipe_query_result result; 191bf215546Sopenharmony_ci bool wait; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci r300->skip_rendering = FALSE; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci if (query) { 196bf215546Sopenharmony_ci wait = mode == PIPE_RENDER_COND_WAIT || 197bf215546Sopenharmony_ci mode == PIPE_RENDER_COND_BY_REGION_WAIT; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci if (r300_get_query_result(pipe, query, wait, &result)) { 200bf215546Sopenharmony_ci if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE || 201bf215546Sopenharmony_ci r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) { 202bf215546Sopenharmony_ci r300->skip_rendering = condition == result.b; 203bf215546Sopenharmony_ci } else { 204bf215546Sopenharmony_ci r300->skip_rendering = condition == !!result.u64; 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci } 207bf215546Sopenharmony_ci } 208bf215546Sopenharmony_ci} 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_cistatic void 211bf215546Sopenharmony_cir300_set_active_query_state(struct pipe_context *pipe, bool enable) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci} 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_civoid r300_init_query_functions(struct r300_context* r300) 216bf215546Sopenharmony_ci{ 217bf215546Sopenharmony_ci r300->context.create_query = r300_create_query; 218bf215546Sopenharmony_ci r300->context.destroy_query = r300_destroy_query; 219bf215546Sopenharmony_ci r300->context.begin_query = r300_begin_query; 220bf215546Sopenharmony_ci r300->context.end_query = r300_end_query; 221bf215546Sopenharmony_ci r300->context.get_query_result = r300_get_query_result; 222bf215546Sopenharmony_ci r300->context.set_active_query_state = r300_set_active_query_state; 223bf215546Sopenharmony_ci r300->context.render_condition = r300_render_condition; 224bf215546Sopenharmony_ci} 225