Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2009 Corbin Simpson <MostAwesomeDude@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/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.                                             unsigned index)
  35. {
  36.     struct r300_context *r300 = r300_context(pipe);
  37.     struct r300_screen *r300screen = r300->screen;
  38.     struct r300_query *q;
  39.  
  40.     if (query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
  41.         query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
  42.         query_type != PIPE_QUERY_GPU_FINISHED) {
  43.         return NULL;
  44.     }
  45.  
  46.     q = CALLOC_STRUCT(r300_query);
  47.     if (!q)
  48.         return NULL;
  49.  
  50.     q->type = query_type;
  51.  
  52.     if (query_type == PIPE_QUERY_GPU_FINISHED) {
  53.         return (struct pipe_query*)q;
  54.     }
  55.  
  56.     if (r300screen->caps.family == CHIP_RV530)
  57.         q->num_pipes = r300screen->info.r300_num_z_pipes;
  58.     else
  59.         q->num_pipes = r300screen->info.r300_num_gb_pipes;
  60.  
  61.     q->buf = r300->rws->buffer_create(r300->rws, 4096, 4096, TRUE,
  62.                                       RADEON_DOMAIN_GTT, 0);
  63.     if (!q->buf) {
  64.         FREE(q);
  65.         return NULL;
  66.     }
  67.     q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf);
  68.  
  69.     return (struct pipe_query*)q;
  70. }
  71.  
  72. static void r300_destroy_query(struct pipe_context* pipe,
  73.                                struct pipe_query* query)
  74. {
  75.     struct r300_query* q = r300_query(query);
  76.  
  77.     pb_reference(&q->buf, NULL);
  78.     FREE(query);
  79. }
  80.  
  81. void r300_resume_query(struct r300_context *r300,
  82.                        struct r300_query *query)
  83. {
  84.     r300->query_current = query;
  85.     r300_mark_atom_dirty(r300, &r300->query_start);
  86. }
  87.  
  88. static boolean r300_begin_query(struct pipe_context* pipe,
  89.                                 struct pipe_query* query)
  90. {
  91.     struct r300_context* r300 = r300_context(pipe);
  92.     struct r300_query* q = r300_query(query);
  93.  
  94.     if (q->type == PIPE_QUERY_GPU_FINISHED)
  95.         return true;
  96.  
  97.     if (r300->query_current != NULL) {
  98.         fprintf(stderr, "r300: begin_query: "
  99.                 "Some other query has already been started.\n");
  100.         assert(0);
  101.         return false;
  102.     }
  103.  
  104.     q->num_results = 0;
  105.     r300_resume_query(r300, q);
  106.     return true;
  107. }
  108.  
  109. void r300_stop_query(struct r300_context *r300)
  110. {
  111.     r300_emit_query_end(r300);
  112.     r300->query_current = NULL;
  113. }
  114.  
  115. static void r300_end_query(struct pipe_context* pipe,
  116.                            struct pipe_query* query)
  117. {
  118.     struct r300_context* r300 = r300_context(pipe);
  119.     struct r300_query *q = r300_query(query);
  120.  
  121.     if (q->type == PIPE_QUERY_GPU_FINISHED) {
  122.         pb_reference(&q->buf, NULL);
  123.         r300_flush(pipe, RADEON_FLUSH_ASYNC,
  124.                    (struct pipe_fence_handle**)&q->buf);
  125.         return;
  126.     }
  127.  
  128.     if (q != r300->query_current) {
  129.         fprintf(stderr, "r300: end_query: Got invalid query.\n");
  130.         assert(0);
  131.         return;
  132.     }
  133.  
  134.     r300_stop_query(r300);
  135. }
  136.  
  137. static boolean r300_get_query_result(struct pipe_context* pipe,
  138.                                      struct pipe_query* query,
  139.                                      boolean wait,
  140.                                      union pipe_query_result *vresult)
  141. {
  142.     struct r300_context* r300 = r300_context(pipe);
  143.     struct r300_query *q = r300_query(query);
  144.     unsigned i;
  145.     uint32_t temp, *map;
  146.  
  147.     if (q->type == PIPE_QUERY_GPU_FINISHED) {
  148.         if (wait) {
  149.             r300->rws->buffer_wait(q->buf, RADEON_USAGE_READWRITE);
  150.             vresult->b = TRUE;
  151.         } else {
  152.             vresult->b = !r300->rws->buffer_is_busy(q->buf, RADEON_USAGE_READWRITE);
  153.         }
  154.         return vresult->b;
  155.     }
  156.  
  157.     map = r300->rws->buffer_map(q->cs_buf, r300->cs,
  158.                                 PIPE_TRANSFER_READ |
  159.                                 (!wait ? PIPE_TRANSFER_DONTBLOCK : 0));
  160.     if (!map)
  161.         return FALSE;
  162.  
  163.     /* Sum up the results. */
  164.     temp = 0;
  165.     for (i = 0; i < q->num_results; i++) {
  166.         /* Convert little endian values written by GPU to CPU byte order */
  167.         temp += util_le32_to_cpu(*map);
  168.         map++;
  169.     }
  170.  
  171.     r300->rws->buffer_unmap(q->cs_buf);
  172.  
  173.     if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
  174.         vresult->b = temp != 0;
  175.     } else {
  176.         vresult->u64 = temp;
  177.     }
  178.     return TRUE;
  179. }
  180.  
  181. static void r300_render_condition(struct pipe_context *pipe,
  182.                                   struct pipe_query *query,
  183.                                   boolean condition,
  184.                                   uint mode)
  185. {
  186.     struct r300_context *r300 = r300_context(pipe);
  187.     union pipe_query_result result;
  188.     boolean wait;
  189.  
  190.     r300->skip_rendering = FALSE;
  191.  
  192.     if (query) {
  193.         wait = mode == PIPE_RENDER_COND_WAIT ||
  194.                mode == PIPE_RENDER_COND_BY_REGION_WAIT;
  195.  
  196.         if (r300_get_query_result(pipe, query, wait, &result)) {
  197.             if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
  198.                 r300->skip_rendering = condition == result.b;
  199.             } else {
  200.                 r300->skip_rendering = condition == !!result.u64;
  201.             }
  202.         }
  203.     }
  204. }
  205.  
  206. void r300_init_query_functions(struct r300_context* r300)
  207. {
  208.     r300->context.create_query = r300_create_query;
  209.     r300->context.destroy_query = r300_destroy_query;
  210.     r300->context.begin_query = r300_begin_query;
  211.     r300->context.end_query = r300_end_query;
  212.     r300->context.get_query_result = r300_get_query_result;
  213.     r300->context.render_condition = r300_render_condition;
  214. }
  215.