static void * nvc0_zsa_state_create(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *cso) { struct nvc0_zsa_stateobj *so = CALLOC_STRUCT(nvc0_zsa_stateobj); so->pipe = *cso; SB_IMMED_3D(so, DEPTH_TEST_ENABLE, cso->depth.enabled); if (cso->depth.enabled) { SB_IMMED_3D(so, DEPTH_WRITE_ENABLE, cso->depth.writemask); SB_BEGIN_3D(so, DEPTH_TEST_FUNC, 1); SB_DATA (so, nvgl_comparison_op(cso->depth.func)); } if (cso->stencil[0].enabled) { SB_BEGIN_3D(so, STENCIL_ENABLE, 5); SB_DATA (so, 1); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); SB_BEGIN_3D(so, STENCIL_FRONT_FUNC_MASK, 2); SB_DATA (so, cso->stencil[0].valuemask); SB_DATA (so, cso->stencil[0].writemask); } else { SB_IMMED_3D(so, STENCIL_ENABLE, 0); } if (cso->stencil[1].enabled) { assert(cso->stencil[0].enabled); SB_BEGIN_3D(so, STENCIL_TWO_SIDE_ENABLE, 5); SB_DATA (so, 1); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); SB_BEGIN_3D(so, STENCIL_BACK_MASK, 2); SB_DATA (so, cso->stencil[1].writemask); SB_DATA (so, cso->stencil[1].valuemask); } else if (cso->stencil[0].enabled) { SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0); } SB_IMMED_3D(so, ALPHA_TEST_ENABLE, cso->alpha.enabled); if (cso->alpha.enabled) { SB_BEGIN_3D(so, ALPHA_TEST_REF, 2); SB_DATA (so, fui(cso->alpha.ref_value)); SB_DATA (so, nvgl_comparison_op(cso->alpha.func)); } assert(so->size <= (sizeof(so->state) / sizeof(so->state[0]))); return (void *)so; }
static void * nvc0_blend_state_create(struct pipe_context *pipe, const struct pipe_blend_state *cso) { struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj); int i; int r; /* reference */ uint8_t blend_en = 0; bool indep_masks = false; bool indep_funcs = false; so->pipe = *cso; /* check which states actually have differing values */ if (cso->independent_blend_enable) { for (r = 0; r < 8 && !cso->rt[r].blend_enable; ++r); blend_en |= 1 << r; for (i = r + 1; i < 8; ++i) { if (!cso->rt[i].blend_enable) continue; blend_en |= 1 << i; if (cso->rt[i].rgb_func != cso->rt[r].rgb_func || cso->rt[i].rgb_src_factor != cso->rt[r].rgb_src_factor || cso->rt[i].rgb_dst_factor != cso->rt[r].rgb_dst_factor || cso->rt[i].alpha_func != cso->rt[r].alpha_func || cso->rt[i].alpha_src_factor != cso->rt[r].alpha_src_factor || cso->rt[i].alpha_dst_factor != cso->rt[r].alpha_dst_factor) { indep_funcs = true; break; } } for (; i < 8; ++i) blend_en |= (cso->rt[i].blend_enable ? 1 : 0) << i; for (i = 1; i < 8; ++i) { if (cso->rt[i].colormask != cso->rt[0].colormask) { indep_masks = true; break; } } } else { r = 0; if (cso->rt[0].blend_enable) blend_en = 0xff; } if (cso->logicop_enable) { SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2); SB_DATA (so, 1); SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); SB_IMMED_3D(so, MACRO_BLEND_ENABLES, 0); } else { SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0); SB_IMMED_3D(so, BLEND_INDEPENDENT, indep_funcs); SB_IMMED_3D(so, MACRO_BLEND_ENABLES, blend_en); if (indep_funcs) { for (i = 0; i < 8; ++i) { if (cso->rt[i].blend_enable) { SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6); SB_DATA (so, nvgl_blend_eqn(cso->rt[i].rgb_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor)); SB_DATA (so, nvgl_blend_eqn(cso->rt[i].alpha_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor)); } } } else if (blend_en) { SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5); SB_DATA (so, nvgl_blend_eqn(cso->rt[r].rgb_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[r].rgb_src_factor)); SB_DATA (so, nvc0_blend_fac(cso->rt[r].rgb_dst_factor)); SB_DATA (so, nvgl_blend_eqn(cso->rt[r].alpha_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[r].alpha_src_factor)); SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1); SB_DATA (so, nvc0_blend_fac(cso->rt[r].alpha_dst_factor)); } SB_IMMED_3D(so, COLOR_MASK_COMMON, !indep_masks); if (indep_masks) { SB_BEGIN_3D(so, COLOR_MASK(0), 8); for (i = 0; i < 8; ++i) SB_DATA(so, nvc0_colormask(cso->rt[i].colormask)); } else { SB_BEGIN_3D(so, COLOR_MASK(0), 1); SB_DATA (so, nvc0_colormask(cso->rt[0].colormask)); } } assert(so->size <= ARRAY_SIZE(so->state)); return so; }
/* NOTE: ignoring line_last_pixel */ static void * nvc0_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { struct nvc0_rasterizer_stateobj *so; uint32_t reg; so = CALLOC_STRUCT(nvc0_rasterizer_stateobj); if (!so) return NULL; so->pipe = *cso; /* Scissor enables are handled in scissor state, we will not want to * always emit 16 commands, one for each scissor rectangle, here. */ SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); SB_IMMED_3D(so, VERT_COLOR_CLAMP_EN, cso->clamp_vertex_color); SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1); SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000); SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample); SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); if (cso->line_smooth || cso->multisample) SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1); else SB_BEGIN_3D(so, LINE_WIDTH_ALIASED, 1); SB_DATA (so, fui(cso->line_width)); SB_IMMED_3D(so, LINE_STIPPLE_ENABLE, cso->line_stipple_enable); if (cso->line_stipple_enable) { SB_BEGIN_3D(so, LINE_STIPPLE_PATTERN, 1); SB_DATA (so, (cso->line_stipple_pattern << 8) | cso->line_stipple_factor); } SB_IMMED_3D(so, VP_POINT_SIZE, cso->point_size_per_vertex); if (!cso->point_size_per_vertex) { SB_BEGIN_3D(so, POINT_SIZE, 1); SB_DATA (so, fui(cso->point_size)); } reg = (cso->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT) ? NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT : NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT; SB_BEGIN_3D(so, POINT_COORD_REPLACE, 1); SB_DATA (so, ((cso->sprite_coord_enable & 0xff) << 3) | reg); SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); SB_IMMED_3D(so, POINT_SMOOTH_ENABLE, cso->point_smooth); SB_BEGIN_3D(so, MACRO_POLYGON_MODE_FRONT, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); SB_BEGIN_3D(so, MACRO_POLYGON_MODE_BACK, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : NVC0_3D_FRONT_FACE_CW); switch (cso->cull_face) { case PIPE_FACE_FRONT_AND_BACK: SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); break; case PIPE_FACE_FRONT: SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); break; case PIPE_FACE_BACK: default: SB_DATA(so, NVC0_3D_CULL_FACE_BACK); break; } SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); SB_DATA (so, cso->offset_point); SB_DATA (so, cso->offset_line); SB_DATA (so, cso->offset_tri); if (cso->offset_point || cso->offset_line || cso->offset_tri) { SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1); SB_DATA (so, fui(cso->offset_scale)); SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); SB_DATA (so, fui(cso->offset_units * 2.0f)); SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1); SB_DATA (so, fui(cso->offset_clamp)); } if (cso->depth_clip) reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1; else reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2; SB_BEGIN_3D(so, VIEW_VOLUME_CLIP_CTRL, 1); SB_DATA (so, reg); SB_IMMED_3D(so, DEPTH_CLIP_NEGATIVE_Z, cso->clip_halfz); SB_IMMED_3D(so, PIXEL_CENTER_INTEGER, !cso->half_pixel_center); assert(so->size <= ARRAY_SIZE(so->state)); return (void *)so; }
/* NOTE: ignoring line_last_pixel */ static void * nvc0_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { struct nvc0_rasterizer_stateobj *so; uint16_t class_3d = nouveau_screen(pipe->screen)->class_3d; uint32_t reg; so = CALLOC_STRUCT(nvc0_rasterizer_stateobj); if (!so) return NULL; so->pipe = *cso; /* Scissor enables are handled in scissor state, we will not want to * always emit 16 commands, one for each scissor rectangle, here. */ SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); SB_IMMED_3D(so, VERT_COLOR_CLAMP_EN, cso->clamp_vertex_color); SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1); SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000); SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample); SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); /* On GM20x+, LINE_WIDTH_SMOOTH controls both aliased and smooth * rendering and LINE_WIDTH_ALIASED seems to be ignored */ if (cso->line_smooth || cso->multisample || class_3d >= GM200_3D_CLASS) SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1); else SB_BEGIN_3D(so, LINE_WIDTH_ALIASED, 1); SB_DATA (so, fui(cso->line_width)); SB_IMMED_3D(so, LINE_STIPPLE_ENABLE, cso->line_stipple_enable); if (cso->line_stipple_enable) { SB_BEGIN_3D(so, LINE_STIPPLE_PATTERN, 1); SB_DATA (so, (cso->line_stipple_pattern << 8) | cso->line_stipple_factor); } SB_IMMED_3D(so, VP_POINT_SIZE, cso->point_size_per_vertex); if (!cso->point_size_per_vertex) { SB_BEGIN_3D(so, POINT_SIZE, 1); SB_DATA (so, fui(cso->point_size)); } reg = (cso->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT) ? NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT : NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT; SB_BEGIN_3D(so, POINT_COORD_REPLACE, 1); SB_DATA (so, ((cso->sprite_coord_enable & 0xff) << 3) | reg); SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); SB_IMMED_3D(so, POINT_SMOOTH_ENABLE, cso->point_smooth); if (class_3d >= GM200_3D_CLASS) { SB_IMMED_3D(so, FILL_RECTANGLE, cso->fill_front == PIPE_POLYGON_MODE_FILL_RECTANGLE ? NVC0_3D_FILL_RECTANGLE_ENABLE : 0); } SB_BEGIN_3D(so, MACRO_POLYGON_MODE_FRONT, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); SB_BEGIN_3D(so, MACRO_POLYGON_MODE_BACK, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : NVC0_3D_FRONT_FACE_CW); switch (cso->cull_face) { case PIPE_FACE_FRONT_AND_BACK: SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); break; case PIPE_FACE_FRONT: SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); break; case PIPE_FACE_BACK: default: SB_DATA(so, NVC0_3D_CULL_FACE_BACK); break; } SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); SB_DATA (so, cso->offset_point); SB_DATA (so, cso->offset_line); SB_DATA (so, cso->offset_tri); if (cso->offset_point || cso->offset_line || cso->offset_tri) { SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1); SB_DATA (so, fui(cso->offset_scale)); if (!cso->offset_units_unscaled) { SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); SB_DATA (so, fui(cso->offset_units * 2.0f)); } SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1); SB_DATA (so, fui(cso->offset_clamp)); } if (cso->depth_clip_near) reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1; else reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2; SB_BEGIN_3D(so, VIEW_VOLUME_CLIP_CTRL, 1); SB_DATA (so, reg); SB_IMMED_3D(so, DEPTH_CLIP_NEGATIVE_Z, cso->clip_halfz); SB_IMMED_3D(so, PIXEL_CENTER_INTEGER, !cso->half_pixel_center); if (class_3d >= GM200_3D_CLASS) { if (cso->conservative_raster_mode != PIPE_CONSERVATIVE_RASTER_OFF) { bool post_snap = cso->conservative_raster_mode == PIPE_CONSERVATIVE_RASTER_POST_SNAP; uint32_t state = cso->subpixel_precision_x; state |= cso->subpixel_precision_y << 4; state |= (uint32_t)(cso->conservative_raster_dilate * 4) << 8; state |= (post_snap || class_3d < GP100_3D_CLASS) ? 1 << 10 : 0; SB_IMMED_3D(so, MACRO_CONSERVATIVE_RASTER_STATE, state); } else { SB_IMMED_3D(so, CONSERVATIVE_RASTER, 0); } } assert(so->size <= ARRAY_SIZE(so->state)); return (void *)so; }
static void * nvc0_blend_state_create(struct pipe_context *pipe, const struct pipe_blend_state *cso) { struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj); int i; uint32_t ms; so->pipe = *cso; SB_IMMED_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable); if (!cso->logicop_enable) SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0); if (cso->logicop_enable) { SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2); SB_DATA (so, 1); SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); SB_IMMED_3D(so, BLEND_ENABLES, 0); } else if (!cso->independent_blend_enable) { SB_IMMED_3D(so, BLEND_ENABLES, cso->rt[0].blend_enable ? 0xff : 0); if (cso->rt[0].blend_enable) { SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5); SB_DATA (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[0].rgb_src_factor)); SB_DATA (so, nvc0_blend_fac(cso->rt[0].rgb_dst_factor)); SB_DATA (so, nvgl_blend_eqn(cso->rt[0].alpha_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[0].alpha_src_factor)); SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1); SB_DATA (so, nvc0_blend_fac(cso->rt[0].alpha_dst_factor)); } SB_IMMED_3D(so, COLOR_MASK_COMMON, 1); SB_BEGIN_3D(so, COLOR_MASK(0), 1); SB_DATA (so, nvc0_colormask(cso->rt[0].colormask)); } else { uint8_t en = 0; for (i = 0; i < 8; ++i) { if (!cso->rt[i].blend_enable) continue; en |= 1 << i; SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6); SB_DATA (so, nvgl_blend_eqn(cso->rt[i].rgb_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor)); SB_DATA (so, nvgl_blend_eqn(cso->rt[i].alpha_func)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor)); SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor)); } SB_IMMED_3D(so, BLEND_ENABLES, en); SB_IMMED_3D(so, COLOR_MASK_COMMON, 0); SB_BEGIN_3D(so, COLOR_MASK(0), 8); for (i = 0; i < 8; ++i) SB_DATA(so, nvc0_colormask(cso->rt[i].colormask)); } ms = 0; if (cso->alpha_to_coverage) ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE; if (cso->alpha_to_one) ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE; SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1); SB_DATA (so, ms); assert(so->size <= (sizeof(so->state) / sizeof(so->state[0]))); return so; }