1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 3bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci/* r300_emit: Functions for emitting state. */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "util/format/u_format.h" 27bf215546Sopenharmony_ci#include "util/u_math.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "r300_context.h" 30bf215546Sopenharmony_ci#include "r300_cb.h" 31bf215546Sopenharmony_ci#include "r300_cs.h" 32bf215546Sopenharmony_ci#include "r300_emit.h" 33bf215546Sopenharmony_ci#include "r300_fs.h" 34bf215546Sopenharmony_ci#include "r300_screen.h" 35bf215546Sopenharmony_ci#include "r300_screen_buffer.h" 36bf215546Sopenharmony_ci#include "r300_vs.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_civoid r300_emit_blend_state(struct r300_context* r300, 39bf215546Sopenharmony_ci unsigned size, void* state) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci struct r300_blend_state* blend = (struct r300_blend_state*)state; 42bf215546Sopenharmony_ci struct pipe_framebuffer_state* fb = 43bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 44bf215546Sopenharmony_ci struct pipe_surface *cb; 45bf215546Sopenharmony_ci CS_LOCALS(r300); 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci cb = fb->nr_cbufs ? r300_get_nonnull_cb(fb, 0) : NULL; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci if (cb) { 50bf215546Sopenharmony_ci if (cb->format == PIPE_FORMAT_R16G16B16A16_FLOAT) { 51bf215546Sopenharmony_ci WRITE_CS_TABLE(blend->cb_noclamp, size); 52bf215546Sopenharmony_ci } else if (cb->format == PIPE_FORMAT_R16G16B16X16_FLOAT) { 53bf215546Sopenharmony_ci WRITE_CS_TABLE(blend->cb_noclamp_noalpha, size); 54bf215546Sopenharmony_ci } else { 55bf215546Sopenharmony_ci unsigned swz = r300_surface(cb)->colormask_swizzle; 56bf215546Sopenharmony_ci WRITE_CS_TABLE(blend->cb_clamp[swz], size); 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci } else { 59bf215546Sopenharmony_ci WRITE_CS_TABLE(blend->cb_no_readwrite, size); 60bf215546Sopenharmony_ci } 61bf215546Sopenharmony_ci} 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_civoid r300_emit_blend_color_state(struct r300_context* r300, 64bf215546Sopenharmony_ci unsigned size, void* state) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state; 67bf215546Sopenharmony_ci CS_LOCALS(r300); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci WRITE_CS_TABLE(bc->cb, size); 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_civoid r300_emit_clip_state(struct r300_context* r300, 73bf215546Sopenharmony_ci unsigned size, void* state) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci struct r300_clip_state* clip = (struct r300_clip_state*)state; 76bf215546Sopenharmony_ci CS_LOCALS(r300); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci WRITE_CS_TABLE(clip->cb, size); 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_civoid r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) 82bf215546Sopenharmony_ci{ 83bf215546Sopenharmony_ci struct r300_dsa_state* dsa = (struct r300_dsa_state*)state; 84bf215546Sopenharmony_ci struct pipe_framebuffer_state* fb = 85bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 86bf215546Sopenharmony_ci boolean is_r500 = r300->screen->caps.is_r500; 87bf215546Sopenharmony_ci CS_LOCALS(r300); 88bf215546Sopenharmony_ci uint32_t alpha_func = dsa->alpha_function; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci /* Choose the alpha ref value between 8-bit (FG_ALPHA_FUNC.AM_VAL) and 91bf215546Sopenharmony_ci * 16-bit (FG_ALPHA_VALUE). */ 92bf215546Sopenharmony_ci if (is_r500 && (alpha_func & R300_FG_ALPHA_FUNC_ENABLE)) { 93bf215546Sopenharmony_ci struct pipe_surface *cb = fb->nr_cbufs ? r300_get_nonnull_cb(fb, 0) : NULL; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (cb && 96bf215546Sopenharmony_ci (cb->format == PIPE_FORMAT_R16G16B16A16_FLOAT || 97bf215546Sopenharmony_ci cb->format == PIPE_FORMAT_R16G16B16X16_FLOAT)) { 98bf215546Sopenharmony_ci alpha_func |= R500_FG_ALPHA_FUNC_FP16_ENABLE; 99bf215546Sopenharmony_ci } else { 100bf215546Sopenharmony_ci alpha_func |= R500_FG_ALPHA_FUNC_8BIT; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci /* Setup alpha-to-coverage. */ 105bf215546Sopenharmony_ci if (r300->alpha_to_coverage && r300->msaa_enable) { 106bf215546Sopenharmony_ci /* Always set 3/6, it improves precision even for 2x and 4x MSAA. */ 107bf215546Sopenharmony_ci alpha_func |= R300_FG_ALPHA_FUNC_MASK_ENABLE | 108bf215546Sopenharmony_ci R300_FG_ALPHA_FUNC_CFG_3_OF_6; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci BEGIN_CS(size); 112bf215546Sopenharmony_ci OUT_CS_REG(R300_FG_ALPHA_FUNC, alpha_func); 113bf215546Sopenharmony_ci OUT_CS_TABLE(fb->zsbuf ? &dsa->cb_begin : dsa->cb_zb_no_readwrite, size-2); 114bf215546Sopenharmony_ci END_CS; 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_cistatic void get_rc_constant_state( 118bf215546Sopenharmony_ci float vec[4], 119bf215546Sopenharmony_ci struct r300_context * r300, 120bf215546Sopenharmony_ci struct rc_constant * constant) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci struct r300_textures_state* texstate = r300->textures_state.state; 123bf215546Sopenharmony_ci struct r300_resource *tex; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci assert(constant->Type == RC_CONSTANT_STATE); 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci /* vec should either be (0, 0, 0, 1), which should be a relatively safe 128bf215546Sopenharmony_ci * RGBA or STRQ value, or it could be one of the RC_CONSTANT_STATE 129bf215546Sopenharmony_ci * state factors. */ 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci switch (constant->u.State[0]) { 132bf215546Sopenharmony_ci /* Factor for converting rectangle coords to 133bf215546Sopenharmony_ci * normalized coords. Should only show up on non-r500. */ 134bf215546Sopenharmony_ci case RC_STATE_R300_TEXRECT_FACTOR: 135bf215546Sopenharmony_ci tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture); 136bf215546Sopenharmony_ci vec[0] = 1.0 / tex->tex.width0; 137bf215546Sopenharmony_ci vec[1] = 1.0 / tex->tex.height0; 138bf215546Sopenharmony_ci vec[2] = 0; 139bf215546Sopenharmony_ci vec[3] = 1; 140bf215546Sopenharmony_ci break; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci case RC_STATE_R300_TEXSCALE_FACTOR: 143bf215546Sopenharmony_ci tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture); 144bf215546Sopenharmony_ci /* Add a small number to the texture size to work around rounding errors in hw. */ 145bf215546Sopenharmony_ci vec[0] = tex->b.width0 / (tex->tex.width0 + 0.001f); 146bf215546Sopenharmony_ci vec[1] = tex->b.height0 / (tex->tex.height0 + 0.001f); 147bf215546Sopenharmony_ci vec[2] = tex->b.depth0 / (tex->tex.depth0 + 0.001f); 148bf215546Sopenharmony_ci vec[3] = 1; 149bf215546Sopenharmony_ci break; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci case RC_STATE_R300_VIEWPORT_SCALE: 152bf215546Sopenharmony_ci vec[0] = r300->viewport.scale[0]; 153bf215546Sopenharmony_ci vec[1] = r300->viewport.scale[1]; 154bf215546Sopenharmony_ci vec[2] = r300->viewport.scale[2]; 155bf215546Sopenharmony_ci vec[3] = 1; 156bf215546Sopenharmony_ci break; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci case RC_STATE_R300_VIEWPORT_OFFSET: 159bf215546Sopenharmony_ci vec[0] = r300->viewport.translate[0]; 160bf215546Sopenharmony_ci vec[1] = r300->viewport.translate[1]; 161bf215546Sopenharmony_ci vec[2] = r300->viewport.translate[2]; 162bf215546Sopenharmony_ci vec[3] = 1; 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci default: 166bf215546Sopenharmony_ci fprintf(stderr, "r300: Implementation error: " 167bf215546Sopenharmony_ci "Unknown RC_CONSTANT type %d\n", constant->u.State[0]); 168bf215546Sopenharmony_ci vec[0] = 0; 169bf215546Sopenharmony_ci vec[1] = 0; 170bf215546Sopenharmony_ci vec[2] = 0; 171bf215546Sopenharmony_ci vec[3] = 1; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci} 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci/* Convert a normal single-precision float into the 7.16 format 176bf215546Sopenharmony_ci * used by the R300 fragment shader. 177bf215546Sopenharmony_ci */ 178bf215546Sopenharmony_ciuint32_t pack_float24(float f) 179bf215546Sopenharmony_ci{ 180bf215546Sopenharmony_ci union { 181bf215546Sopenharmony_ci float fl; 182bf215546Sopenharmony_ci uint32_t u; 183bf215546Sopenharmony_ci } u; 184bf215546Sopenharmony_ci float mantissa; 185bf215546Sopenharmony_ci int exponent; 186bf215546Sopenharmony_ci uint32_t float24 = 0; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci if (f == 0.0) 189bf215546Sopenharmony_ci return 0; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci u.fl = f; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci mantissa = frexpf(f, &exponent); 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci /* Handle -ve */ 196bf215546Sopenharmony_ci if (mantissa < 0) { 197bf215546Sopenharmony_ci float24 |= (1 << 23); 198bf215546Sopenharmony_ci mantissa = mantissa * -1.0; 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci /* Handle exponent, bias of 63 */ 201bf215546Sopenharmony_ci exponent += 62; 202bf215546Sopenharmony_ci float24 |= (exponent << 16); 203bf215546Sopenharmony_ci /* Kill 7 LSB of mantissa */ 204bf215546Sopenharmony_ci float24 |= (u.u & 0x7FFFFF) >> 7; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci return float24; 207bf215546Sopenharmony_ci} 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_civoid r300_emit_fs(struct r300_context* r300, unsigned size, void *state) 210bf215546Sopenharmony_ci{ 211bf215546Sopenharmony_ci struct r300_fragment_shader *fs = r300_fs(r300); 212bf215546Sopenharmony_ci CS_LOCALS(r300); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size); 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_civoid r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) 218bf215546Sopenharmony_ci{ 219bf215546Sopenharmony_ci struct r300_fragment_shader *fs = r300_fs(r300); 220bf215546Sopenharmony_ci struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; 221bf215546Sopenharmony_ci unsigned count = fs->shader->externals_count; 222bf215546Sopenharmony_ci unsigned i, j; 223bf215546Sopenharmony_ci CS_LOCALS(r300); 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci if (count == 0) 226bf215546Sopenharmony_ci return; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci BEGIN_CS(size); 229bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4); 230bf215546Sopenharmony_ci if (buf->remap_table){ 231bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 232bf215546Sopenharmony_ci float *data = (float*)&buf->ptr[buf->remap_table[i]*4]; 233bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 234bf215546Sopenharmony_ci OUT_CS(pack_float24(data[j])); 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci } else { 237bf215546Sopenharmony_ci for (i = 0; i < count; i++) 238bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 239bf215546Sopenharmony_ci OUT_CS(pack_float24(*(float*)&buf->ptr[i*4+j])); 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci END_CS; 243bf215546Sopenharmony_ci} 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_civoid r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) 246bf215546Sopenharmony_ci{ 247bf215546Sopenharmony_ci struct r300_fragment_shader *fs = r300_fs(r300); 248bf215546Sopenharmony_ci struct rc_constant_list *constants = &fs->shader->code.constants; 249bf215546Sopenharmony_ci unsigned i; 250bf215546Sopenharmony_ci unsigned count = fs->shader->rc_state_count; 251bf215546Sopenharmony_ci unsigned first = fs->shader->externals_count; 252bf215546Sopenharmony_ci unsigned end = constants->Count; 253bf215546Sopenharmony_ci unsigned j; 254bf215546Sopenharmony_ci CS_LOCALS(r300); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci if (count == 0) 257bf215546Sopenharmony_ci return; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci BEGIN_CS(size); 260bf215546Sopenharmony_ci for(i = first; i < end; ++i) { 261bf215546Sopenharmony_ci if (constants->Constants[i].Type == RC_CONSTANT_STATE) { 262bf215546Sopenharmony_ci float data[4]; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci get_rc_constant_state(data, r300, &constants->Constants[i]); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); 267bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 268bf215546Sopenharmony_ci OUT_CS(pack_float24(data[j])); 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci END_CS; 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_civoid r500_emit_fs(struct r300_context* r300, unsigned size, void *state) 275bf215546Sopenharmony_ci{ 276bf215546Sopenharmony_ci struct r300_fragment_shader *fs = r300_fs(r300); 277bf215546Sopenharmony_ci CS_LOCALS(r300); 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size); 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_civoid r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) 283bf215546Sopenharmony_ci{ 284bf215546Sopenharmony_ci struct r300_fragment_shader *fs = r300_fs(r300); 285bf215546Sopenharmony_ci struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; 286bf215546Sopenharmony_ci unsigned count = fs->shader->externals_count; 287bf215546Sopenharmony_ci CS_LOCALS(r300); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci if (count == 0) 290bf215546Sopenharmony_ci return; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci BEGIN_CS(size); 293bf215546Sopenharmony_ci OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); 294bf215546Sopenharmony_ci OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4); 295bf215546Sopenharmony_ci if (buf->remap_table){ 296bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 297bf215546Sopenharmony_ci uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; 298bf215546Sopenharmony_ci OUT_CS_TABLE(data, 4); 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci } else { 301bf215546Sopenharmony_ci OUT_CS_TABLE(buf->ptr, count * 4); 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci END_CS; 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_civoid r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) 307bf215546Sopenharmony_ci{ 308bf215546Sopenharmony_ci struct r300_fragment_shader *fs = r300_fs(r300); 309bf215546Sopenharmony_ci struct rc_constant_list *constants = &fs->shader->code.constants; 310bf215546Sopenharmony_ci unsigned i; 311bf215546Sopenharmony_ci unsigned count = fs->shader->rc_state_count; 312bf215546Sopenharmony_ci unsigned first = fs->shader->externals_count; 313bf215546Sopenharmony_ci unsigned end = constants->Count; 314bf215546Sopenharmony_ci CS_LOCALS(r300); 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci if (count == 0) 317bf215546Sopenharmony_ci return; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci BEGIN_CS(size); 320bf215546Sopenharmony_ci for(i = first; i < end; ++i) { 321bf215546Sopenharmony_ci if (constants->Constants[i].Type == RC_CONSTANT_STATE) { 322bf215546Sopenharmony_ci float data[4]; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci get_rc_constant_state(data, r300, &constants->Constants[i]); 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci OUT_CS_REG(R500_GA_US_VECTOR_INDEX, 327bf215546Sopenharmony_ci R500_GA_US_VECTOR_INDEX_TYPE_CONST | 328bf215546Sopenharmony_ci (i & R500_GA_US_VECTOR_INDEX_MASK)); 329bf215546Sopenharmony_ci OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4); 330bf215546Sopenharmony_ci OUT_CS_TABLE(data, 4); 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci END_CS; 334bf215546Sopenharmony_ci} 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_civoid r300_emit_gpu_flush(struct r300_context *r300, unsigned size, void *state) 337bf215546Sopenharmony_ci{ 338bf215546Sopenharmony_ci struct r300_gpu_flush *gpuflush = (struct r300_gpu_flush*)state; 339bf215546Sopenharmony_ci struct pipe_framebuffer_state* fb = 340bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 341bf215546Sopenharmony_ci uint32_t height = fb->height; 342bf215546Sopenharmony_ci uint32_t width = fb->width; 343bf215546Sopenharmony_ci CS_LOCALS(r300); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci if (r300->cbzb_clear) { 346bf215546Sopenharmony_ci struct r300_surface *surf = r300_surface(fb->cbufs[0]); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci height = surf->cbzb_height; 349bf215546Sopenharmony_ci width = surf->cbzb_width; 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci DBG(r300, DBG_SCISSOR, 353bf215546Sopenharmony_ci "r300: Scissor width: %i, height: %i, CBZB clear: %s\n", 354bf215546Sopenharmony_ci width, height, r300->cbzb_clear ? "YES" : "NO"); 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci BEGIN_CS(size); 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci /* Set up scissors. 359bf215546Sopenharmony_ci * By writing to the SC registers, SC & US assert idle. */ 360bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); 361bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 362bf215546Sopenharmony_ci OUT_CS(0); 363bf215546Sopenharmony_ci OUT_CS(((width - 1) << R300_SCISSORS_X_SHIFT) | 364bf215546Sopenharmony_ci ((height - 1) << R300_SCISSORS_Y_SHIFT)); 365bf215546Sopenharmony_ci } else { 366bf215546Sopenharmony_ci OUT_CS((1440 << R300_SCISSORS_X_SHIFT) | 367bf215546Sopenharmony_ci (1440 << R300_SCISSORS_Y_SHIFT)); 368bf215546Sopenharmony_ci OUT_CS(((width + 1440-1) << R300_SCISSORS_X_SHIFT) | 369bf215546Sopenharmony_ci ((height + 1440-1) << R300_SCISSORS_Y_SHIFT)); 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci /* Flush CB & ZB caches and wait until the 3D engine is idle and clean. */ 373bf215546Sopenharmony_ci OUT_CS_TABLE(gpuflush->cb_flush_clean, 6); 374bf215546Sopenharmony_ci END_CS; 375bf215546Sopenharmony_ci} 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_civoid r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) 378bf215546Sopenharmony_ci{ 379bf215546Sopenharmony_ci struct r300_aa_state *aa = (struct r300_aa_state*)state; 380bf215546Sopenharmony_ci CS_LOCALS(r300); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci BEGIN_CS(size); 383bf215546Sopenharmony_ci OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci if (aa->dest) { 386bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 3); 387bf215546Sopenharmony_ci OUT_CS(aa->dest->offset); 388bf215546Sopenharmony_ci OUT_CS(aa->dest->pitch & R300_RB3D_AARESOLVE_PITCH_MASK); 389bf215546Sopenharmony_ci OUT_CS(R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE | 390bf215546Sopenharmony_ci R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE); 391bf215546Sopenharmony_ci OUT_CS_RELOC(aa->dest); 392bf215546Sopenharmony_ci } else { 393bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0); 394bf215546Sopenharmony_ci } 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci END_CS; 397bf215546Sopenharmony_ci} 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_civoid r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) 400bf215546Sopenharmony_ci{ 401bf215546Sopenharmony_ci struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; 402bf215546Sopenharmony_ci struct r300_surface* surf; 403bf215546Sopenharmony_ci unsigned i; 404bf215546Sopenharmony_ci uint32_t rb3d_cctl = 0; 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci CS_LOCALS(r300); 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci BEGIN_CS(size); 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 411bf215546Sopenharmony_ci rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE; 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers. */ 414bf215546Sopenharmony_ci if (fb->nr_cbufs && r300->fb_multiwrite) { 415bf215546Sopenharmony_ci rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs); 416bf215546Sopenharmony_ci } 417bf215546Sopenharmony_ci if (r300->cmask_in_use) { 418bf215546Sopenharmony_ci rb3d_cctl |= R300_RB3D_CCTL_AA_COMPRESSION_ENABLE | 419bf215546Sopenharmony_ci R300_RB3D_CCTL_CMASK_ENABLE; 420bf215546Sopenharmony_ci } 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl); 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci /* Set up colorbuffers. */ 425bf215546Sopenharmony_ci for (i = 0; i < fb->nr_cbufs; i++) { 426bf215546Sopenharmony_ci surf = r300_surface(r300_get_nonnull_cb(fb, i)); 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset); 429bf215546Sopenharmony_ci OUT_CS_RELOC(surf); 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch); 432bf215546Sopenharmony_ci OUT_CS_RELOC(surf); 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci if (r300->cmask_in_use && i == 0) { 435bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_CMASK_OFFSET0, 0); 436bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_CMASK_PITCH0, surf->pitch_cmask); 437bf215546Sopenharmony_ci OUT_CS_REG(R300_RB3D_COLOR_CLEAR_VALUE, r300->color_clear_value); 438bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 439bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2); 440bf215546Sopenharmony_ci OUT_CS(r300->color_clear_value_ar); 441bf215546Sopenharmony_ci OUT_CS(r300->color_clear_value_gb); 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci /* Set up the ZB part of the CBZB clear. */ 447bf215546Sopenharmony_ci if (r300->cbzb_clear) { 448bf215546Sopenharmony_ci surf = r300_surface(fb->cbufs[0]); 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format); 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset); 453bf215546Sopenharmony_ci OUT_CS_RELOC(surf); 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch); 456bf215546Sopenharmony_ci OUT_CS_RELOC(surf); 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci DBG(r300, DBG_CBZB, 459bf215546Sopenharmony_ci "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format, 460bf215546Sopenharmony_ci surf->cbzb_pitch); 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci /* Set up a zbuffer. */ 463bf215546Sopenharmony_ci else if (fb->zsbuf) { 464bf215546Sopenharmony_ci surf = r300_surface(fb->zsbuf); 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_FORMAT, surf->format); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset); 469bf215546Sopenharmony_ci OUT_CS_RELOC(surf); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch); 472bf215546Sopenharmony_ci OUT_CS_RELOC(surf); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci if (r300->hyperz_enabled) { 475bf215546Sopenharmony_ci /* HiZ RAM. */ 476bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0); 477bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_HIZ_PITCH, surf->pitch_hiz); 478bf215546Sopenharmony_ci /* Z Mask RAM. (compressed zbuffer) */ 479bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); 480bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf->pitch_zmask); 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci } 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci END_CS; 485bf215546Sopenharmony_ci} 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_civoid r300_emit_hyperz_state(struct r300_context *r300, 488bf215546Sopenharmony_ci unsigned size, void *state) 489bf215546Sopenharmony_ci{ 490bf215546Sopenharmony_ci struct r300_hyperz_state *z = state; 491bf215546Sopenharmony_ci CS_LOCALS(r300); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci if (z->flush) 494bf215546Sopenharmony_ci WRITE_CS_TABLE(&z->cb_flush_begin, size); 495bf215546Sopenharmony_ci else 496bf215546Sopenharmony_ci WRITE_CS_TABLE(&z->cb_begin, size - 2); 497bf215546Sopenharmony_ci} 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_civoid r300_emit_hyperz_end(struct r300_context *r300) 500bf215546Sopenharmony_ci{ 501bf215546Sopenharmony_ci struct r300_hyperz_state z = 502bf215546Sopenharmony_ci *(struct r300_hyperz_state*)r300->hyperz_state.state; 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci z.flush = 1; 505bf215546Sopenharmony_ci z.zb_bw_cntl = 0; 506bf215546Sopenharmony_ci z.zb_depthclearvalue = 0; 507bf215546Sopenharmony_ci z.sc_hyperz = R300_SC_HYPERZ_ADJ_2; 508bf215546Sopenharmony_ci z.gb_z_peq_config = 0; 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci r300_emit_hyperz_state(r300, r300->hyperz_state.size, &z); 511bf215546Sopenharmony_ci} 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci#define R300_NIBBLES(x0, y0, x1, y1, x2, y2, d0y, d0x) \ 514bf215546Sopenharmony_ci (((x0) & 0xf) | (((y0) & 0xf) << 4) | \ 515bf215546Sopenharmony_ci (((x1) & 0xf) << 8) | (((y1) & 0xf) << 12) | \ 516bf215546Sopenharmony_ci (((x2) & 0xf) << 16) | (((y2) & 0xf) << 20) | \ 517bf215546Sopenharmony_ci (((d0y) & 0xf) << 24) | (((d0x) & 0xf) << 28)) 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_cistatic unsigned r300_get_mspos(int index, unsigned *p) 520bf215546Sopenharmony_ci{ 521bf215546Sopenharmony_ci unsigned reg, i, distx, disty, dist; 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci if (index == 0) { 524bf215546Sopenharmony_ci /* MSPOS0 contains positions for samples 0,1,2 as (X,Y) pairs of nibbles, 525bf215546Sopenharmony_ci * followed by a (Y,X) pair containing the minimum distance from the pixel 526bf215546Sopenharmony_ci * edge: 527bf215546Sopenharmony_ci * X0, Y0, X1, Y1, X2, Y2, D0_Y, D0_X 528bf215546Sopenharmony_ci * 529bf215546Sopenharmony_ci * There is a quirk when setting D0_X. The value represents the distance 530bf215546Sopenharmony_ci * from the left edge of the pixel quad to the first sample in subpixels. 531bf215546Sopenharmony_ci * All values less than eight should use the actual value, but „7‟ should 532bf215546Sopenharmony_ci * be used for the distance „8‟. The hardware will convert 7 into 8 internally. 533bf215546Sopenharmony_ci */ 534bf215546Sopenharmony_ci distx = 11; 535bf215546Sopenharmony_ci for (i = 0; i < 12; i += 2) { 536bf215546Sopenharmony_ci if (p[i] < distx) 537bf215546Sopenharmony_ci distx = p[i]; 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci disty = 11; 541bf215546Sopenharmony_ci for (i = 1; i < 12; i += 2) { 542bf215546Sopenharmony_ci if (p[i] < disty) 543bf215546Sopenharmony_ci disty = p[i]; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci if (distx == 8) 547bf215546Sopenharmony_ci distx = 7; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci reg = R300_NIBBLES(p[0], p[1], p[2], p[3], p[4], p[5], disty, distx); 550bf215546Sopenharmony_ci } else { 551bf215546Sopenharmony_ci /* MSPOS1 contains positions for samples 3,4,5 as (X,Y) pairs of nibbles, 552bf215546Sopenharmony_ci * followed by the minimum distance from the pixel edge (not sure if X or Y): 553bf215546Sopenharmony_ci * X3, Y3, X4, Y4, X5, Y5, D1 554bf215546Sopenharmony_ci */ 555bf215546Sopenharmony_ci dist = 11; 556bf215546Sopenharmony_ci for (i = 0; i < 12; i++) { 557bf215546Sopenharmony_ci if (p[i] < dist) 558bf215546Sopenharmony_ci dist = p[i]; 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci reg = R300_NIBBLES(p[6], p[7], p[8], p[9], p[10], p[11], dist, 0); 562bf215546Sopenharmony_ci } 563bf215546Sopenharmony_ci return reg; 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_civoid r300_emit_fb_state_pipelined(struct r300_context *r300, 567bf215546Sopenharmony_ci unsigned size, void *state) 568bf215546Sopenharmony_ci{ 569bf215546Sopenharmony_ci /* The sample coordinates are in the range [0,11], because 570bf215546Sopenharmony_ci * GB_TILE_CONFIG.SUBPIXEL is set to the 1/12 subpixel precision. 571bf215546Sopenharmony_ci * 572bf215546Sopenharmony_ci * Some sample coordinates reach to neighboring pixels and should not be used. 573bf215546Sopenharmony_ci * (e.g. Y=11) 574bf215546Sopenharmony_ci * 575bf215546Sopenharmony_ci * The unused samples must be set to the positions of other valid samples. */ 576bf215546Sopenharmony_ci static unsigned sample_locs_1x[12] = { 577bf215546Sopenharmony_ci 6,6, 6,6, 6,6, 6,6, 6,6, 6,6 578bf215546Sopenharmony_ci }; 579bf215546Sopenharmony_ci static unsigned sample_locs_2x[12] = { 580bf215546Sopenharmony_ci 3,9, 9,3, 9,3, 9,3, 9,3, 9,3 581bf215546Sopenharmony_ci }; 582bf215546Sopenharmony_ci static unsigned sample_locs_4x[12] = { 583bf215546Sopenharmony_ci 4,4, 8,8, 2,10, 10,2, 10,2, 10,2 584bf215546Sopenharmony_ci }; 585bf215546Sopenharmony_ci static unsigned sample_locs_6x[12] = { 586bf215546Sopenharmony_ci 3,1, 7,3, 11,5, 1,7, 5,9, 9,10 587bf215546Sopenharmony_ci }; 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ci struct pipe_framebuffer_state* fb = 590bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 591bf215546Sopenharmony_ci unsigned i, num_cbufs = fb->nr_cbufs; 592bf215546Sopenharmony_ci unsigned mspos0, mspos1; 593bf215546Sopenharmony_ci CS_LOCALS(r300); 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be 596bf215546Sopenharmony_ci * marked as UNUSED in the US block. */ 597bf215546Sopenharmony_ci if (r300->fb_multiwrite) { 598bf215546Sopenharmony_ci num_cbufs = MIN2(num_cbufs, 1); 599bf215546Sopenharmony_ci } 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci BEGIN_CS(size); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci /* Colorbuffer format in the US block. 604bf215546Sopenharmony_ci * (must be written after unpipelined regs) */ 605bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); 606bf215546Sopenharmony_ci for (i = 0; i < num_cbufs; i++) { 607bf215546Sopenharmony_ci OUT_CS(r300_surface(r300_get_nonnull_cb(fb, i))->format); 608bf215546Sopenharmony_ci } 609bf215546Sopenharmony_ci for (; i < 1; i++) { 610bf215546Sopenharmony_ci OUT_CS(R300_US_OUT_FMT_C4_8 | 611bf215546Sopenharmony_ci R300_C0_SEL_B | R300_C1_SEL_G | 612bf215546Sopenharmony_ci R300_C2_SEL_R | R300_C3_SEL_A); 613bf215546Sopenharmony_ci } 614bf215546Sopenharmony_ci for (; i < 4; i++) { 615bf215546Sopenharmony_ci OUT_CS(R300_US_OUT_FMT_UNUSED); 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci /* Set sample positions. It depends on the framebuffer sample count. 619bf215546Sopenharmony_ci * These are pipelined regs and as such cannot be moved to the AA state. 620bf215546Sopenharmony_ci */ 621bf215546Sopenharmony_ci switch (r300->num_samples) { 622bf215546Sopenharmony_ci default: 623bf215546Sopenharmony_ci mspos0 = r300_get_mspos(0, sample_locs_1x); 624bf215546Sopenharmony_ci mspos1 = r300_get_mspos(1, sample_locs_1x); 625bf215546Sopenharmony_ci break; 626bf215546Sopenharmony_ci case 2: 627bf215546Sopenharmony_ci mspos0 = r300_get_mspos(0, sample_locs_2x); 628bf215546Sopenharmony_ci mspos1 = r300_get_mspos(1, sample_locs_2x); 629bf215546Sopenharmony_ci break; 630bf215546Sopenharmony_ci case 4: 631bf215546Sopenharmony_ci mspos0 = r300_get_mspos(0, sample_locs_4x); 632bf215546Sopenharmony_ci mspos1 = r300_get_mspos(1, sample_locs_4x); 633bf215546Sopenharmony_ci break; 634bf215546Sopenharmony_ci case 6: 635bf215546Sopenharmony_ci mspos0 = r300_get_mspos(0, sample_locs_6x); 636bf215546Sopenharmony_ci mspos1 = r300_get_mspos(1, sample_locs_6x); 637bf215546Sopenharmony_ci break; 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2); 641bf215546Sopenharmony_ci OUT_CS(mspos0); 642bf215546Sopenharmony_ci OUT_CS(mspos1); 643bf215546Sopenharmony_ci END_CS; 644bf215546Sopenharmony_ci} 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_civoid r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) 647bf215546Sopenharmony_ci{ 648bf215546Sopenharmony_ci struct r300_query *query = r300->query_current; 649bf215546Sopenharmony_ci CS_LOCALS(r300); 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci if (!query) 652bf215546Sopenharmony_ci return; 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci BEGIN_CS(size); 655bf215546Sopenharmony_ci if (r300->screen->caps.family == CHIP_RV530) { 656bf215546Sopenharmony_ci OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); 657bf215546Sopenharmony_ci } else { 658bf215546Sopenharmony_ci OUT_CS_REG(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); 659bf215546Sopenharmony_ci } 660bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); 661bf215546Sopenharmony_ci END_CS; 662bf215546Sopenharmony_ci query->begin_emitted = TRUE; 663bf215546Sopenharmony_ci} 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_cistatic void r300_emit_query_end_frag_pipes(struct r300_context *r300, 666bf215546Sopenharmony_ci struct r300_query *query) 667bf215546Sopenharmony_ci{ 668bf215546Sopenharmony_ci struct r300_capabilities* caps = &r300->screen->caps; 669bf215546Sopenharmony_ci uint32_t gb_pipes = r300->screen->info.r300_num_gb_pipes; 670bf215546Sopenharmony_ci CS_LOCALS(r300); 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci assert(gb_pipes); 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci BEGIN_CS(6 * gb_pipes + 2); 675bf215546Sopenharmony_ci /* I'm not so sure I like this switch, but it's hard to be elegant 676bf215546Sopenharmony_ci * when there's so many special cases... 677bf215546Sopenharmony_ci * 678bf215546Sopenharmony_ci * So here's the basic idea. For each pipe, enable writes to it only, 679bf215546Sopenharmony_ci * then put out the relocation for ZPASS_ADDR, taking into account a 680bf215546Sopenharmony_ci * 4-byte offset for each pipe. RV380 and older are special; they have 681bf215546Sopenharmony_ci * only two pipes, and the second pipe's enable is on bit 3, not bit 1, 682bf215546Sopenharmony_ci * so there's a chipset cap for that. */ 683bf215546Sopenharmony_ci switch (gb_pipes) { 684bf215546Sopenharmony_ci case 4: 685bf215546Sopenharmony_ci /* pipe 3 only */ 686bf215546Sopenharmony_ci OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); 687bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 3) * 4); 688bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 689bf215546Sopenharmony_ci FALLTHROUGH; 690bf215546Sopenharmony_ci case 3: 691bf215546Sopenharmony_ci /* pipe 2 only */ 692bf215546Sopenharmony_ci OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); 693bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 2) * 4); 694bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 695bf215546Sopenharmony_ci FALLTHROUGH; 696bf215546Sopenharmony_ci case 2: 697bf215546Sopenharmony_ci /* pipe 1 only */ 698bf215546Sopenharmony_ci /* As mentioned above, accommodate RV380 and older. */ 699bf215546Sopenharmony_ci OUT_CS_REG(R300_SU_REG_DEST, 700bf215546Sopenharmony_ci 1 << (caps->high_second_pipe ? 3 : 1)); 701bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); 702bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 703bf215546Sopenharmony_ci FALLTHROUGH; 704bf215546Sopenharmony_ci case 1: 705bf215546Sopenharmony_ci /* pipe 0 only */ 706bf215546Sopenharmony_ci OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); 707bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); 708bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 709bf215546Sopenharmony_ci break; 710bf215546Sopenharmony_ci default: 711bf215546Sopenharmony_ci fprintf(stderr, "r300: Implementation error: Chipset reports %d" 712bf215546Sopenharmony_ci " pixel pipes!\n", gb_pipes); 713bf215546Sopenharmony_ci abort(); 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci /* And, finally, reset it to normal... */ 717bf215546Sopenharmony_ci OUT_CS_REG(R300_SU_REG_DEST, 0xF); 718bf215546Sopenharmony_ci END_CS; 719bf215546Sopenharmony_ci} 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_cistatic void rv530_emit_query_end_single_z(struct r300_context *r300, 722bf215546Sopenharmony_ci struct r300_query *query) 723bf215546Sopenharmony_ci{ 724bf215546Sopenharmony_ci CS_LOCALS(r300); 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci BEGIN_CS(8); 727bf215546Sopenharmony_ci OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); 728bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, query->num_results * 4); 729bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 730bf215546Sopenharmony_ci OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); 731bf215546Sopenharmony_ci END_CS; 732bf215546Sopenharmony_ci} 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_cistatic void rv530_emit_query_end_double_z(struct r300_context *r300, 735bf215546Sopenharmony_ci struct r300_query *query) 736bf215546Sopenharmony_ci{ 737bf215546Sopenharmony_ci CS_LOCALS(r300); 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci BEGIN_CS(14); 740bf215546Sopenharmony_ci OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); 741bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); 742bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 743bf215546Sopenharmony_ci OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); 744bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); 745bf215546Sopenharmony_ci OUT_CS_RELOC(r300->query_current); 746bf215546Sopenharmony_ci OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); 747bf215546Sopenharmony_ci END_CS; 748bf215546Sopenharmony_ci} 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_civoid r300_emit_query_end(struct r300_context* r300) 751bf215546Sopenharmony_ci{ 752bf215546Sopenharmony_ci struct r300_capabilities *caps = &r300->screen->caps; 753bf215546Sopenharmony_ci struct r300_query *query = r300->query_current; 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci if (!query) 756bf215546Sopenharmony_ci return; 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci if (query->begin_emitted == FALSE) 759bf215546Sopenharmony_ci return; 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci if (caps->family == CHIP_RV530) { 762bf215546Sopenharmony_ci if (r300->screen->info.r300_num_z_pipes == 2) 763bf215546Sopenharmony_ci rv530_emit_query_end_double_z(r300, query); 764bf215546Sopenharmony_ci else 765bf215546Sopenharmony_ci rv530_emit_query_end_single_z(r300, query); 766bf215546Sopenharmony_ci } else 767bf215546Sopenharmony_ci r300_emit_query_end_frag_pipes(r300, query); 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci query->begin_emitted = FALSE; 770bf215546Sopenharmony_ci query->num_results += query->num_pipes; 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci /* XXX grab all the results and reset the counter. */ 773bf215546Sopenharmony_ci if (query->num_results >= query->buf->size / 4 - 4) { 774bf215546Sopenharmony_ci query->num_results = (query->buf->size / 4) / 2; 775bf215546Sopenharmony_ci fprintf(stderr, "r300: Rewinding OQBO...\n"); 776bf215546Sopenharmony_ci } 777bf215546Sopenharmony_ci} 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_civoid r300_emit_invariant_state(struct r300_context *r300, 780bf215546Sopenharmony_ci unsigned size, void *state) 781bf215546Sopenharmony_ci{ 782bf215546Sopenharmony_ci CS_LOCALS(r300); 783bf215546Sopenharmony_ci WRITE_CS_TABLE(state, size); 784bf215546Sopenharmony_ci} 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_civoid r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) 787bf215546Sopenharmony_ci{ 788bf215546Sopenharmony_ci struct r300_rs_state* rs = state; 789bf215546Sopenharmony_ci CS_LOCALS(r300); 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci BEGIN_CS(size); 792bf215546Sopenharmony_ci OUT_CS_TABLE(rs->cb_main, RS_STATE_MAIN_SIZE); 793bf215546Sopenharmony_ci if (rs->polygon_offset_enable) { 794bf215546Sopenharmony_ci if (r300->zbuffer_bpp == 16) { 795bf215546Sopenharmony_ci OUT_CS_TABLE(rs->cb_poly_offset_zb16, 5); 796bf215546Sopenharmony_ci } else { 797bf215546Sopenharmony_ci OUT_CS_TABLE(rs->cb_poly_offset_zb24, 5); 798bf215546Sopenharmony_ci } 799bf215546Sopenharmony_ci } 800bf215546Sopenharmony_ci END_CS; 801bf215546Sopenharmony_ci} 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_civoid r300_emit_rs_block_state(struct r300_context* r300, 804bf215546Sopenharmony_ci unsigned size, void* state) 805bf215546Sopenharmony_ci{ 806bf215546Sopenharmony_ci struct r300_rs_block* rs = (struct r300_rs_block*)state; 807bf215546Sopenharmony_ci unsigned i; 808bf215546Sopenharmony_ci /* It's the same for both INST and IP tables */ 809bf215546Sopenharmony_ci unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1; 810bf215546Sopenharmony_ci CS_LOCALS(r300); 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci if (DBG_ON(r300, DBG_RS_BLOCK)) { 813bf215546Sopenharmony_ci r500_dump_rs_block(rs); 814bf215546Sopenharmony_ci 815bf215546Sopenharmony_ci fprintf(stderr, "r300: RS emit:\n"); 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci for (i = 0; i < count; i++) 818bf215546Sopenharmony_ci fprintf(stderr, " : ip %d: 0x%08x\n", i, rs->ip[i]); 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci for (i = 0; i < count; i++) 821bf215546Sopenharmony_ci fprintf(stderr, " : inst %d: 0x%08x\n", i, rs->inst[i]); 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci fprintf(stderr, " : count: 0x%08x inst_count: 0x%08x\n", 824bf215546Sopenharmony_ci rs->count, rs->inst_count); 825bf215546Sopenharmony_ci } 826bf215546Sopenharmony_ci 827bf215546Sopenharmony_ci BEGIN_CS(size); 828bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); 829bf215546Sopenharmony_ci OUT_CS(rs->vap_vtx_state_cntl); 830bf215546Sopenharmony_ci OUT_CS(rs->vap_vsm_vtx_assm); 831bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); 832bf215546Sopenharmony_ci OUT_CS(rs->vap_out_vtx_fmt[0]); 833bf215546Sopenharmony_ci OUT_CS(rs->vap_out_vtx_fmt[1]); 834bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_GB_ENABLE, 1); 835bf215546Sopenharmony_ci OUT_CS(rs->gb_enable); 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 838bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R500_RS_IP_0, count); 839bf215546Sopenharmony_ci } else { 840bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_RS_IP_0, count); 841bf215546Sopenharmony_ci } 842bf215546Sopenharmony_ci OUT_CS_TABLE(rs->ip, count); 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_RS_COUNT, 2); 845bf215546Sopenharmony_ci OUT_CS(rs->count); 846bf215546Sopenharmony_ci OUT_CS(rs->inst_count); 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 849bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R500_RS_INST_0, count); 850bf215546Sopenharmony_ci } else { 851bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_RS_INST_0, count); 852bf215546Sopenharmony_ci } 853bf215546Sopenharmony_ci OUT_CS_TABLE(rs->inst, count); 854bf215546Sopenharmony_ci END_CS; 855bf215546Sopenharmony_ci} 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_civoid r300_emit_sample_mask(struct r300_context *r300, 858bf215546Sopenharmony_ci unsigned size, void *state) 859bf215546Sopenharmony_ci{ 860bf215546Sopenharmony_ci unsigned mask = (*(unsigned*)state) & ((1 << 6)-1); 861bf215546Sopenharmony_ci CS_LOCALS(r300); 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci BEGIN_CS(size); 864bf215546Sopenharmony_ci OUT_CS_REG(R300_SC_SCREENDOOR, 865bf215546Sopenharmony_ci mask | (mask << 6) | (mask << 12) | (mask << 18)); 866bf215546Sopenharmony_ci END_CS; 867bf215546Sopenharmony_ci} 868bf215546Sopenharmony_ci 869bf215546Sopenharmony_civoid r300_emit_scissor_state(struct r300_context* r300, 870bf215546Sopenharmony_ci unsigned size, void* state) 871bf215546Sopenharmony_ci{ 872bf215546Sopenharmony_ci struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state; 873bf215546Sopenharmony_ci CS_LOCALS(r300); 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci BEGIN_CS(size); 876bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_SC_CLIPRECT_TL_0, 2); 877bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 878bf215546Sopenharmony_ci OUT_CS((scissor->minx << R300_CLIPRECT_X_SHIFT) | 879bf215546Sopenharmony_ci (scissor->miny << R300_CLIPRECT_Y_SHIFT)); 880bf215546Sopenharmony_ci OUT_CS(((scissor->maxx - 1) << R300_CLIPRECT_X_SHIFT) | 881bf215546Sopenharmony_ci ((scissor->maxy - 1) << R300_CLIPRECT_Y_SHIFT)); 882bf215546Sopenharmony_ci } else { 883bf215546Sopenharmony_ci OUT_CS(((scissor->minx + 1440) << R300_CLIPRECT_X_SHIFT) | 884bf215546Sopenharmony_ci ((scissor->miny + 1440) << R300_CLIPRECT_Y_SHIFT)); 885bf215546Sopenharmony_ci OUT_CS(((scissor->maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) | 886bf215546Sopenharmony_ci ((scissor->maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT)); 887bf215546Sopenharmony_ci } 888bf215546Sopenharmony_ci END_CS; 889bf215546Sopenharmony_ci} 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_civoid r300_emit_textures_state(struct r300_context *r300, 892bf215546Sopenharmony_ci unsigned size, void *state) 893bf215546Sopenharmony_ci{ 894bf215546Sopenharmony_ci struct r300_textures_state *allstate = (struct r300_textures_state*)state; 895bf215546Sopenharmony_ci struct r300_texture_sampler_state *texstate; 896bf215546Sopenharmony_ci struct r300_resource *tex; 897bf215546Sopenharmony_ci unsigned i; 898bf215546Sopenharmony_ci boolean has_us_format = r300->screen->caps.has_us_format; 899bf215546Sopenharmony_ci CS_LOCALS(r300); 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_ci BEGIN_CS(size); 902bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_ENABLE, allstate->tx_enable); 903bf215546Sopenharmony_ci 904bf215546Sopenharmony_ci for (i = 0; i < allstate->count; i++) { 905bf215546Sopenharmony_ci if ((1 << i) & allstate->tx_enable) { 906bf215546Sopenharmony_ci texstate = &allstate->regs[i]; 907bf215546Sopenharmony_ci tex = r300_resource(allstate->sampler_views[i]->base.texture); 908bf215546Sopenharmony_ci 909bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0); 910bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1); 911bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (i * 4), 912bf215546Sopenharmony_ci texstate->border_color); 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format.format0); 915bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1); 916bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2); 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_OFFSET_0 + (i * 4), texstate->format.tile_config); 919bf215546Sopenharmony_ci OUT_CS_RELOC(tex); 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci if (has_us_format) { 922bf215546Sopenharmony_ci OUT_CS_REG(R500_US_FORMAT0_0 + (i * 4), 923bf215546Sopenharmony_ci texstate->format.us_format0); 924bf215546Sopenharmony_ci } 925bf215546Sopenharmony_ci } 926bf215546Sopenharmony_ci } 927bf215546Sopenharmony_ci END_CS; 928bf215546Sopenharmony_ci} 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_civoid r300_emit_vertex_arrays(struct r300_context* r300, int offset, 931bf215546Sopenharmony_ci boolean indexed, int instance_id) 932bf215546Sopenharmony_ci{ 933bf215546Sopenharmony_ci struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; 934bf215546Sopenharmony_ci struct pipe_vertex_element *velem = r300->velems->velem; 935bf215546Sopenharmony_ci struct r300_resource *buf; 936bf215546Sopenharmony_ci int i; 937bf215546Sopenharmony_ci unsigned vertex_array_count = r300->velems->count; 938bf215546Sopenharmony_ci unsigned packet_size = (vertex_array_count * 3 + 1) / 2; 939bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb1, *vb2; 940bf215546Sopenharmony_ci unsigned *hw_format_size = r300->velems->format_size; 941bf215546Sopenharmony_ci unsigned size1, size2, offset1, offset2, stride1, stride2; 942bf215546Sopenharmony_ci CS_LOCALS(r300); 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci BEGIN_CS(2 + packet_size + vertex_array_count * 2); 945bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); 946bf215546Sopenharmony_ci OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_ci if (instance_id == -1) { 949bf215546Sopenharmony_ci /* Non-instanced arrays. This ignores instance_divisor and instance_id. */ 950bf215546Sopenharmony_ci for (i = 0; i < vertex_array_count - 1; i += 2) { 951bf215546Sopenharmony_ci vb1 = &vbuf[velem[i].vertex_buffer_index]; 952bf215546Sopenharmony_ci vb2 = &vbuf[velem[i+1].vertex_buffer_index]; 953bf215546Sopenharmony_ci size1 = hw_format_size[i]; 954bf215546Sopenharmony_ci size2 = hw_format_size[i+1]; 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | 957bf215546Sopenharmony_ci R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); 958bf215546Sopenharmony_ci OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); 959bf215546Sopenharmony_ci OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); 960bf215546Sopenharmony_ci } 961bf215546Sopenharmony_ci 962bf215546Sopenharmony_ci if (vertex_array_count & 1) { 963bf215546Sopenharmony_ci vb1 = &vbuf[velem[i].vertex_buffer_index]; 964bf215546Sopenharmony_ci size1 = hw_format_size[i]; 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_ci OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); 967bf215546Sopenharmony_ci OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); 968bf215546Sopenharmony_ci } 969bf215546Sopenharmony_ci 970bf215546Sopenharmony_ci for (i = 0; i < vertex_array_count; i++) { 971bf215546Sopenharmony_ci buf = r300_resource(vbuf[velem[i].vertex_buffer_index].buffer.resource); 972bf215546Sopenharmony_ci OUT_CS_RELOC(buf); 973bf215546Sopenharmony_ci } 974bf215546Sopenharmony_ci } else { 975bf215546Sopenharmony_ci /* Instanced arrays. */ 976bf215546Sopenharmony_ci for (i = 0; i < vertex_array_count - 1; i += 2) { 977bf215546Sopenharmony_ci vb1 = &vbuf[velem[i].vertex_buffer_index]; 978bf215546Sopenharmony_ci vb2 = &vbuf[velem[i+1].vertex_buffer_index]; 979bf215546Sopenharmony_ci size1 = hw_format_size[i]; 980bf215546Sopenharmony_ci size2 = hw_format_size[i+1]; 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci if (velem[i].instance_divisor) { 983bf215546Sopenharmony_ci stride1 = 0; 984bf215546Sopenharmony_ci offset1 = vb1->buffer_offset + velem[i].src_offset + 985bf215546Sopenharmony_ci (instance_id / velem[i].instance_divisor) * vb1->stride; 986bf215546Sopenharmony_ci } else { 987bf215546Sopenharmony_ci stride1 = vb1->stride; 988bf215546Sopenharmony_ci offset1 = vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride; 989bf215546Sopenharmony_ci } 990bf215546Sopenharmony_ci if (velem[i+1].instance_divisor) { 991bf215546Sopenharmony_ci stride2 = 0; 992bf215546Sopenharmony_ci offset2 = vb2->buffer_offset + velem[i+1].src_offset + 993bf215546Sopenharmony_ci (instance_id / velem[i+1].instance_divisor) * vb2->stride; 994bf215546Sopenharmony_ci } else { 995bf215546Sopenharmony_ci stride2 = vb2->stride; 996bf215546Sopenharmony_ci offset2 = vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride; 997bf215546Sopenharmony_ci } 998bf215546Sopenharmony_ci 999bf215546Sopenharmony_ci OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(stride1) | 1000bf215546Sopenharmony_ci R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(stride2)); 1001bf215546Sopenharmony_ci OUT_CS(offset1); 1002bf215546Sopenharmony_ci OUT_CS(offset2); 1003bf215546Sopenharmony_ci } 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_ci if (vertex_array_count & 1) { 1006bf215546Sopenharmony_ci vb1 = &vbuf[velem[i].vertex_buffer_index]; 1007bf215546Sopenharmony_ci size1 = hw_format_size[i]; 1008bf215546Sopenharmony_ci 1009bf215546Sopenharmony_ci if (velem[i].instance_divisor) { 1010bf215546Sopenharmony_ci stride1 = 0; 1011bf215546Sopenharmony_ci offset1 = vb1->buffer_offset + velem[i].src_offset + 1012bf215546Sopenharmony_ci (instance_id / velem[i].instance_divisor) * vb1->stride; 1013bf215546Sopenharmony_ci } else { 1014bf215546Sopenharmony_ci stride1 = vb1->stride; 1015bf215546Sopenharmony_ci offset1 = vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride; 1016bf215546Sopenharmony_ci } 1017bf215546Sopenharmony_ci 1018bf215546Sopenharmony_ci OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(stride1)); 1019bf215546Sopenharmony_ci OUT_CS(offset1); 1020bf215546Sopenharmony_ci } 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_ci for (i = 0; i < vertex_array_count; i++) { 1023bf215546Sopenharmony_ci buf = r300_resource(vbuf[velem[i].vertex_buffer_index].buffer.resource); 1024bf215546Sopenharmony_ci OUT_CS_RELOC(buf); 1025bf215546Sopenharmony_ci } 1026bf215546Sopenharmony_ci } 1027bf215546Sopenharmony_ci END_CS; 1028bf215546Sopenharmony_ci} 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_civoid r300_emit_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed) 1031bf215546Sopenharmony_ci{ 1032bf215546Sopenharmony_ci CS_LOCALS(r300); 1033bf215546Sopenharmony_ci 1034bf215546Sopenharmony_ci DBG(r300, DBG_SWTCL, "r300: Preparing vertex buffer %p for render, " 1035bf215546Sopenharmony_ci "vertex size %d\n", r300->vbo, 1036bf215546Sopenharmony_ci r300->vertex_info.size); 1037bf215546Sopenharmony_ci /* Set the pointer to our vertex buffer. The emitted values are this: 1038bf215546Sopenharmony_ci * PACKET3 [3D_LOAD_VBPNTR] 1039bf215546Sopenharmony_ci * COUNT [1] 1040bf215546Sopenharmony_ci * FORMAT [size | stride << 8] 1041bf215546Sopenharmony_ci * OFFSET [offset into BO] 1042bf215546Sopenharmony_ci * VBPNTR [relocated BO] 1043bf215546Sopenharmony_ci */ 1044bf215546Sopenharmony_ci BEGIN_CS(7); 1045bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); 1046bf215546Sopenharmony_ci OUT_CS(1 | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); 1047bf215546Sopenharmony_ci OUT_CS(r300->vertex_info.size | 1048bf215546Sopenharmony_ci (r300->vertex_info.size << 8)); 1049bf215546Sopenharmony_ci OUT_CS(r300->draw_vbo_offset); 1050bf215546Sopenharmony_ci OUT_CS(0); 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci assert(r300->vbo); 1053bf215546Sopenharmony_ci OUT_CS(0xc0001000); /* PKT3_NOP */ 1054bf215546Sopenharmony_ci OUT_CS(r300->rws->cs_lookup_buffer(&r300->cs, r300->vbo) * 4); 1055bf215546Sopenharmony_ci END_CS; 1056bf215546Sopenharmony_ci} 1057bf215546Sopenharmony_ci 1058bf215546Sopenharmony_civoid r300_emit_vertex_stream_state(struct r300_context* r300, 1059bf215546Sopenharmony_ci unsigned size, void* state) 1060bf215546Sopenharmony_ci{ 1061bf215546Sopenharmony_ci struct r300_vertex_stream_state *streams = 1062bf215546Sopenharmony_ci (struct r300_vertex_stream_state*)state; 1063bf215546Sopenharmony_ci unsigned i; 1064bf215546Sopenharmony_ci CS_LOCALS(r300); 1065bf215546Sopenharmony_ci 1066bf215546Sopenharmony_ci if (DBG_ON(r300, DBG_PSC)) { 1067bf215546Sopenharmony_ci fprintf(stderr, "r300: PSC emit:\n"); 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci for (i = 0; i < streams->count; i++) { 1070bf215546Sopenharmony_ci fprintf(stderr, " : prog_stream_cntl%d: 0x%08x\n", i, 1071bf215546Sopenharmony_ci streams->vap_prog_stream_cntl[i]); 1072bf215546Sopenharmony_ci } 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci for (i = 0; i < streams->count; i++) { 1075bf215546Sopenharmony_ci fprintf(stderr, " : prog_stream_cntl_ext%d: 0x%08x\n", i, 1076bf215546Sopenharmony_ci streams->vap_prog_stream_cntl_ext[i]); 1077bf215546Sopenharmony_ci } 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci BEGIN_CS(size); 1081bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, streams->count); 1082bf215546Sopenharmony_ci OUT_CS_TABLE(streams->vap_prog_stream_cntl, streams->count); 1083bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, streams->count); 1084bf215546Sopenharmony_ci OUT_CS_TABLE(streams->vap_prog_stream_cntl_ext, streams->count); 1085bf215546Sopenharmony_ci END_CS; 1086bf215546Sopenharmony_ci} 1087bf215546Sopenharmony_ci 1088bf215546Sopenharmony_civoid r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state) 1089bf215546Sopenharmony_ci{ 1090bf215546Sopenharmony_ci CS_LOCALS(r300); 1091bf215546Sopenharmony_ci 1092bf215546Sopenharmony_ci BEGIN_CS(size); 1093bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); 1094bf215546Sopenharmony_ci END_CS; 1095bf215546Sopenharmony_ci} 1096bf215546Sopenharmony_ci 1097bf215546Sopenharmony_civoid r300_emit_vap_invariant_state(struct r300_context *r300, 1098bf215546Sopenharmony_ci unsigned size, void *state) 1099bf215546Sopenharmony_ci{ 1100bf215546Sopenharmony_ci CS_LOCALS(r300); 1101bf215546Sopenharmony_ci WRITE_CS_TABLE(state, size); 1102bf215546Sopenharmony_ci} 1103bf215546Sopenharmony_ci 1104bf215546Sopenharmony_civoid r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) 1105bf215546Sopenharmony_ci{ 1106bf215546Sopenharmony_ci struct r300_vertex_shader_code* vs = ((struct r300_vertex_shader*)state)->shader; 1107bf215546Sopenharmony_ci struct r300_vertex_program_code* code = &vs->code; 1108bf215546Sopenharmony_ci struct r300_screen* r300screen = r300->screen; 1109bf215546Sopenharmony_ci unsigned instruction_count = code->length / 4; 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_ci unsigned vtx_mem_size = r300screen->caps.is_r500 ? 128 : 72; 1112bf215546Sopenharmony_ci unsigned input_count = MAX2(util_bitcount(code->InputsRead), 1); 1113bf215546Sopenharmony_ci unsigned output_count = MAX2(util_bitcount(code->OutputsWritten), 1); 1114bf215546Sopenharmony_ci unsigned temp_count = MAX2(code->num_temporaries, 1); 1115bf215546Sopenharmony_ci 1116bf215546Sopenharmony_ci unsigned pvs_num_slots = MIN3(vtx_mem_size / input_count, 1117bf215546Sopenharmony_ci vtx_mem_size / output_count, 10); 1118bf215546Sopenharmony_ci unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 5); 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci CS_LOCALS(r300); 1121bf215546Sopenharmony_ci 1122bf215546Sopenharmony_ci BEGIN_CS(size); 1123bf215546Sopenharmony_ci 1124bf215546Sopenharmony_ci /* R300_VAP_PVS_CODE_CNTL_0 1125bf215546Sopenharmony_ci * R300_VAP_PVS_CONST_CNTL 1126bf215546Sopenharmony_ci * R300_VAP_PVS_CODE_CNTL_1 1127bf215546Sopenharmony_ci * See the r5xx docs for instructions on how to use these. */ 1128bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_0, R300_PVS_FIRST_INST(0) | 1129bf215546Sopenharmony_ci R300_PVS_XYZW_VALID_INST(code->last_pos_write) | 1130bf215546Sopenharmony_ci R300_PVS_LAST_INST(instruction_count - 1)); 1131bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_1, code->last_input_read); 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); 1134bf215546Sopenharmony_ci OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length); 1135bf215546Sopenharmony_ci OUT_CS_TABLE(code->body.d, code->length); 1136bf215546Sopenharmony_ci 1137bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) | 1138bf215546Sopenharmony_ci R300_PVS_NUM_CNTLRS(pvs_num_controllers) | 1139bf215546Sopenharmony_ci R300_PVS_NUM_FPUS(r300screen->caps.num_vert_fpus) | 1140bf215546Sopenharmony_ci R300_PVS_VF_MAX_VTX_NUM(12) | 1141bf215546Sopenharmony_ci (r300->clip_halfz ? R300_DX_CLIP_SPACE_DEF : 0) | 1142bf215546Sopenharmony_ci (r300screen->caps.is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0)); 1143bf215546Sopenharmony_ci 1144bf215546Sopenharmony_ci /* Emit flow control instructions. Even if there are no fc instructions, 1145bf215546Sopenharmony_ci * we still need to write the registers to make sure they are cleared. */ 1146bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_FLOW_CNTL_OPC, code->fc_ops); 1147bf215546Sopenharmony_ci if (r300screen->caps.is_r500) { 1148bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R500_VAP_PVS_FLOW_CNTL_ADDRS_LW_0, R300_VS_MAX_FC_OPS * 2); 1149bf215546Sopenharmony_ci OUT_CS_TABLE(code->fc_op_addrs.r500, R300_VS_MAX_FC_OPS * 2); 1150bf215546Sopenharmony_ci } else { 1151bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_ADDRS_0, R300_VS_MAX_FC_OPS); 1152bf215546Sopenharmony_ci OUT_CS_TABLE(code->fc_op_addrs.r300, R300_VS_MAX_FC_OPS); 1153bf215546Sopenharmony_ci } 1154bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_LOOP_INDEX_0, R300_VS_MAX_FC_OPS); 1155bf215546Sopenharmony_ci OUT_CS_TABLE(code->fc_loop_index, R300_VS_MAX_FC_OPS); 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci END_CS; 1158bf215546Sopenharmony_ci} 1159bf215546Sopenharmony_ci 1160bf215546Sopenharmony_civoid r300_emit_vs_constants(struct r300_context* r300, 1161bf215546Sopenharmony_ci unsigned size, void *state) 1162bf215546Sopenharmony_ci{ 1163bf215546Sopenharmony_ci unsigned count = r300_vs(r300)->shader->externals_count; 1164bf215546Sopenharmony_ci struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; 1165bf215546Sopenharmony_ci struct r300_vertex_shader_code *vs = r300_vs(r300)->shader; 1166bf215546Sopenharmony_ci unsigned i; 1167bf215546Sopenharmony_ci int imm_first = vs->externals_count; 1168bf215546Sopenharmony_ci int imm_end = vs->code.constants.Count; 1169bf215546Sopenharmony_ci int imm_count = vs->immediates_count; 1170bf215546Sopenharmony_ci CS_LOCALS(r300); 1171bf215546Sopenharmony_ci 1172bf215546Sopenharmony_ci BEGIN_CS(size); 1173bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_CONST_CNTL, 1174bf215546Sopenharmony_ci R300_PVS_CONST_BASE_OFFSET(buf->buffer_base) | 1175bf215546Sopenharmony_ci R300_PVS_MAX_CONST_ADDR(MAX2(imm_end - 1, 0))); 1176bf215546Sopenharmony_ci if (vs->externals_count) { 1177bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 1178bf215546Sopenharmony_ci (r300->screen->caps.is_r500 ? 1179bf215546Sopenharmony_ci R500_PVS_CONST_START : R300_PVS_CONST_START) + buf->buffer_base); 1180bf215546Sopenharmony_ci OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4); 1181bf215546Sopenharmony_ci if (buf->remap_table){ 1182bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 1183bf215546Sopenharmony_ci uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; 1184bf215546Sopenharmony_ci OUT_CS_TABLE(data, 4); 1185bf215546Sopenharmony_ci } 1186bf215546Sopenharmony_ci } else { 1187bf215546Sopenharmony_ci OUT_CS_TABLE(buf->ptr, count * 4); 1188bf215546Sopenharmony_ci } 1189bf215546Sopenharmony_ci } 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_ci /* Emit immediates. */ 1192bf215546Sopenharmony_ci if (imm_count) { 1193bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 1194bf215546Sopenharmony_ci (r300->screen->caps.is_r500 ? 1195bf215546Sopenharmony_ci R500_PVS_CONST_START : R300_PVS_CONST_START) + 1196bf215546Sopenharmony_ci buf->buffer_base + imm_first); 1197bf215546Sopenharmony_ci OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, imm_count * 4); 1198bf215546Sopenharmony_ci for (i = imm_first; i < imm_end; i++) { 1199bf215546Sopenharmony_ci const float *data = vs->code.constants.Constants[i].u.Immediate; 1200bf215546Sopenharmony_ci OUT_CS_TABLE(data, 4); 1201bf215546Sopenharmony_ci } 1202bf215546Sopenharmony_ci } 1203bf215546Sopenharmony_ci END_CS; 1204bf215546Sopenharmony_ci} 1205bf215546Sopenharmony_ci 1206bf215546Sopenharmony_civoid r300_emit_viewport_state(struct r300_context* r300, 1207bf215546Sopenharmony_ci unsigned size, void* state) 1208bf215546Sopenharmony_ci{ 1209bf215546Sopenharmony_ci struct r300_viewport_state* viewport = (struct r300_viewport_state*)state; 1210bf215546Sopenharmony_ci CS_LOCALS(r300); 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci BEGIN_CS(size); 1213bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); 1214bf215546Sopenharmony_ci OUT_CS_TABLE(&viewport->xscale, 6); 1215bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); 1216bf215546Sopenharmony_ci END_CS; 1217bf215546Sopenharmony_ci} 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_civoid r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) 1220bf215546Sopenharmony_ci{ 1221bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = 1222bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 1223bf215546Sopenharmony_ci struct r300_resource* tex; 1224bf215546Sopenharmony_ci CS_LOCALS(r300); 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci tex = r300_resource(fb->zsbuf->texture); 1227bf215546Sopenharmony_ci 1228bf215546Sopenharmony_ci BEGIN_CS(size); 1229bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_HIZ, 2); 1230bf215546Sopenharmony_ci OUT_CS(0); 1231bf215546Sopenharmony_ci OUT_CS(tex->tex.hiz_dwords[fb->zsbuf->u.tex.level]); 1232bf215546Sopenharmony_ci OUT_CS(r300->hiz_clear_value); 1233bf215546Sopenharmony_ci END_CS; 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_ci /* Mark the current zbuffer's hiz ram as in use. */ 1236bf215546Sopenharmony_ci r300->hiz_in_use = TRUE; 1237bf215546Sopenharmony_ci r300->hiz_func = HIZ_FUNC_NONE; 1238bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->hyperz_state); 1239bf215546Sopenharmony_ci} 1240bf215546Sopenharmony_ci 1241bf215546Sopenharmony_civoid r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state) 1242bf215546Sopenharmony_ci{ 1243bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = 1244bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 1245bf215546Sopenharmony_ci struct r300_resource *tex; 1246bf215546Sopenharmony_ci CS_LOCALS(r300); 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci tex = r300_resource(fb->zsbuf->texture); 1249bf215546Sopenharmony_ci 1250bf215546Sopenharmony_ci BEGIN_CS(size); 1251bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2); 1252bf215546Sopenharmony_ci OUT_CS(0); 1253bf215546Sopenharmony_ci OUT_CS(tex->tex.zmask_dwords[fb->zsbuf->u.tex.level]); 1254bf215546Sopenharmony_ci OUT_CS(0); 1255bf215546Sopenharmony_ci END_CS; 1256bf215546Sopenharmony_ci 1257bf215546Sopenharmony_ci /* Mark the current zbuffer's zmask as in use. */ 1258bf215546Sopenharmony_ci r300->zmask_in_use = TRUE; 1259bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->hyperz_state); 1260bf215546Sopenharmony_ci} 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_civoid r300_emit_cmask_clear(struct r300_context *r300, unsigned size, void *state) 1263bf215546Sopenharmony_ci{ 1264bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = 1265bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 1266bf215546Sopenharmony_ci struct r300_resource *tex; 1267bf215546Sopenharmony_ci CS_LOCALS(r300); 1268bf215546Sopenharmony_ci 1269bf215546Sopenharmony_ci tex = r300_resource(fb->cbufs[0]->texture); 1270bf215546Sopenharmony_ci 1271bf215546Sopenharmony_ci BEGIN_CS(size); 1272bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_CMASK, 2); 1273bf215546Sopenharmony_ci OUT_CS(0); 1274bf215546Sopenharmony_ci OUT_CS(tex->tex.cmask_dwords); 1275bf215546Sopenharmony_ci OUT_CS(0); 1276bf215546Sopenharmony_ci END_CS; 1277bf215546Sopenharmony_ci 1278bf215546Sopenharmony_ci /* Mark the current zbuffer's zmask as in use. */ 1279bf215546Sopenharmony_ci r300->cmask_in_use = TRUE; 1280bf215546Sopenharmony_ci r300_mark_fb_state_dirty(r300, R300_CHANGED_CMASK_ENABLE); 1281bf215546Sopenharmony_ci} 1282bf215546Sopenharmony_ci 1283bf215546Sopenharmony_civoid r300_emit_ztop_state(struct r300_context* r300, 1284bf215546Sopenharmony_ci unsigned size, void* state) 1285bf215546Sopenharmony_ci{ 1286bf215546Sopenharmony_ci struct r300_ztop_state* ztop = (struct r300_ztop_state*)state; 1287bf215546Sopenharmony_ci CS_LOCALS(r300); 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci BEGIN_CS(size); 1290bf215546Sopenharmony_ci OUT_CS_REG(R300_ZB_ZTOP, ztop->z_buffer_top); 1291bf215546Sopenharmony_ci END_CS; 1292bf215546Sopenharmony_ci} 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_civoid r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, void* state) 1295bf215546Sopenharmony_ci{ 1296bf215546Sopenharmony_ci CS_LOCALS(r300); 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci BEGIN_CS(size); 1299bf215546Sopenharmony_ci OUT_CS_REG(R300_TX_INVALTAGS, 0); 1300bf215546Sopenharmony_ci END_CS; 1301bf215546Sopenharmony_ci} 1302bf215546Sopenharmony_ci 1303bf215546Sopenharmony_ciboolean r300_emit_buffer_validate(struct r300_context *r300, 1304bf215546Sopenharmony_ci boolean do_validate_vertex_buffers, 1305bf215546Sopenharmony_ci struct pipe_resource *index_buffer) 1306bf215546Sopenharmony_ci{ 1307bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = 1308bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 1309bf215546Sopenharmony_ci struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; 1310bf215546Sopenharmony_ci struct r300_textures_state *texstate = 1311bf215546Sopenharmony_ci (struct r300_textures_state*)r300->textures_state.state; 1312bf215546Sopenharmony_ci struct r300_resource *tex; 1313bf215546Sopenharmony_ci unsigned i; 1314bf215546Sopenharmony_ci boolean flushed = FALSE; 1315bf215546Sopenharmony_ci 1316bf215546Sopenharmony_civalidate: 1317bf215546Sopenharmony_ci if (r300->fb_state.dirty) { 1318bf215546Sopenharmony_ci /* Color buffers... */ 1319bf215546Sopenharmony_ci for (i = 0; i < fb->nr_cbufs; i++) { 1320bf215546Sopenharmony_ci if (!fb->cbufs[i]) 1321bf215546Sopenharmony_ci continue; 1322bf215546Sopenharmony_ci tex = r300_resource(fb->cbufs[i]->texture); 1323bf215546Sopenharmony_ci assert(tex && tex->buf && "cbuf is marked, but NULL!"); 1324bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, tex->buf, 1325bf215546Sopenharmony_ci RADEON_USAGE_READWRITE | RADEON_USAGE_SYNCHRONIZED | 1326bf215546Sopenharmony_ci (tex->b.nr_samples > 1 ? 1327bf215546Sopenharmony_ci RADEON_PRIO_COLOR_BUFFER_MSAA : 1328bf215546Sopenharmony_ci RADEON_PRIO_COLOR_BUFFER), 1329bf215546Sopenharmony_ci r300_surface(fb->cbufs[i])->domain); 1330bf215546Sopenharmony_ci } 1331bf215546Sopenharmony_ci /* ...depth buffer... */ 1332bf215546Sopenharmony_ci if (fb->zsbuf) { 1333bf215546Sopenharmony_ci tex = r300_resource(fb->zsbuf->texture); 1334bf215546Sopenharmony_ci assert(tex && tex->buf && "zsbuf is marked, but NULL!"); 1335bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, tex->buf, 1336bf215546Sopenharmony_ci RADEON_USAGE_READWRITE | RADEON_USAGE_SYNCHRONIZED | 1337bf215546Sopenharmony_ci (tex->b.nr_samples > 1 ? 1338bf215546Sopenharmony_ci RADEON_PRIO_DEPTH_BUFFER_MSAA : 1339bf215546Sopenharmony_ci RADEON_PRIO_DEPTH_BUFFER), 1340bf215546Sopenharmony_ci r300_surface(fb->zsbuf)->domain); 1341bf215546Sopenharmony_ci } 1342bf215546Sopenharmony_ci } 1343bf215546Sopenharmony_ci /* The AA resolve buffer. */ 1344bf215546Sopenharmony_ci if (r300->aa_state.dirty) { 1345bf215546Sopenharmony_ci if (aa->dest) { 1346bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, aa->dest->buf, 1347bf215546Sopenharmony_ci RADEON_USAGE_WRITE | RADEON_USAGE_SYNCHRONIZED | 1348bf215546Sopenharmony_ci RADEON_PRIO_COLOR_BUFFER, 1349bf215546Sopenharmony_ci aa->dest->domain); 1350bf215546Sopenharmony_ci } 1351bf215546Sopenharmony_ci } 1352bf215546Sopenharmony_ci if (r300->textures_state.dirty) { 1353bf215546Sopenharmony_ci /* ...textures... */ 1354bf215546Sopenharmony_ci for (i = 0; i < texstate->count; i++) { 1355bf215546Sopenharmony_ci if (!(texstate->tx_enable & (1U << i))) { 1356bf215546Sopenharmony_ci continue; 1357bf215546Sopenharmony_ci } 1358bf215546Sopenharmony_ci 1359bf215546Sopenharmony_ci tex = r300_resource(texstate->sampler_views[i]->base.texture); 1360bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, tex->buf, 1361bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED | 1362bf215546Sopenharmony_ci RADEON_PRIO_SAMPLER_TEXTURE, 1363bf215546Sopenharmony_ci tex->domain); 1364bf215546Sopenharmony_ci } 1365bf215546Sopenharmony_ci } 1366bf215546Sopenharmony_ci /* ...occlusion query buffer... */ 1367bf215546Sopenharmony_ci if (r300->query_current) 1368bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, r300->query_current->buf, 1369bf215546Sopenharmony_ci RADEON_USAGE_WRITE | RADEON_USAGE_SYNCHRONIZED | 1370bf215546Sopenharmony_ci RADEON_PRIO_QUERY, 1371bf215546Sopenharmony_ci RADEON_DOMAIN_GTT); 1372bf215546Sopenharmony_ci /* ...vertex buffer for SWTCL path... */ 1373bf215546Sopenharmony_ci if (r300->vbo) 1374bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, r300->vbo, 1375bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED | 1376bf215546Sopenharmony_ci RADEON_PRIO_VERTEX_BUFFER, 1377bf215546Sopenharmony_ci RADEON_DOMAIN_GTT); 1378bf215546Sopenharmony_ci /* ...vertex buffers for HWTCL path... */ 1379bf215546Sopenharmony_ci if (do_validate_vertex_buffers && r300->vertex_arrays_dirty) { 1380bf215546Sopenharmony_ci struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; 1381bf215546Sopenharmony_ci struct pipe_vertex_buffer *last = r300->vertex_buffer + 1382bf215546Sopenharmony_ci r300->nr_vertex_buffers; 1383bf215546Sopenharmony_ci struct pipe_resource *buf; 1384bf215546Sopenharmony_ci 1385bf215546Sopenharmony_ci for (; vbuf != last; vbuf++) { 1386bf215546Sopenharmony_ci buf = vbuf->buffer.resource; 1387bf215546Sopenharmony_ci if (!buf) 1388bf215546Sopenharmony_ci continue; 1389bf215546Sopenharmony_ci 1390bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, r300_resource(buf)->buf, 1391bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED | 1392bf215546Sopenharmony_ci RADEON_PRIO_SAMPLER_BUFFER, 1393bf215546Sopenharmony_ci r300_resource(buf)->domain); 1394bf215546Sopenharmony_ci } 1395bf215546Sopenharmony_ci } 1396bf215546Sopenharmony_ci /* ...and index buffer for HWTCL path. */ 1397bf215546Sopenharmony_ci if (index_buffer) 1398bf215546Sopenharmony_ci r300->rws->cs_add_buffer(&r300->cs, r300_resource(index_buffer)->buf, 1399bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED | 1400bf215546Sopenharmony_ci RADEON_PRIO_INDEX_BUFFER, 1401bf215546Sopenharmony_ci r300_resource(index_buffer)->domain); 1402bf215546Sopenharmony_ci 1403bf215546Sopenharmony_ci /* Now do the validation (flush is called inside cs_validate on failure). */ 1404bf215546Sopenharmony_ci if (!r300->rws->cs_validate(&r300->cs)) { 1405bf215546Sopenharmony_ci /* Ooops, an infinite loop, give up. */ 1406bf215546Sopenharmony_ci if (flushed) 1407bf215546Sopenharmony_ci return FALSE; 1408bf215546Sopenharmony_ci 1409bf215546Sopenharmony_ci flushed = TRUE; 1410bf215546Sopenharmony_ci goto validate; 1411bf215546Sopenharmony_ci } 1412bf215546Sopenharmony_ci 1413bf215546Sopenharmony_ci return TRUE; 1414bf215546Sopenharmony_ci} 1415bf215546Sopenharmony_ci 1416bf215546Sopenharmony_ciunsigned r300_get_num_dirty_dwords(struct r300_context *r300) 1417bf215546Sopenharmony_ci{ 1418bf215546Sopenharmony_ci struct r300_atom* atom; 1419bf215546Sopenharmony_ci unsigned dwords = 0; 1420bf215546Sopenharmony_ci 1421bf215546Sopenharmony_ci foreach_dirty_atom(r300, atom) { 1422bf215546Sopenharmony_ci if (atom->dirty) { 1423bf215546Sopenharmony_ci dwords += atom->size; 1424bf215546Sopenharmony_ci } 1425bf215546Sopenharmony_ci } 1426bf215546Sopenharmony_ci 1427bf215546Sopenharmony_ci /* let's reserve some more, just in case */ 1428bf215546Sopenharmony_ci dwords += 32; 1429bf215546Sopenharmony_ci 1430bf215546Sopenharmony_ci return dwords; 1431bf215546Sopenharmony_ci} 1432bf215546Sopenharmony_ci 1433bf215546Sopenharmony_ciunsigned r300_get_num_cs_end_dwords(struct r300_context *r300) 1434bf215546Sopenharmony_ci{ 1435bf215546Sopenharmony_ci unsigned dwords = 0; 1436bf215546Sopenharmony_ci 1437bf215546Sopenharmony_ci /* Emitted in flush. */ 1438bf215546Sopenharmony_ci dwords += 26; /* emit_query_end */ 1439bf215546Sopenharmony_ci dwords += r300->hyperz_state.size + 2; /* emit_hyperz_end + zcache flush */ 1440bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) 1441bf215546Sopenharmony_ci dwords += 2; /* emit_index_bias */ 1442bf215546Sopenharmony_ci dwords += 3; /* MSPOS */ 1443bf215546Sopenharmony_ci 1444bf215546Sopenharmony_ci return dwords; 1445bf215546Sopenharmony_ci} 1446bf215546Sopenharmony_ci 1447bf215546Sopenharmony_ci/* Emit all dirty state. */ 1448bf215546Sopenharmony_civoid r300_emit_dirty_state(struct r300_context* r300) 1449bf215546Sopenharmony_ci{ 1450bf215546Sopenharmony_ci struct r300_atom *atom; 1451bf215546Sopenharmony_ci 1452bf215546Sopenharmony_ci foreach_dirty_atom(r300, atom) { 1453bf215546Sopenharmony_ci if (atom->dirty) { 1454bf215546Sopenharmony_ci atom->emit(r300, atom->size, atom->state); 1455bf215546Sopenharmony_ci atom->dirty = FALSE; 1456bf215546Sopenharmony_ci } 1457bf215546Sopenharmony_ci } 1458bf215546Sopenharmony_ci 1459bf215546Sopenharmony_ci r300->first_dirty = NULL; 1460bf215546Sopenharmony_ci r300->last_dirty = NULL; 1461bf215546Sopenharmony_ci r300->dirty_hw++; 1462bf215546Sopenharmony_ci} 1463