14a49301eSmrg/* 24a49301eSmrg * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 33464ebd5Sriastradh * Copyright 2010 Marek Olšák <maraeo@gmail.com> 44a49301eSmrg * 54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64a49301eSmrg * copy of this software and associated documentation files (the "Software"), 74a49301eSmrg * to deal in the Software without restriction, including without limitation 84a49301eSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 94a49301eSmrg * license, and/or sell copies of the Software, and to permit persons to whom 104a49301eSmrg * the Software is furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice (including the next 134a49301eSmrg * paragraph) shall be included in all copies or substantial portions of the 144a49301eSmrg * Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174a49301eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 194a49301eSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 204a49301eSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 214a49301eSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 224a49301eSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 234a49301eSmrg 244a49301eSmrg#include "draw/draw_context.h" 254a49301eSmrg#include "draw/draw_private.h" 264a49301eSmrg 2701e04c3fSmrg#include "util/simple_list.h" 283464ebd5Sriastradh#include "util/u_upload_mgr.h" 293464ebd5Sriastradh 3001e04c3fSmrg#include "util/os_time.h" 314a49301eSmrg 324a49301eSmrg#include "r300_context.h" 334a49301eSmrg#include "r300_cs.h" 344a49301eSmrg#include "r300_emit.h" 354a49301eSmrg 363464ebd5Sriastradh 37af69d88dSmrgstatic void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags, 38af69d88dSmrg struct pipe_fence_handle **fence) 394a49301eSmrg{ 40cdc920a0Smrg struct r300_atom *atom; 414a49301eSmrg 423464ebd5Sriastradh r300_emit_hyperz_end(r300); 433464ebd5Sriastradh r300_emit_query_end(r300); 443464ebd5Sriastradh if (r300->screen->caps.is_r500) 453464ebd5Sriastradh r500_emit_index_bias(r300, 0); 463464ebd5Sriastradh 47af69d88dSmrg /* The DDX doesn't set these regs. */ 4801e04c3fSmrg { 49af69d88dSmrg CS_LOCALS(r300); 50af69d88dSmrg OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2); 51af69d88dSmrg OUT_CS(0x66666666); 52af69d88dSmrg OUT_CS(0x6666666); 53af69d88dSmrg } 54af69d88dSmrg 553464ebd5Sriastradh r300->flush_counter++; 567ec681f3Smrg r300->rws->cs_flush(&r300->cs, flags, fence); 573464ebd5Sriastradh r300->dirty_hw = 0; 583464ebd5Sriastradh 593464ebd5Sriastradh /* New kitchen sink, baby. */ 603464ebd5Sriastradh foreach_atom(r300, atom) { 613464ebd5Sriastradh if (atom->state || atom->allow_null_state) { 623464ebd5Sriastradh r300_mark_atom_dirty(r300, atom); 633464ebd5Sriastradh } 644a49301eSmrg } 653464ebd5Sriastradh r300->vertex_arrays_dirty = TRUE; 664a49301eSmrg 673464ebd5Sriastradh /* Unmark HWTCL state for SWTCL. */ 683464ebd5Sriastradh if (!r300->screen->caps.has_tcl) { 693464ebd5Sriastradh r300->vs_state.dirty = FALSE; 703464ebd5Sriastradh r300->vs_constants.dirty = FALSE; 71af69d88dSmrg r300->clip_state.dirty = FALSE; 723464ebd5Sriastradh } 733464ebd5Sriastradh} 743464ebd5Sriastradh 753464ebd5Sriastradhvoid r300_flush(struct pipe_context *pipe, 763464ebd5Sriastradh unsigned flags, 773464ebd5Sriastradh struct pipe_fence_handle **fence) 783464ebd5Sriastradh{ 793464ebd5Sriastradh struct r300_context *r300 = r300_context(pipe); 80af69d88dSmrg 814a49301eSmrg if (r300->dirty_hw) { 82af69d88dSmrg r300_flush_and_cleanup(r300, flags, fence); 833464ebd5Sriastradh } else { 84af69d88dSmrg if (fence) { 853464ebd5Sriastradh /* We have to create a fence object, but the command stream is empty 863464ebd5Sriastradh * and we cannot emit an empty CS. Let's write to some reg. */ 873464ebd5Sriastradh CS_LOCALS(r300); 883464ebd5Sriastradh OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0); 897ec681f3Smrg r300->rws->cs_flush(&r300->cs, flags, fence); 903464ebd5Sriastradh } else { 913464ebd5Sriastradh /* Even if hw is not dirty, we should at least reset the CS in case 923464ebd5Sriastradh * the space checking failed for the first draw operation. */ 937ec681f3Smrg r300->rws->cs_flush(&r300->cs, flags, NULL); 94cdc920a0Smrg } 954a49301eSmrg } 96cdc920a0Smrg 973464ebd5Sriastradh /* Update Hyper-Z status. */ 98af69d88dSmrg if (r300->hyperz_enabled) { 99af69d88dSmrg /* If there was a Z clear, keep Hyper-Z access. */ 100af69d88dSmrg if (r300->num_z_clears) { 101af69d88dSmrg r300->hyperz_time_of_last_flush = os_time_get(); 102af69d88dSmrg r300->num_z_clears = 0; 103af69d88dSmrg } else if (r300->hyperz_time_of_last_flush - os_time_get() > 2000000) { 104af69d88dSmrg /* If there hasn't been a Z clear for 2 seconds, revoke Hyper-Z access. */ 105af69d88dSmrg r300->hiz_in_use = FALSE; 106af69d88dSmrg 107af69d88dSmrg /* Decompress the Z buffer. */ 108af69d88dSmrg if (r300->zmask_in_use) { 109af69d88dSmrg if (r300->locked_zbuffer) { 110af69d88dSmrg r300_decompress_zmask_locked(r300); 111af69d88dSmrg } else { 112af69d88dSmrg r300_decompress_zmask(r300); 113af69d88dSmrg } 114af69d88dSmrg 115af69d88dSmrg if (fence && *fence) 116af69d88dSmrg r300->rws->fence_reference(fence, NULL); 117af69d88dSmrg r300_flush_and_cleanup(r300, flags, fence); 1183464ebd5Sriastradh } 1193464ebd5Sriastradh 120af69d88dSmrg /* Revoke Hyper-Z access, so that some other process can take it. */ 1217ec681f3Smrg r300->rws->cs_request_feature(&r300->cs, RADEON_FID_R300_HYPERZ_ACCESS, 122af69d88dSmrg FALSE); 123af69d88dSmrg r300->hyperz_enabled = FALSE; 1243464ebd5Sriastradh } 1254a49301eSmrg } 1264a49301eSmrg} 1274a49301eSmrg 1283464ebd5Sriastradhstatic void r300_flush_wrapped(struct pipe_context *pipe, 129af69d88dSmrg struct pipe_fence_handle **fence, 130af69d88dSmrg unsigned flags) 1313464ebd5Sriastradh{ 13201e04c3fSmrg if (flags & PIPE_FLUSH_HINT_FINISH) 13301e04c3fSmrg flags &= ~PIPE_FLUSH_ASYNC; 13401e04c3fSmrg 13501e04c3fSmrg r300_flush(pipe, flags, fence); 1363464ebd5Sriastradh} 1374a49301eSmrg 1384a49301eSmrgvoid r300_init_flush_functions(struct r300_context* r300) 1394a49301eSmrg{ 1403464ebd5Sriastradh r300->context.flush = r300_flush_wrapped; 1414a49301eSmrg} 142