Home | History | Annotate | Download | only in r300
      1 /*
      2  * Copyright 2008 Corbin Simpson <MostAwesomeDude (at) gmail.com>
      3  * Copyright 2010 Marek Olk <maraeo (at) gmail.com>
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * on the rights to use, copy, modify, merge, publish, distribute, sub
      9  * license, and/or sell copies of the Software, and to permit persons to whom
     10  * the Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     22  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
     23 
     24 #include "draw/draw_context.h"
     25 #include "draw/draw_private.h"
     26 
     27 #include "util/simple_list.h"
     28 #include "util/u_upload_mgr.h"
     29 
     30 #include "os/os_time.h"
     31 
     32 #include "r300_context.h"
     33 #include "r300_cs.h"
     34 #include "r300_emit.h"
     35 
     36 
     37 static void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags,
     38                                    struct pipe_fence_handle **fence)
     39 {
     40     struct r300_atom *atom;
     41 
     42     r300_emit_hyperz_end(r300);
     43     r300_emit_query_end(r300);
     44     if (r300->screen->caps.is_r500)
     45         r500_emit_index_bias(r300, 0);
     46 
     47     /* The DDX doesn't set these regs. */
     48     {
     49         CS_LOCALS(r300);
     50         OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
     51         OUT_CS(0x66666666);
     52         OUT_CS(0x6666666);
     53     }
     54 
     55     r300->flush_counter++;
     56     r300->rws->cs_flush(r300->cs, flags, fence);
     57     r300->dirty_hw = 0;
     58 
     59     /* New kitchen sink, baby. */
     60     foreach_atom(r300, atom) {
     61         if (atom->state || atom->allow_null_state) {
     62             r300_mark_atom_dirty(r300, atom);
     63         }
     64     }
     65     r300->vertex_arrays_dirty = TRUE;
     66 
     67     /* Unmark HWTCL state for SWTCL. */
     68     if (!r300->screen->caps.has_tcl) {
     69         r300->vs_state.dirty = FALSE;
     70         r300->vs_constants.dirty = FALSE;
     71         r300->clip_state.dirty = FALSE;
     72     }
     73 }
     74 
     75 void r300_flush(struct pipe_context *pipe,
     76                 unsigned flags,
     77                 struct pipe_fence_handle **fence)
     78 {
     79     struct r300_context *r300 = r300_context(pipe);
     80 
     81     if (r300->dirty_hw) {
     82         r300_flush_and_cleanup(r300, flags, fence);
     83     } else {
     84         if (fence) {
     85             /* We have to create a fence object, but the command stream is empty
     86              * and we cannot emit an empty CS. Let's write to some reg. */
     87             CS_LOCALS(r300);
     88             OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0);
     89             r300->rws->cs_flush(r300->cs, flags, fence);
     90         } else {
     91             /* Even if hw is not dirty, we should at least reset the CS in case
     92              * the space checking failed for the first draw operation. */
     93             r300->rws->cs_flush(r300->cs, flags, NULL);
     94         }
     95     }
     96 
     97     /* Update Hyper-Z status. */
     98     if (r300->hyperz_enabled) {
     99         /* If there was a Z clear, keep Hyper-Z access. */
    100         if (r300->num_z_clears) {
    101             r300->hyperz_time_of_last_flush = os_time_get();
    102             r300->num_z_clears = 0;
    103         } else if (r300->hyperz_time_of_last_flush - os_time_get() > 2000000) {
    104             /* If there hasn't been a Z clear for 2 seconds, revoke Hyper-Z access. */
    105             r300->hiz_in_use = FALSE;
    106 
    107             /* Decompress the Z buffer. */
    108             if (r300->zmask_in_use) {
    109                 if (r300->locked_zbuffer) {
    110                     r300_decompress_zmask_locked(r300);
    111                 } else {
    112                     r300_decompress_zmask(r300);
    113                 }
    114 
    115                 if (fence && *fence)
    116                     r300->rws->fence_reference(fence, NULL);
    117                 r300_flush_and_cleanup(r300, flags, fence);
    118             }
    119 
    120             /* Revoke Hyper-Z access, so that some other process can take it. */
    121             r300->rws->cs_request_feature(r300->cs, RADEON_FID_R300_HYPERZ_ACCESS,
    122                                           FALSE);
    123             r300->hyperz_enabled = FALSE;
    124         }
    125     }
    126 }
    127 
    128 static void r300_flush_wrapped(struct pipe_context *pipe,
    129                                struct pipe_fence_handle **fence,
    130                                unsigned flags)
    131 {
    132     r300_flush(pipe,
    133                flags & PIPE_FLUSH_END_OF_FRAME ? RADEON_FLUSH_END_OF_FRAME : 0,
    134                fence);
    135 }
    136 
    137 void r300_init_flush_functions(struct r300_context* r300)
    138 {
    139     r300->context.flush = r300_flush_wrapped;
    140 }
    141