1 /* 2 * Copyright 2012 Red Hat Inc. 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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 * 24 */ 25 26 #include "util/u_format.h" 27 #include "util/u_helpers.h" 28 #include "util/u_inlines.h" 29 30 #include "nouveau_gldefs.h" 31 #include "nv_object.xml.h" 32 #include "nv30/nv30-40_3d.xml.h" 33 #include "nv30/nv30_context.h" 34 #include "nv30/nv30_winsys.h" 35 36 #define NV40_3D_MRT_BLEND_ENABLE 0x0000036c 37 38 static void * 39 nv30_blend_state_create(struct pipe_context *pipe, 40 const struct pipe_blend_state *cso) 41 { 42 struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; 43 struct nv30_blend_stateobj *so; 44 uint32_t blend[2], cmask[2]; 45 int i; 46 47 so = CALLOC_STRUCT(nv30_blend_stateobj); 48 if (!so) 49 return NULL; 50 so->pipe = *cso; 51 52 if (cso->logicop_enable) { 53 SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 2); 54 SB_DATA (so, 1); 55 SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); 56 } else { 57 SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 1); 58 SB_DATA (so, 0); 59 } 60 61 SB_MTHD30(so, DITHER_ENABLE, 1); 62 SB_DATA (so, cso->dither); 63 64 blend[0] = cso->rt[0].blend_enable; 65 cmask[0] = !!(cso->rt[0].colormask & PIPE_MASK_A) << 24 | 66 !!(cso->rt[0].colormask & PIPE_MASK_R) << 16 | 67 !!(cso->rt[0].colormask & PIPE_MASK_G) << 8 | 68 !!(cso->rt[0].colormask & PIPE_MASK_B); 69 if (cso->independent_blend_enable) { 70 blend[1] = 0; 71 cmask[1] = 0; 72 for (i = 1; i < 4; i++) { 73 blend[1] |= cso->rt[i].blend_enable << i; 74 cmask[1] |= !!(cso->rt[i].colormask & PIPE_MASK_A) << (0 + (i * 4)) | 75 !!(cso->rt[i].colormask & PIPE_MASK_R) << (1 + (i * 4)) | 76 !!(cso->rt[i].colormask & PIPE_MASK_G) << (2 + (i * 4)) | 77 !!(cso->rt[i].colormask & PIPE_MASK_B) << (3 + (i * 4)); 78 } 79 } else { 80 blend[1] = 0x0000000e * (blend[0] & 0x00000001); 81 cmask[1] = 0x00001110 * !!(cmask[0] & 0x01000000); 82 cmask[1] |= 0x00002220 * !!(cmask[0] & 0x00010000); 83 cmask[1] |= 0x00004440 * !!(cmask[0] & 0x00000100); 84 cmask[1] |= 0x00008880 * !!(cmask[0] & 0x00000001); 85 } 86 87 if (eng3d->oclass >= NV40_3D_CLASS) { 88 SB_MTHD40(so, MRT_BLEND_ENABLE, 2); 89 SB_DATA (so, blend[1]); 90 SB_DATA (so, cmask[1]); 91 } 92 93 if (blend[0] || blend[1]) { 94 SB_MTHD30(so, BLEND_FUNC_ENABLE, 3); 95 SB_DATA (so, blend[0]); 96 SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | 97 nvgl_blend_func(cso->rt[0].rgb_src_factor)); 98 SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16) | 99 nvgl_blend_func(cso->rt[0].rgb_dst_factor)); 100 if (eng3d->oclass < NV40_3D_CLASS) { 101 SB_MTHD30(so, BLEND_EQUATION, 1); 102 SB_DATA (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); 103 } else { 104 SB_MTHD40(so, BLEND_EQUATION, 1); 105 SB_DATA (so, (nvgl_blend_eqn(cso->rt[0].alpha_func) << 16) | 106 nvgl_blend_eqn(cso->rt[0].rgb_func)); 107 } 108 } else { 109 SB_MTHD30(so, BLEND_FUNC_ENABLE, 1); 110 SB_DATA (so, blend[0]); 111 } 112 113 SB_MTHD30(so, COLOR_MASK, 1); 114 SB_DATA (so, cmask[0]); 115 return so; 116 } 117 118 static void 119 nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso) 120 { 121 struct nv30_context *nv30 = nv30_context(pipe); 122 123 nv30->blend = hwcso; 124 nv30->dirty |= NV30_NEW_BLEND; 125 } 126 127 static void 128 nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso) 129 { 130 FREE(hwcso); 131 } 132 133 static void * 134 nv30_rasterizer_state_create(struct pipe_context *pipe, 135 const struct pipe_rasterizer_state *cso) 136 { 137 struct nv30_rasterizer_stateobj *so; 138 139 so = CALLOC_STRUCT(nv30_rasterizer_stateobj); 140 if (!so) 141 return NULL; 142 so->pipe = *cso; 143 144 SB_MTHD30(so, SHADE_MODEL, 1); 145 SB_DATA (so, cso->flatshade ? NV30_3D_SHADE_MODEL_FLAT : 146 NV30_3D_SHADE_MODEL_SMOOTH); 147 148 SB_MTHD30(so, POLYGON_MODE_FRONT, 6); 149 SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); 150 SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); 151 if (cso->cull_face == PIPE_FACE_FRONT_AND_BACK) 152 SB_DATA (so, NV30_3D_CULL_FACE_FRONT_AND_BACK); 153 else 154 if (cso->cull_face == PIPE_FACE_FRONT) 155 SB_DATA (so, NV30_3D_CULL_FACE_FRONT); 156 else 157 SB_DATA (so, NV30_3D_CULL_FACE_BACK); 158 SB_DATA (so, cso->front_ccw ? NV30_3D_FRONT_FACE_CCW : 159 NV30_3D_FRONT_FACE_CW); 160 SB_DATA (so, cso->poly_smooth); 161 SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); 162 163 SB_MTHD30(so, POLYGON_OFFSET_POINT_ENABLE, 3); 164 SB_DATA (so, cso->offset_point); 165 SB_DATA (so, cso->offset_line); 166 SB_DATA (so, cso->offset_tri); 167 if (cso->offset_point || cso->offset_line || cso->offset_tri) { 168 SB_MTHD30(so, POLYGON_OFFSET_FACTOR, 2); 169 SB_DATA (so, fui(cso->offset_scale)); 170 SB_DATA (so, fui(cso->offset_units * 2.0)); 171 } 172 173 SB_MTHD30(so, LINE_WIDTH, 2); 174 SB_DATA (so, (unsigned char)(cso->line_width * 8.0) & 0xff); 175 SB_DATA (so, cso->line_smooth); 176 SB_MTHD30(so, LINE_STIPPLE_ENABLE, 2); 177 SB_DATA (so, cso->line_stipple_enable); 178 SB_DATA (so, (cso->line_stipple_pattern << 16) | 179 cso->line_stipple_factor); 180 181 SB_MTHD30(so, VERTEX_TWO_SIDE_ENABLE, 1); 182 SB_DATA (so, cso->light_twoside); 183 SB_MTHD30(so, POLYGON_STIPPLE_ENABLE, 1); 184 SB_DATA (so, cso->poly_stipple_enable); 185 SB_MTHD30(so, POINT_SIZE, 1); 186 SB_DATA (so, fui(cso->point_size)); 187 SB_MTHD30(so, FLATSHADE_FIRST, 1); 188 SB_DATA (so, cso->flatshade_first); 189 190 SB_MTHD30(so, DEPTH_CONTROL, 1); 191 SB_DATA (so, cso->depth_clip ? 0x00000001 : 0x00000010); 192 return so; 193 } 194 195 static void 196 nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) 197 { 198 struct nv30_context *nv30 = nv30_context(pipe); 199 200 nv30->rast = hwcso; 201 nv30->dirty |= NV30_NEW_RASTERIZER; 202 } 203 204 static void 205 nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) 206 { 207 FREE(hwcso); 208 } 209 210 static void * 211 nv30_zsa_state_create(struct pipe_context *pipe, 212 const struct pipe_depth_stencil_alpha_state *cso) 213 { 214 struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; 215 struct nv30_zsa_stateobj *so; 216 217 so = CALLOC_STRUCT(nv30_zsa_stateobj); 218 if (!so) 219 return NULL; 220 so->pipe = *cso; 221 222 SB_MTHD30(so, DEPTH_FUNC, 3); 223 SB_DATA (so, nvgl_comparison_op(cso->depth.func)); 224 SB_DATA (so, cso->depth.writemask); 225 SB_DATA (so, cso->depth.enabled); 226 227 if (eng3d->oclass == NV35_3D_CLASS || eng3d->oclass >= NV40_3D_CLASS) { 228 SB_MTHD35(so, DEPTH_BOUNDS_TEST_ENABLE, 3); 229 SB_DATA (so, cso->depth.bounds_test); 230 SB_DATA (so, fui(cso->depth.bounds_min)); 231 SB_DATA (so, fui(cso->depth.bounds_max)); 232 } 233 234 if (cso->stencil[0].enabled) { 235 SB_MTHD30(so, STENCIL_ENABLE(0), 3); 236 SB_DATA (so, 1); 237 SB_DATA (so, cso->stencil[0].writemask); 238 SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); 239 SB_MTHD30(so, STENCIL_FUNC_MASK(0), 4); 240 SB_DATA (so, cso->stencil[0].valuemask); 241 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); 242 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); 243 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); 244 } else { 245 SB_MTHD30(so, STENCIL_ENABLE(0), 2); 246 SB_DATA (so, 0); 247 SB_DATA (so, 0x000000ff); 248 } 249 250 if (cso->stencil[1].enabled) { 251 SB_MTHD30(so, STENCIL_ENABLE(1), 3); 252 SB_DATA (so, 1); 253 SB_DATA (so, cso->stencil[1].writemask); 254 SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); 255 SB_MTHD30(so, STENCIL_FUNC_MASK(1), 4); 256 SB_DATA (so, cso->stencil[1].valuemask); 257 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); 258 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); 259 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); 260 } else { 261 SB_MTHD30(so, STENCIL_ENABLE(1), 1); 262 SB_DATA (so, 0); 263 } 264 265 SB_MTHD30(so, ALPHA_FUNC_ENABLE, 3); 266 SB_DATA (so, cso->alpha.enabled ? 1 : 0); 267 SB_DATA (so, nvgl_comparison_op(cso->alpha.func)); 268 SB_DATA (so, float_to_ubyte(cso->alpha.ref_value)); 269 270 return so; 271 } 272 273 static void 274 nv30_zsa_state_bind(struct pipe_context *pipe, void *hwcso) 275 { 276 struct nv30_context *nv30 = nv30_context(pipe); 277 278 nv30->zsa = hwcso; 279 nv30->dirty |= NV30_NEW_ZSA; 280 } 281 282 static void 283 nv30_zsa_state_delete(struct pipe_context *pipe, void *hwcso) 284 { 285 FREE(hwcso); 286 } 287 288 static void 289 nv30_set_blend_color(struct pipe_context *pipe, 290 const struct pipe_blend_color *bcol) 291 { 292 struct nv30_context *nv30 = nv30_context(pipe); 293 294 nv30->blend_colour = *bcol; 295 nv30->dirty |= NV30_NEW_BLEND_COLOUR; 296 } 297 298 static void 299 nv30_set_stencil_ref(struct pipe_context *pipe, 300 const struct pipe_stencil_ref *sr) 301 { 302 struct nv30_context *nv30 = nv30_context(pipe); 303 304 nv30->stencil_ref = *sr; 305 nv30->dirty |= NV30_NEW_STENCIL_REF; 306 } 307 308 static void 309 nv30_set_clip_state(struct pipe_context *pipe, 310 const struct pipe_clip_state *clip) 311 { 312 struct nv30_context *nv30 = nv30_context(pipe); 313 314 memcpy(nv30->clip.ucp, clip->ucp, sizeof(clip->ucp)); 315 316 nv30->dirty |= NV30_NEW_CLIP; 317 } 318 319 static void 320 nv30_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) 321 { 322 struct nv30_context *nv30 = nv30_context(pipe); 323 324 nv30->sample_mask = sample_mask; 325 nv30->dirty |= NV30_NEW_SAMPLE_MASK; 326 } 327 328 static void 329 nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, 330 const struct pipe_constant_buffer *cb) 331 { 332 struct nv30_context *nv30 = nv30_context(pipe); 333 struct pipe_resource *buf = cb ? cb->buffer : NULL; 334 unsigned size; 335 336 if (cb && cb->user_buffer) { 337 buf = nouveau_user_buffer_create(pipe->screen, (void*)cb->user_buffer, 338 cb->buffer_size, 339 PIPE_BIND_CONSTANT_BUFFER); 340 } 341 342 size = 0; 343 if (buf) 344 size = buf->width0 / (4 * sizeof(float)); 345 346 if (shader == PIPE_SHADER_VERTEX) { 347 pipe_resource_reference(&nv30->vertprog.constbuf, buf); 348 nv30->vertprog.constbuf_nr = size; 349 nv30->dirty |= NV30_NEW_VERTCONST; 350 } else 351 if (shader == PIPE_SHADER_FRAGMENT) { 352 pipe_resource_reference(&nv30->fragprog.constbuf, buf); 353 nv30->fragprog.constbuf_nr = size; 354 nv30->dirty |= NV30_NEW_FRAGCONST; 355 } 356 357 if (cb && cb->user_buffer) { 358 pipe_resource_reference(&buf, NULL); 359 } 360 } 361 362 static void 363 nv30_set_framebuffer_state(struct pipe_context *pipe, 364 const struct pipe_framebuffer_state *fb) 365 { 366 struct nv30_context *nv30 = nv30_context(pipe); 367 368 nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB); 369 370 nv30->framebuffer = *fb; 371 nv30->dirty |= NV30_NEW_FRAMEBUFFER; 372 373 /* Hardware can't handle different swizzled-ness or different blocksizes 374 * for zs and cbufs. If both are supplied and something doesn't match, 375 * blank out the zs for now so that at least *some* rendering can occur. 376 */ 377 if (fb->nr_cbufs > 0 && fb->zsbuf) { 378 struct nv30_miptree *color_mt = nv30_miptree(fb->cbufs[0]->texture); 379 struct nv30_miptree *zeta_mt = nv30_miptree(fb->zsbuf->texture); 380 381 if (color_mt->swizzled != zeta_mt->swizzled || 382 (color_mt->swizzled && 383 (util_format_get_blocksize(fb->zsbuf->format) > 2) != 384 (util_format_get_blocksize(fb->cbufs[0]->format) > 2))) { 385 nv30->framebuffer.zsbuf = NULL; 386 debug_printf("Mismatched color and zeta formats, ignoring zeta.\n"); 387 } 388 } 389 } 390 391 static void 392 nv30_set_polygon_stipple(struct pipe_context *pipe, 393 const struct pipe_poly_stipple *stipple) 394 { 395 struct nv30_context *nv30 = nv30_context(pipe); 396 397 nv30->stipple = *stipple; 398 nv30->dirty |= NV30_NEW_STIPPLE; 399 } 400 401 static void 402 nv30_set_scissor_states(struct pipe_context *pipe, 403 unsigned start_slot, 404 unsigned num_viewports, 405 const struct pipe_scissor_state *scissor) 406 { 407 struct nv30_context *nv30 = nv30_context(pipe); 408 409 nv30->scissor = *scissor; 410 nv30->dirty |= NV30_NEW_SCISSOR; 411 } 412 413 static void 414 nv30_set_viewport_states(struct pipe_context *pipe, 415 unsigned start_slot, 416 unsigned num_viewports, 417 const struct pipe_viewport_state *vpt) 418 { 419 struct nv30_context *nv30 = nv30_context(pipe); 420 421 nv30->viewport = *vpt; 422 nv30->dirty |= NV30_NEW_VIEWPORT; 423 } 424 425 static void 426 nv30_set_vertex_buffers(struct pipe_context *pipe, 427 unsigned start_slot, unsigned count, 428 const struct pipe_vertex_buffer *vb) 429 { 430 struct nv30_context *nv30 = nv30_context(pipe); 431 432 nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF); 433 434 util_set_vertex_buffers_count(nv30->vtxbuf, &nv30->num_vtxbufs, 435 vb, start_slot, count); 436 437 nv30->dirty |= NV30_NEW_ARRAYS; 438 } 439 440 static void 441 nv30_set_index_buffer(struct pipe_context *pipe, 442 const struct pipe_index_buffer *ib) 443 { 444 struct nv30_context *nv30 = nv30_context(pipe); 445 446 if (ib) { 447 pipe_resource_reference(&nv30->idxbuf.buffer, ib->buffer); 448 nv30->idxbuf.index_size = ib->index_size; 449 nv30->idxbuf.offset = ib->offset; 450 nv30->idxbuf.user_buffer = ib->user_buffer; 451 } else { 452 pipe_resource_reference(&nv30->idxbuf.buffer, NULL); 453 nv30->idxbuf.user_buffer = NULL; 454 } 455 } 456 457 void 458 nv30_state_init(struct pipe_context *pipe) 459 { 460 pipe->create_blend_state = nv30_blend_state_create; 461 pipe->bind_blend_state = nv30_blend_state_bind; 462 pipe->delete_blend_state = nv30_blend_state_delete; 463 464 pipe->create_rasterizer_state = nv30_rasterizer_state_create; 465 pipe->bind_rasterizer_state = nv30_rasterizer_state_bind; 466 pipe->delete_rasterizer_state = nv30_rasterizer_state_delete; 467 468 pipe->create_depth_stencil_alpha_state = nv30_zsa_state_create; 469 pipe->bind_depth_stencil_alpha_state = nv30_zsa_state_bind; 470 pipe->delete_depth_stencil_alpha_state = nv30_zsa_state_delete; 471 472 pipe->set_blend_color = nv30_set_blend_color; 473 pipe->set_stencil_ref = nv30_set_stencil_ref; 474 pipe->set_clip_state = nv30_set_clip_state; 475 pipe->set_sample_mask = nv30_set_sample_mask; 476 pipe->set_constant_buffer = nv30_set_constant_buffer; 477 pipe->set_framebuffer_state = nv30_set_framebuffer_state; 478 pipe->set_polygon_stipple = nv30_set_polygon_stipple; 479 pipe->set_scissor_states = nv30_set_scissor_states; 480 pipe->set_viewport_states = nv30_set_viewport_states; 481 482 pipe->set_vertex_buffers = nv30_set_vertex_buffers; 483 pipe->set_index_buffer = nv30_set_index_buffer; 484 } 485