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 36 static void * 37 nv30_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 116 static void 117 nv30_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 125 static void 126 nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso) 127 { 128 FREE(hwcso); 129 } 130 131 static void * 132 nv30_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 193 static void 194 nv30_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 202 static void 203 nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) 204 { 205 FREE(hwcso); 206 } 207 208 static void * 209 nv30_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 263 static void 264 nv30_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 272 static void 273 nv30_zsa_state_delete(struct pipe_context *pipe, void *hwcso) 274 { 275 FREE(hwcso); 276 } 277 278 static void 279 nv30_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 288 static void 289 nv30_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 298 static void 299 nv30_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 309 static void 310 nv30_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 318 static void 319 nv30_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 352 static void 353 nv30_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 364 static void 365 nv30_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 374 static void 375 nv30_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 384 static void 385 nv30_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 394 static void 395 nv30_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 415 static void 416 nv30_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 nv30->idxbuf.index_size = ib->index_size; 424 nv30->idxbuf.offset = ib->offset; 425 nv30->idxbuf.user_buffer = ib->user_buffer; 426 } else { 427 pipe_resource_reference(&nv30->idxbuf.buffer, NULL); 428 nv30->idxbuf.user_buffer = NULL; 429 } 430 } 431 432 void 433 nv30_state_init(struct pipe_context *pipe) 434 { 435 pipe->create_blend_state = nv30_blend_state_create; 436 pipe->bind_blend_state = nv30_blend_state_bind; 437 pipe->delete_blend_state = nv30_blend_state_delete; 438 439 pipe->create_rasterizer_state = nv30_rasterizer_state_create; 440 pipe->bind_rasterizer_state = nv30_rasterizer_state_bind; 441 pipe->delete_rasterizer_state = nv30_rasterizer_state_delete; 442 443 pipe->create_depth_stencil_alpha_state = nv30_zsa_state_create; 444 pipe->bind_depth_stencil_alpha_state = nv30_zsa_state_bind; 445 pipe->delete_depth_stencil_alpha_state = nv30_zsa_state_delete; 446 447 pipe->set_blend_color = nv30_set_blend_color; 448 pipe->set_stencil_ref = nv30_set_stencil_ref; 449 pipe->set_clip_state = nv30_set_clip_state; 450 pipe->set_sample_mask = nv30_set_sample_mask; 451 pipe->set_constant_buffer = nv30_set_constant_buffer; 452 pipe->set_framebuffer_state = nv30_set_framebuffer_state; 453 pipe->set_polygon_stipple = nv30_set_polygon_stipple; 454 pipe->set_scissor_state = nv30_set_scissor_state; 455 pipe->set_viewport_state = nv30_set_viewport_state; 456 457 pipe->set_vertex_buffers = nv30_set_vertex_buffers; 458 pipe->set_index_buffer = nv30_set_index_buffer; 459 } 460