Home | History | Annotate | Download | only in r300
      1 /*
      2  * Copyright 2009 Corbin Simpson <MostAwesomeDude (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  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
     22 
     23 #include "util/u_memory.h"
     24 #include "util/u_simple_list.h"
     25 
     26 #include "r300_context.h"
     27 #include "r300_screen.h"
     28 #include "r300_emit.h"
     29 
     30 #include <stdio.h>
     31 
     32 static struct pipe_query *r300_create_query(struct pipe_context *pipe,
     33                                             unsigned query_type)
     34 {
     35     struct r300_context *r300 = r300_context(pipe);
     36     struct r300_screen *r300screen = r300->screen;
     37     struct r300_query *q;
     38 
     39     if (query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
     40         query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
     41         query_type != PIPE_QUERY_GPU_FINISHED) {
     42         return NULL;
     43     }
     44 
     45     q = CALLOC_STRUCT(r300_query);
     46     if (!q)
     47         return NULL;
     48 
     49     q->type = query_type;
     50 
     51     if (query_type == PIPE_QUERY_GPU_FINISHED) {
     52         return (struct pipe_query*)q;
     53     }
     54 
     55     if (r300screen->caps.family == CHIP_FAMILY_RV530)
     56         q->num_pipes = r300screen->info.r300_num_z_pipes;
     57     else
     58         q->num_pipes = r300screen->info.r300_num_gb_pipes;
     59 
     60     q->buf = r300->rws->buffer_create(r300->rws, 4096, 4096,
     61                                       PIPE_BIND_CUSTOM, RADEON_DOMAIN_GTT);
     62     if (!q->buf) {
     63         FREE(q);
     64         return NULL;
     65     }
     66     q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf);
     67 
     68     return (struct pipe_query*)q;
     69 }
     70 
     71 static void r300_destroy_query(struct pipe_context* pipe,
     72                                struct pipe_query* query)
     73 {
     74     struct r300_query* q = r300_query(query);
     75 
     76     pb_reference(&q->buf, NULL);
     77     FREE(query);
     78 }
     79 
     80 void r300_resume_query(struct r300_context *r300,
     81                        struct r300_query *query)
     82 {
     83     r300->query_current = query;
     84     r300_mark_atom_dirty(r300, &r300->query_start);
     85 }
     86 
     87 static void r300_begin_query(struct pipe_context* pipe,
     88                              struct pipe_query* query)
     89 {
     90     struct r300_context* r300 = r300_context(pipe);
     91     struct r300_query* q = r300_query(query);
     92 
     93     if (q->type == PIPE_QUERY_GPU_FINISHED)
     94         return;
     95 
     96     if (r300->query_current != NULL) {
     97         fprintf(stderr, "r300: begin_query: "
     98                 "Some other query has already been started.\n");
     99         assert(0);
    100         return;
    101     }
    102 
    103     q->num_results = 0;
    104     r300_resume_query(r300, q);
    105 }
    106 
    107 void r300_stop_query(struct r300_context *r300)
    108 {
    109     r300_emit_query_end(r300);
    110     r300->query_current = NULL;
    111 }
    112 
    113 static void r300_end_query(struct pipe_context* pipe,
    114 	                   struct pipe_query* query)
    115 {
    116     struct r300_context* r300 = r300_context(pipe);
    117     struct r300_query *q = r300_query(query);
    118 
    119     if (q->type == PIPE_QUERY_GPU_FINISHED) {
    120         pb_reference(&q->buf, NULL);
    121         r300_flush(pipe, RADEON_FLUSH_ASYNC,
    122                    (struct pipe_fence_handle**)&q->buf);
    123         return;
    124     }
    125 
    126     if (q != r300->query_current) {
    127         fprintf(stderr, "r300: end_query: Got invalid query.\n");
    128         assert(0);
    129         return;
    130     }
    131 
    132     r300_stop_query(r300);
    133 }
    134 
    135 static boolean r300_get_query_result(struct pipe_context* pipe,
    136                                      struct pipe_query* query,
    137                                      boolean wait,
    138                                      union pipe_query_result *vresult)
    139 {
    140     struct r300_context* r300 = r300_context(pipe);
    141     struct r300_query *q = r300_query(query);
    142     unsigned i;
    143     uint32_t temp, *map;
    144 
    145     if (q->type == PIPE_QUERY_GPU_FINISHED) {
    146         if (wait) {
    147             r300->rws->buffer_wait(q->buf, RADEON_USAGE_READWRITE);
    148             vresult->b = TRUE;
    149         } else {
    150             vresult->b = !r300->rws->buffer_is_busy(q->buf, RADEON_USAGE_READWRITE);
    151         }
    152         return vresult->b;
    153     }
    154 
    155     map = r300->rws->buffer_map(q->cs_buf, r300->cs,
    156                                 PIPE_TRANSFER_READ |
    157                                 (!wait ? PIPE_TRANSFER_DONTBLOCK : 0));
    158     if (!map)
    159         return FALSE;
    160 
    161     /* Sum up the results. */
    162     temp = 0;
    163     for (i = 0; i < q->num_results; i++) {
    164         /* Convert little endian values written by GPU to CPU byte order */
    165         temp += util_le32_to_cpu(*map);
    166         map++;
    167     }
    168 
    169     r300->rws->buffer_unmap(q->cs_buf);
    170 
    171     if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
    172         vresult->b = temp != 0;
    173     } else {
    174         vresult->u64 = temp;
    175     }
    176     return TRUE;
    177 }
    178 
    179 static void r300_render_condition(struct pipe_context *pipe,
    180                                   struct pipe_query *query,
    181                                   uint mode)
    182 {
    183     struct r300_context *r300 = r300_context(pipe);
    184     union pipe_query_result result;
    185     boolean wait;
    186 
    187     r300->skip_rendering = FALSE;
    188 
    189     if (query) {
    190         wait = mode == PIPE_RENDER_COND_WAIT ||
    191                mode == PIPE_RENDER_COND_BY_REGION_WAIT;
    192 
    193         if (r300_get_query_result(pipe, query, wait, &result)) {
    194             if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
    195                 r300->skip_rendering = !result.b;
    196             } else {
    197                 r300->skip_rendering = !result.u64;
    198 	    }
    199         }
    200     }
    201 }
    202 
    203 void r300_init_query_functions(struct r300_context* r300)
    204 {
    205     r300->context.create_query = r300_create_query;
    206     r300->context.destroy_query = r300_destroy_query;
    207     r300->context.begin_query = r300_begin_query;
    208     r300->context.end_query = r300_end_query;
    209     r300->context.get_query_result = r300_get_query_result;
    210     r300->context.render_condition = r300_render_condition;
    211 }
    212