Home | History | Annotate | Download | only in softpipe
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 /* Author:
     29  *    Keith Whitwell <keith (at) tungstengraphics.com>
     30  */
     31 
     32 #include "draw/draw_context.h"
     33 #include "os/os_time.h"
     34 #include "pipe/p_defines.h"
     35 #include "util/u_memory.h"
     36 #include "sp_context.h"
     37 #include "sp_query.h"
     38 #include "sp_state.h"
     39 
     40 struct softpipe_query {
     41    unsigned type;
     42    uint64_t start;
     43    uint64_t end;
     44    struct pipe_query_data_so_statistics so;
     45    unsigned num_primitives_generated;
     46 };
     47 
     48 
     49 static struct softpipe_query *softpipe_query( struct pipe_query *p )
     50 {
     51    return (struct softpipe_query *)p;
     52 }
     53 
     54 static struct pipe_query *
     55 softpipe_create_query(struct pipe_context *pipe,
     56 		      unsigned type)
     57 {
     58    struct softpipe_query* sq;
     59 
     60    assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
     61           type == PIPE_QUERY_TIME_ELAPSED ||
     62           type == PIPE_QUERY_SO_STATISTICS ||
     63           type == PIPE_QUERY_PRIMITIVES_EMITTED ||
     64           type == PIPE_QUERY_PRIMITIVES_GENERATED ||
     65           type == PIPE_QUERY_GPU_FINISHED ||
     66           type == PIPE_QUERY_TIMESTAMP ||
     67           type == PIPE_QUERY_TIMESTAMP_DISJOINT);
     68    sq = CALLOC_STRUCT( softpipe_query );
     69    sq->type = type;
     70 
     71    return (struct pipe_query *)sq;
     72 }
     73 
     74 
     75 static void
     76 softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
     77 {
     78    FREE(q);
     79 }
     80 
     81 
     82 static void
     83 softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
     84 {
     85    struct softpipe_context *softpipe = softpipe_context( pipe );
     86    struct softpipe_query *sq = softpipe_query(q);
     87 
     88    switch (sq->type) {
     89    case PIPE_QUERY_OCCLUSION_COUNTER:
     90       sq->start = softpipe->occlusion_count;
     91       break;
     92    case PIPE_QUERY_TIMESTAMP_DISJOINT:
     93    case PIPE_QUERY_TIME_ELAPSED:
     94       sq->start = 1000*os_time_get();
     95       break;
     96    case PIPE_QUERY_SO_STATISTICS:
     97       sq->so.primitives_storage_needed = 0;
     98    case PIPE_QUERY_PRIMITIVES_EMITTED:
     99       sq->so.num_primitives_written = 0;
    100       softpipe->so_stats.num_primitives_written = 0;
    101       break;
    102    case PIPE_QUERY_PRIMITIVES_GENERATED:
    103       sq->num_primitives_generated = 0;
    104       softpipe->num_primitives_generated = 0;
    105       break;
    106    case PIPE_QUERY_TIMESTAMP:
    107    case PIPE_QUERY_GPU_FINISHED:
    108       break;
    109    default:
    110       assert(0);
    111       break;
    112    }
    113    softpipe->active_query_count++;
    114    softpipe->dirty |= SP_NEW_QUERY;
    115 }
    116 
    117 
    118 static void
    119 softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
    120 {
    121    struct softpipe_context *softpipe = softpipe_context( pipe );
    122    struct softpipe_query *sq = softpipe_query(q);
    123 
    124    softpipe->active_query_count--;
    125    switch (sq->type) {
    126    case PIPE_QUERY_OCCLUSION_COUNTER:
    127       sq->end = softpipe->occlusion_count;
    128       break;
    129    case PIPE_QUERY_TIMESTAMP:
    130       sq->start = 0;
    131       /* fall through */
    132    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    133    case PIPE_QUERY_TIME_ELAPSED:
    134       sq->end = 1000*os_time_get();
    135       break;
    136    case PIPE_QUERY_SO_STATISTICS:
    137       sq->so.primitives_storage_needed =
    138          softpipe->so_stats.primitives_storage_needed;
    139    case PIPE_QUERY_PRIMITIVES_EMITTED:
    140       sq->so.num_primitives_written =
    141          softpipe->so_stats.num_primitives_written;
    142       break;
    143    case PIPE_QUERY_PRIMITIVES_GENERATED:
    144       sq->num_primitives_generated = softpipe->num_primitives_generated;
    145       break;
    146    case PIPE_QUERY_GPU_FINISHED:
    147       break;
    148    default:
    149       assert(0);
    150       break;
    151    }
    152    softpipe->dirty |= SP_NEW_QUERY;
    153 }
    154 
    155 
    156 static boolean
    157 softpipe_get_query_result(struct pipe_context *pipe,
    158 			  struct pipe_query *q,
    159 			  boolean wait,
    160 			  union pipe_query_result *vresult)
    161 {
    162    struct softpipe_query *sq = softpipe_query(q);
    163    uint64_t *result = (uint64_t*)vresult;
    164 
    165    switch (sq->type) {
    166    case PIPE_QUERY_SO_STATISTICS:
    167       memcpy(vresult, &sq->so,
    168              sizeof(struct pipe_query_data_so_statistics));
    169       break;
    170    case PIPE_QUERY_GPU_FINISHED:
    171       *result = TRUE;
    172       break;
    173    case PIPE_QUERY_TIMESTAMP_DISJOINT: {
    174       struct pipe_query_data_timestamp_disjoint td;
    175       /*os_get_time is in microseconds*/
    176       td.frequency = 1000000;
    177       td.disjoint = sq->end != sq->start;
    178       memcpy(vresult, &td,
    179              sizeof(struct pipe_query_data_timestamp_disjoint));
    180    }
    181       break;
    182    case PIPE_QUERY_PRIMITIVES_EMITTED:
    183       *result = sq->so.num_primitives_written;
    184       break;
    185    case PIPE_QUERY_PRIMITIVES_GENERATED:
    186       *result = sq->num_primitives_generated;
    187       break;
    188    default:
    189       *result = sq->end - sq->start;
    190       break;
    191    }
    192    return TRUE;
    193 }
    194 
    195 
    196 /**
    197  * Called by rendering function to check rendering is conditional.
    198  * \return TRUE if we should render, FALSE if we should skip rendering
    199  */
    200 boolean
    201 softpipe_check_render_cond(struct softpipe_context *sp)
    202 {
    203    struct pipe_context *pipe = &sp->pipe;
    204    boolean b, wait;
    205    uint64_t result;
    206 
    207    if (!sp->render_cond_query) {
    208       return TRUE;  /* no query predicate, draw normally */
    209    }
    210 
    211    wait = (sp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
    212            sp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
    213 
    214    b = pipe->get_query_result(pipe, sp->render_cond_query, wait,
    215                               (void*)&result);
    216    if (b)
    217       return result > 0;
    218    else
    219       return TRUE;
    220 }
    221 
    222 
    223 void softpipe_init_query_funcs(struct softpipe_context *softpipe )
    224 {
    225    softpipe->pipe.create_query = softpipe_create_query;
    226    softpipe->pipe.destroy_query = softpipe_destroy_query;
    227    softpipe->pipe.begin_query = softpipe_begin_query;
    228    softpipe->pipe.end_query = softpipe_end_query;
    229    softpipe->pipe.get_query_result = softpipe_get_query_result;
    230 }
    231 
    232 
    233