RenderPassDesc Driver::getRenderPassDesc() { auto desc = RenderPassDesc {}; auto cb_target_mask = getRegister<latte::CB_TARGET_MASK>(latte::Register::CB_TARGET_MASK); for (auto i = 0u; i < latte::MaxRenderTargets; ++i) { auto targetMask = (cb_target_mask.value >> (i * 4)) & 0xF; auto cb_color_base = getRegister<latte::CB_COLORN_BASE>(latte::Register::CB_COLOR0_BASE + i * 4); auto cb_color_info = getRegister<latte::CB_COLORN_INFO>(latte::Register::CB_COLOR0_INFO + i * 4); if (!!targetMask && cb_color_base.BASE_256B() != 0) { desc.colorTargets[i] = RenderPassDesc::ColorTarget { true, cb_color_info.FORMAT(), cb_color_info.NUMBER_TYPE(), 1 }; } else { desc.colorTargets[i] = RenderPassDesc::ColorTarget { false, latte::CB_FORMAT::COLOR_INVALID, latte::CB_NUMBER_TYPE::UNORM, 0 }; } } auto db_depth_control = getRegister<latte::DB_DEPTH_CONTROL>(latte::Register::DB_DEPTH_CONTROL); auto zEnable = db_depth_control.Z_ENABLE(); auto stencilEnable = db_depth_control.STENCIL_ENABLE(); auto depthEnabled = zEnable || stencilEnable; auto db_depth_base = getRegister<latte::DB_DEPTH_BASE>(latte::Register::DB_DEPTH_BASE); auto db_depth_info = getRegister<latte::DB_DEPTH_INFO>(latte::Register::DB_DEPTH_INFO); if (depthEnabled && db_depth_base.BASE_256B() != 0) { desc.depthTarget = RenderPassDesc::DepthStencilTarget { true, db_depth_info.FORMAT() }; } else { desc.depthTarget = { false, latte::DB_FORMAT::DEPTH_INVALID }; } return desc; }
static void * nv30_zsa_state_create(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *cso) { struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; struct nv30_zsa_stateobj *so; so = CALLOC_STRUCT(nv30_zsa_stateobj); if (!so) return NULL; so->pipe = *cso; SB_MTHD30(so, DEPTH_FUNC, 3); SB_DATA (so, nvgl_comparison_op(cso->depth.func)); SB_DATA (so, cso->depth.writemask); SB_DATA (so, cso->depth.enabled); if (eng3d->oclass == NV35_3D_CLASS || eng3d->oclass >= NV40_3D_CLASS) { SB_MTHD35(so, DEPTH_BOUNDS_TEST_ENABLE, 3); SB_DATA (so, cso->depth.bounds_test); SB_DATA (so, fui(cso->depth.bounds_min)); SB_DATA (so, fui(cso->depth.bounds_max)); } if (cso->stencil[0].enabled) { SB_MTHD30(so, STENCIL_ENABLE(0), 3); SB_DATA (so, 1); SB_DATA (so, cso->stencil[0].writemask); SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); SB_MTHD30(so, STENCIL_FUNC_MASK(0), 4); SB_DATA (so, cso->stencil[0].valuemask); 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)); } else { SB_MTHD30(so, STENCIL_ENABLE(0), 2); SB_DATA (so, 0); SB_DATA (so, 0x000000ff); } if (cso->stencil[1].enabled) { SB_MTHD30(so, STENCIL_ENABLE(1), 3); SB_DATA (so, 1); SB_DATA (so, cso->stencil[1].writemask); SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); SB_MTHD30(so, STENCIL_FUNC_MASK(1), 4); SB_DATA (so, cso->stencil[1].valuemask); 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)); } else { SB_MTHD30(so, STENCIL_ENABLE(1), 1); SB_DATA (so, 0); } SB_MTHD30(so, ALPHA_FUNC_ENABLE, 3); SB_DATA (so, cso->alpha.enabled ? 1 : 0); SB_DATA (so, nvgl_comparison_op(cso->alpha.func)); SB_DATA (so, float_to_ubyte(cso->alpha.ref_value)); return so; }
static void nv30_transfer_rect_blit(XFER_ARGS) { struct nv04_resource *fp = nv30_transfer_rect_fragprog(nv30); struct nouveau_heap *vp = nv30_transfer_rect_vertprog(nv30); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_pushbuf_refn refs[] = { { fp->bo, fp->domain | NOUVEAU_BO_RD }, { src->bo, src->domain | NOUVEAU_BO_RD }, { dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR }, }; u32 texfmt, texswz; u32 format, stride; if (nouveau_pushbuf_space(push, 512, 8, 0) || nouveau_pushbuf_refn (push, refs, sizeof(refs) / sizeof(refs[0]))) return; /* various switches depending on cpp of the transfer */ switch (dst->cpp) { case 4: format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 | NV30_3D_RT_FORMAT_ZETA_Z24S8; texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8; texswz = 0x0000aae4; break; case 2: format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 | NV30_3D_RT_FORMAT_ZETA_Z16; texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5; texswz = 0x0000a9e4; break; case 1: format = NV30_3D_RT_FORMAT_COLOR_B8 | NV30_3D_RT_FORMAT_ZETA_Z16; texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8; texswz = 0x0000aaff; break; default: assert(0); return; } /* render target */ if (!dst->pitch) { format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; format |= util_logbase2(dst->w) << 16; format |= util_logbase2(dst->h) << 24; stride = 64; } else { format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; stride = dst->pitch; } BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2); PUSH_DATA (push, dst->w << 16); PUSH_DATA (push, dst->h << 16); BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5); PUSH_DATA (push, dst->w << 16); PUSH_DATA (push, dst->h << 16); PUSH_DATA (push, format); PUSH_DATA (push, stride); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); nv30->dirty |= NV30_NEW_FRAMEBUFFER; /* viewport state */ BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); nv30->dirty |= NV30_NEW_VIEWPORT; /* blend state */ BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1); PUSH_DATA (push, 0x01010101); nv30->dirty |= NV30_NEW_BLEND; /* depth-stencil-alpha state */ BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2); PUSH_DATA (push, 0); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1); PUSH_DATA (push, 0); nv30->dirty |= NV30_NEW_ZSA; /* rasterizer state */ BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1); PUSH_DATA (push, NV30_3D_SHADE_MODEL_FLAT); BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2); PUSH_DATA (push, NV30_3D_POLYGON_MODE_FRONT_FILL); PUSH_DATA (push, NV30_3D_POLYGON_MODE_BACK_FILL); BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FILL_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1); PUSH_DATA (push, 0); nv30->state.scissor_off = 0; nv30->dirty |= NV30_NEW_RASTERIZER; /* vertex program */ BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1); PUSH_DATA (push, vp->start); BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2); PUSH_DATA (push, 0x00000101); /* attrib: 0, 8 */ PUSH_DATA (push, 0x00004000); /* result: hpos, tex0 */ BEGIN_NV04(push, NV30_3D(ENGINE), 1); PUSH_DATA (push, 0x00000103); BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1); PUSH_DATA (push, 0x00000000); nv30->dirty |= NV30_NEW_VERTPROG; nv30->dirty |= NV30_NEW_CLIP; /* fragment program */ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_RELOC(push, fp->bo, fp->offset, fp->domain | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x02000000); nv30->state.fragprog = NULL; nv30->dirty |= NV30_NEW_FRAGPROG; /* texture */ texfmt |= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT; texfmt |= NV30_3D_TEX_FORMAT_NO_BORDER; texfmt |= NV40_3D_TEX_FORMAT_RECT; texfmt |= 0x00008000; if (src->d < 2) texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D; else texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D; if (src->pitch) texfmt |= NV40_3D_TEX_FORMAT_LINEAR; BEGIN_NV04(push, NV30_3D(TEX_OFFSET(0)), 8); PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, src->bo, texfmt, NOUVEAU_BO_OR, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE | NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE | NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE); PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE); PUSH_DATA (push, texswz); switch (filter) { case BILINEAR: PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR | NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000); break; default: PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST | NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000); break; } PUSH_DATA (push, (src->w << 16) | src->h); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV40_3D(TEX_SIZE1(0)), 1); PUSH_DATA (push, 0x00100000 | src->pitch); BEGIN_NV04(push, SUBC_3D(0x0b40), 1); PUSH_DATA (push, src->d < 2 ? 0x00000001 : 0x00000000); BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 1); nv30->fragprog.dirty_samplers |= 1; nv30->dirty |= NV30_NEW_FRAGTEX; /* blit! */ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (dst->x1 - dst->x0) << 16 | dst->x0); PUSH_DATA (push, (dst->y1 - dst->y0) << 16 | dst->y0); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_QUADS); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x0); PUSH_DATAf(push, src->y0); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y0 << 16) | dst->x0); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x1); PUSH_DATAf(push, src->y0); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y0 << 16) | dst->x1); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x1); PUSH_DATAf(push, src->y1); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y1 << 16) | dst->x1); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x0); PUSH_DATAf(push, src->y1); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y1 << 16) | dst->x0); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); }
bool GLDriver::checkActiveDepthBuffer() { auto db_depth_base = getRegister<latte::DB_DEPTH_BASE>(latte::Register::DB_DEPTH_BASE); auto db_depth_size = getRegister<latte::DB_DEPTH_SIZE>(latte::Register::DB_DEPTH_SIZE); auto db_depth_info = getRegister<latte::DB_DEPTH_INFO>(latte::Register::DB_DEPTH_INFO); auto db_depth_control = getRegister<latte::DB_DEPTH_CONTROL>(latte::Register::DB_DEPTH_CONTROL); auto format = db_depth_info.FORMAT(); auto z_enable = db_depth_control.Z_ENABLE(); auto stencil_enable = db_depth_control.STENCIL_ENABLE(); // We unbind the depth buffer whenever depth testing is disabled so a // size mismatch with color buffers doesn't clip render operations, but // we have to look up the surface regardless of whether depth testing // is enabled; if it's a combined depth/stencil format and stencil // testing is enabled, we still have to bind the buffer to the stencil // attachment. SurfaceBuffer *surface; if (db_depth_base.BASE_256B()) { surface = getDepthBuffer(db_depth_base, db_depth_size, db_depth_info, false); } else { surface = nullptr; } auto surfaceObject = surface ? surface->active->object : 0; if (format != latte::DB_FORMAT::DEPTH_8_24 && format != latte::DB_FORMAT::DEPTH_8_24_FLOAT && format != latte::DB_FORMAT::DEPTH_X8_24 && format != latte::DB_FORMAT::DEPTH_X8_24_FLOAT && format != latte::DB_FORMAT::DEPTH_X24_8_32_FLOAT) { // You cannot bind a stencil buffer if the framebuffer does not support it. stencil_enable = false; } if (surfaceObject != mDepthBufferCache.object || z_enable != mDepthBufferCache.depthBound || stencil_enable != mDepthBufferCache.stencilBound) { if (z_enable && stencil_enable) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_STENCIL_ATTACHMENT, surfaceObject, 0); } else if (!z_enable && !stencil_enable) { if (mDepthBufferCache.depthBound || mDepthBufferCache.stencilBound) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_STENCIL_ATTACHMENT, 0, 0); } } else if (z_enable) { decaf_check(!stencil_enable); if (mDepthBufferCache.stencilBound) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_STENCIL_ATTACHMENT, 0, 0); } gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, surfaceObject, 0); } else { decaf_check(!z_enable && stencil_enable); if (mDepthBufferCache.depthBound) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, 0, 0); } gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_STENCIL_ATTACHMENT, surfaceObject, 0); } mFramebufferChanged = true; mDepthBufferCache.object = surfaceObject; mDepthBufferCache.depthBound = z_enable; mDepthBufferCache.stencilBound = stencil_enable; } return true; }