nv50_state_validate.c revision df4228deddea36b9d5b41ea395a216137e046205
1/* 2 * Copyright 2008 Ben Skeggs 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23#include "nv50_context.h" 24#include "nouveau/nouveau_stateobj.h" 25 26static void 27nv50_state_validate_fb(struct nv50_context *nv50) 28{ 29 struct nouveau_grobj *tesla = nv50->screen->tesla; 30 struct nouveau_stateobj *so = so_new(128, 18); 31 struct pipe_framebuffer_state *fb = &nv50->framebuffer; 32 unsigned i, w, h, gw = 0; 33 34 for (i = 0; i < fb->num_cbufs; i++) { 35 if (!gw) { 36 w = fb->cbufs[i]->width; 37 h = fb->cbufs[i]->height; 38 gw = 1; 39 } else { 40 assert(w == fb->cbufs[i]->width); 41 assert(h == fb->cbufs[i]->height); 42 } 43 44 so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2); 45 so_data (so, fb->cbufs[i]->width); 46 so_data (so, fb->cbufs[i]->height); 47 48 so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5); 49 so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset, 50 NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0); 51 so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset, 52 NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0); 53 switch (fb->cbufs[i]->format) { 54 case PIPE_FORMAT_A8R8G8B8_UNORM: 55 so_data(so, 0xcf); 56 break; 57 case PIPE_FORMAT_R5G6B5_UNORM: 58 so_data(so, 0xe8); 59 break; 60 default: 61 NOUVEAU_ERR("AIIII unknown format %s\n", 62 pf_name(fb->cbufs[i]->format)); 63 so_data(so, 0xe6); 64 break; 65 } 66 so_data(so, 0x00000000); 67 so_data(so, 0x00000000); 68 69 so_method(so, tesla, 0x1224, 1); 70 so_data (so, 1); 71 } 72 73 if (fb->zsbuf) { 74 if (!gw) { 75 w = fb->zsbuf->width; 76 h = fb->zsbuf->height; 77 gw = 1; 78 } else { 79 assert(w == fb->zsbuf->width); 80 assert(h == fb->zsbuf->height); 81 } 82 83 so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5); 84 so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset, 85 NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0); 86 so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset, 87 NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0); 88 switch (fb->zsbuf->format) { 89 case PIPE_FORMAT_Z24S8_UNORM: 90 so_data(so, 0x16); 91 break; 92 case PIPE_FORMAT_Z16_UNORM: 93 so_data(so, 0x15); 94 break; 95 default: 96 NOUVEAU_ERR("AIIII unknown format %s\n", 97 pf_name(fb->zsbuf->format)); 98 so_data(so, 0x16); 99 break; 100 } 101 so_data(so, 0x00000000); 102 so_data(so, 0x00000000); 103 104 so_method(so, tesla, 0x1538, 1); 105 so_data (so, 1); 106 so_method(so, tesla, 0x1228, 3); 107 so_data (so, fb->zsbuf->width); 108 so_data (so, fb->zsbuf->height); 109 so_data (so, 0x00010001); 110 } 111 112 so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2); 113 so_data (so, w << 16); 114 so_data (so, h << 16); 115 so_method(so, tesla, 0x0e04, 2); 116 so_data (so, w << 16); 117 so_data (so, h << 16); 118 so_method(so, tesla, 0xdf8, 2); 119 so_data (so, 0); 120 so_data (so, h); 121 122 so_ref(so, &nv50->state.fb); 123} 124 125static void 126nv50_state_emit(struct nv50_context *nv50) 127{ 128 struct nv50_screen *screen = nv50->screen; 129 struct nouveau_winsys *nvws = screen->nvws; 130 131 if (nv50->pctx_id != screen->cur_pctx) { 132 nv50->state.dirty |= 0xffffffff; 133 screen->cur_pctx = nv50->pctx_id; 134 } 135 136 if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER) 137 so_emit(nvws, nv50->state.fb); 138 if (nv50->state.dirty & NV50_NEW_BLEND) 139 so_emit(nvws, nv50->state.blend); 140 if (nv50->state.dirty & NV50_NEW_ZSA) 141 so_emit(nvws, nv50->state.zsa); 142 if (nv50->state.dirty & NV50_NEW_VERTPROG) 143 so_emit(nvws, nv50->state.vertprog); 144 if (nv50->state.dirty & NV50_NEW_FRAGPROG) 145 so_emit(nvws, nv50->state.fragprog); 146 if (nv50->state.dirty & NV50_NEW_RASTERIZER) 147 so_emit(nvws, nv50->state.rast); 148 if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR) 149 so_emit(nvws, nv50->state.blend_colour); 150 if (nv50->state.dirty & NV50_NEW_STIPPLE) 151 so_emit(nvws, nv50->state.stipple); 152 if (nv50->state.dirty & NV50_NEW_SCISSOR) 153 so_emit(nvws, nv50->state.scissor); 154 if (nv50->state.dirty & NV50_NEW_VIEWPORT) 155 so_emit(nvws, nv50->state.viewport); 156 if (nv50->state.dirty & NV50_NEW_SAMPLER) 157 so_emit(nvws, nv50->state.tsc_upload); 158 if (nv50->state.dirty & NV50_NEW_TEXTURE) 159 so_emit(nvws, nv50->state.tic_upload); 160 if (nv50->state.dirty & NV50_NEW_ARRAYS) { 161 so_emit(nvws, nv50->state.vtxfmt); 162 so_emit(nvws, nv50->state.vtxbuf); 163 } 164 nv50->state.dirty = 0; 165 166 so_emit_reloc_markers(nvws, nv50->state.fb); 167 so_emit_reloc_markers(nvws, nv50->state.vertprog); 168 so_emit_reloc_markers(nvws, nv50->state.fragprog); 169 so_emit_reloc_markers(nvws, nv50->state.vtxbuf); 170 so_emit_reloc_markers(nvws, nv50->screen->static_init); 171} 172 173boolean 174nv50_state_validate(struct nv50_context *nv50) 175{ 176 const struct pipe_framebuffer_state *fb = &nv50->framebuffer; 177 struct nouveau_grobj *tesla = nv50->screen->tesla; 178 struct nouveau_stateobj *so; 179 unsigned i; 180 181 for (i = 0; i < fb->num_cbufs; i++) 182 fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED; 183 184 if (fb->zsbuf) 185 fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED; 186 187 if (nv50->dirty & NV50_NEW_FRAMEBUFFER) 188 nv50_state_validate_fb(nv50); 189 190 if (nv50->dirty & NV50_NEW_BLEND) 191 so_ref(nv50->blend->so, &nv50->state.blend); 192 193 if (nv50->dirty & NV50_NEW_ZSA) 194 so_ref(nv50->zsa->so, &nv50->state.zsa); 195 196 if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB)) 197 nv50_vertprog_validate(nv50); 198 199 if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB)) 200 nv50_fragprog_validate(nv50); 201 202 if (nv50->dirty & NV50_NEW_RASTERIZER) 203 so_ref(nv50->rasterizer->so, &nv50->state.rast); 204 205 if (nv50->dirty & NV50_NEW_BLEND_COLOUR) { 206 so = so_new(5, 0); 207 so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4); 208 so_data (so, fui(nv50->blend_colour.color[0])); 209 so_data (so, fui(nv50->blend_colour.color[1])); 210 so_data (so, fui(nv50->blend_colour.color[2])); 211 so_data (so, fui(nv50->blend_colour.color[3])); 212 so_ref(so, &nv50->state.blend_colour); 213 } 214 215 if (nv50->dirty & NV50_NEW_STIPPLE) { 216 so = so_new(33, 0); 217 so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); 218 for (i = 0; i < 32; i++) 219 so_data(so, nv50->stipple.stipple[i]); 220 so_ref(so, &nv50->state.stipple); 221 } 222 223 if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) { 224 struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe; 225 struct pipe_scissor_state *s = &nv50->scissor; 226 227 if (nv50->state.scissor && 228 (rast->scissor == 0 && nv50->state.scissor_enabled == 0)) 229 goto scissor_uptodate; 230 nv50->state.scissor_enabled = rast->scissor; 231 232 so = so_new(3, 0); 233 so_method(so, tesla, 0x0ff4, 2); 234 if (nv50->state.scissor_enabled) { 235 so_data(so, ((s->maxx - s->minx) << 16) | s->minx); 236 so_data(so, ((s->maxy - s->miny) << 16) | s->miny); 237 } else { 238 so_data(so, (8192 << 16)); 239 so_data(so, (8192 << 16)); 240 } 241 so_ref(so, &nv50->state.scissor); 242 nv50->state.dirty |= NV50_NEW_SCISSOR; 243 } 244scissor_uptodate: 245 246 if (nv50->dirty & NV50_NEW_VIEWPORT) { 247 unsigned bypass; 248 249 if (!nv50->rasterizer->pipe.bypass_clipping) 250 bypass = 0; 251 else 252 bypass = 1; 253 254 if (nv50->state.viewport && 255 (bypass || !(nv50->dirty & NV50_NEW_VIEWPORT)) && 256 nv50->state.viewport_bypass == bypass) 257 goto viewport_uptodate; 258 nv50->state.viewport_bypass = bypass; 259 260 so = so_new(12, 0); 261 if (!bypass) { 262 so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3); 263 so_data (so, fui(nv50->viewport.translate[0])); 264 so_data (so, fui(nv50->viewport.translate[1])); 265 so_data (so, fui(nv50->viewport.translate[2])); 266 so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3); 267 so_data (so, fui(nv50->viewport.scale[0])); 268 so_data (so, fui(-nv50->viewport.scale[1])); 269 so_data (so, fui(nv50->viewport.scale[2])); 270 so_method(so, tesla, 0x192c, 1); 271 so_data (so, 1); 272 so_method(so, tesla, 0x0f90, 1); 273 so_data (so, 0); 274 } else { 275 so_method(so, tesla, 0x192c, 1); 276 so_data (so, 0); 277 so_method(so, tesla, 0x0f90, 1); 278 so_data (so, 1); 279 } 280 281 so_ref(so, &nv50->state.viewport); 282 } 283viewport_uptodate: 284 285 if (nv50->dirty & NV50_NEW_SAMPLER) { 286 int i; 287 288 so = so_new(nv50->sampler_nr * 8 + 3, 0); 289 so_method(so, tesla, 0x0f00, 1); 290 so_data (so, NV50_CB_TSC); 291 so_method(so, tesla, 0x40000f04, nv50->sampler_nr * 8); 292 for (i = 0; i < nv50->sampler_nr; i++) 293 so_datap (so, nv50->sampler[i], 8); 294 so_ref(so, &nv50->state.tsc_upload); 295 } 296 297 if (nv50->dirty & NV50_NEW_TEXTURE) 298 nv50_tex_validate(nv50); 299 300 if (nv50->dirty & NV50_NEW_ARRAYS) 301 nv50_vbo_validate(nv50); 302 303 nv50->state.dirty |= nv50->dirty; 304 nv50->dirty = 0; 305 nv50_state_emit(nv50); 306 307 return TRUE; 308} 309 310