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