void nv20_emit_framebuffer(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct nouveau_surface *s; unsigned rt_format = NV20_3D_RT_FORMAT_TYPE_LINEAR; unsigned rt_pitch = 0, zeta_pitch = 0; unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR; if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) return; PUSH_RESET(push, BUFCTX_FB); /* Render target */ if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; rt_format |= get_rt_format(s->format); rt_pitch = s->pitch; BEGIN_NV04(push, NV20_3D(COLOR_OFFSET), 1); PUSH_MTHDl(push, NV20_3D(COLOR_OFFSET), BUFCTX_FB, s->bo, 0, bo_flags); } /* depth/stencil */ if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { s = &to_nouveau_renderbuffer( fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; rt_format |= get_rt_format(s->format); zeta_pitch = s->pitch; BEGIN_NV04(push, NV20_3D(ZETA_OFFSET), 1); PUSH_MTHDl(push, NV20_3D(ZETA_OFFSET), BUFCTX_FB, s->bo, 0, bo_flags); if (context_chipset(ctx) >= 0x25) setup_hierz_buffer(ctx); } else { rt_format |= get_rt_format(MESA_FORMAT_S8_UINT_Z24_UNORM); zeta_pitch = rt_pitch; } BEGIN_NV04(push, NV20_3D(RT_FORMAT), 2); PUSH_DATA (push, rt_format); PUSH_DATA (push, zeta_pitch << 16 | rt_pitch); /* Recompute the viewport/scissor state. */ context_dirty(ctx, VIEWPORT); context_dirty(ctx, SCISSOR); context_dirty(ctx, DEPTH); }
static void nv30_draw_elements(struct nv30_context *nv30, boolean shorten, unsigned mode, unsigned start, unsigned count, unsigned instance_count, int32_t index_bias) { const unsigned index_size = nv30->idxbuf.index_size; struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; unsigned prim = nv30_prim_gl(mode); #if 0 /*XXX*/ if (index_bias != nv30->state.index_bias) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1); PUSH_DATA (push, index_bias); nv30->state.index_bias = index_bias; } #endif if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 && nv30->idxbuf.buffer) { struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer); unsigned offset = nv30->idxbuf.offset; assert(nouveau_resource_mapped_by_gpu(&res->base)); BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2); PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0); PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo, (index_size == 2) ? 0x00000010 : 0x00000000, res->domain | NOUVEAU_BO_RD, 0, NV30_3D_IDXBUF_FORMAT_DMA1); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, prim); while (count) { const unsigned mpush = 2047 * 256; unsigned npush = (count > mpush) ? mpush : count; unsigned wpush = ((npush + 255) & ~255) >> 8; count -= npush; BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush); while (npush >= 256) { PUSH_DATA (push, 0xff000000 | start); start += 256; npush -= 256; } if (npush) PUSH_DATA (push, ((npush - 1) << 24) | start); } BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_IDXBUF); } else {
Bool NV10EXAPrepareComposite(int op, PicturePtr pict_src, PicturePtr pict_mask, PicturePtr pict_dst, PixmapPtr src, PixmapPtr mask, PixmapPtr dst) { ScrnInfoPtr pScrn = xf86ScreenToScrn(dst->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t sc, sa, mc, ma; if (!PUSH_SPACE(push, 128)) return FALSE; PUSH_RESET(push); /* setup render target and blending */ if (!setup_render_target(pNv, pict_dst, dst)) return FALSE; setup_blend_function(pNv, pict_dst, op); /* select picture sources */ if (!setup_picture(pNv, pict_src, src, 0, &sc, &sa)) return FALSE; if (!setup_picture(pNv, pict_mask, mask, 1, &mc, &ma)) return FALSE; /* configure register combiners */ BEGIN_NV04(push, NV10_3D(RC_IN_ALPHA(0)), 1); PUSH_DATA (push, sa | ma); BEGIN_NV04(push, NV10_3D(RC_IN_RGB(0)), 1); if (effective_component_alpha(pict_mask)) { if (needs_src_alpha(op)) PUSH_DATA(push, sa | mc); else PUSH_DATA(push, sc | mc); } else { PUSH_DATA(push, sc | ma); } nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } pNv->pspict = pict_src; pNv->pmpict = pict_mask; return TRUE; }
void nv04_emit_framebuffer(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct nouveau_surface *s; uint32_t rt_format = NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_PITCH; uint32_t rt_pitch = 0, zeta_pitch = 0; unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR; if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) return; PUSH_RESET(push, BUFCTX_FB); /* Render target */ if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; rt_format |= get_rt_format(s->format); zeta_pitch = rt_pitch = s->pitch; BEGIN_NV04(push, NV04_SF3D(OFFSET_COLOR), 1); PUSH_MTHDl(push, NV04_SF3D(OFFSET_COLOR), BUFCTX_FB, s->bo, 0, bo_flags); } /* depth/stencil */ if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { s = &to_nouveau_renderbuffer( fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; zeta_pitch = s->pitch; BEGIN_NV04(push, NV04_SF3D(OFFSET_ZETA), 1); PUSH_MTHDl(push, NV04_SF3D(OFFSET_ZETA), BUFCTX_FB, s->bo, 0, bo_flags); } BEGIN_NV04(push, NV04_SF3D(FORMAT), 1); PUSH_DATA (push, rt_format); BEGIN_NV04(push, NV04_SF3D(PITCH), 1); PUSH_DATA (push, zeta_pitch << 16 | rt_pitch); /* Recompute the scissor state. */ context_dirty(ctx, SCISSOR); context_dirty(ctx, CONTROL); }
static void nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_fragprog *fp = hwcso; /* reset the bucftx so that we don't keep a dangling reference to the fp * code */ if (fp != nv30->state.fragprog) PUSH_RESET(nv30->base.pushbuf, BUFCTX_FRAGPROG); nv30->fragprog.program = fp; nv30->dirty |= NV30_NEW_FRAGPROG; }
static void nv30_render_draw_elements(struct vbuf_render *render, const ushort *indices, uint count) { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); for (i = 0; i < r->vertex_info.num_attribs; i++) { PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, nv04_resource(r->buffer), r->offset + r->vtxptr[i], NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } if (!nv30_state_validate(nv30, FALSE)) return; BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, r->prim); if (count & 1) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1); PUSH_DATA (push, *indices++); } count >>= 1; while (count) { unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); count -= npush; BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush); while (npush--) { PUSH_DATA(push, (indices[1] << 16) | indices[0]); indices += 2; } } BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_VTXTMP); }
static void nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr) { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned fn = nr >> 8, pn = nr & 0xff; unsigned ps = fn + (pn ? 1 : 0); unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); for (i = 0; i < r->vertex_info.num_attribs; i++) { PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, nv04_resource(r->buffer), r->offset + r->vtxptr[i], NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } if (!nv30_state_validate(nv30, FALSE)) return; BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, r->prim); BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps); while (fn--) { PUSH_DATA (push, 0xff000000 | start); start += 256; } if (pn) PUSH_DATA (push, ((pn - 1) << 24) | start); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_VTXTMP); }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV40_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t fragprog; if (!PUSH_SPACE(push, 128)) NOUVEAU_FALLBACK("space\n"); PUSH_RESET(push); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXAPicture(pNv, psPix, psPict, 0)) return FALSE; if (pmPict) { if (!NV40EXAPicture(pNv, pmPix, pmPict, 1)) return FALSE; if (pdPict->format == PICT_a8) { fragprog = PFP_C_A8; } else if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fragprog = PFP_CCASA; else fragprog = PFP_CCA; } else { fragprog = PFP_C; } } else { if (pdPict->format == PICT_a8) fragprog = PFP_S_A8; else fragprog = PFP_S; } BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, fragprog, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | 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); /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 2); BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 1); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }
void nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info) { struct push_context ctx; unsigned i, index_size; boolean apply_bias = info->indexed && info->index_bias; ctx.push = nv30->base.pushbuf; ctx.translate = nv30->vertex->translate; ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max; ctx.vertex_words = nv30->vertex->vtx_size; for (i = 0; i < nv30->num_vtxbufs; ++i) { uint8_t *data; struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i]; struct nv04_resource *res = nv04_resource(vb->buffer); if (!vb->buffer && !vb->user_buffer) { continue; } data = nouveau_resource_map_offset(&nv30->base, res, vb->buffer_offset, NOUVEAU_BO_RD); if (apply_bias) data += info->index_bias * vb->stride; ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0); } if (info->indexed) { if (nv30->idxbuf.buffer) ctx.idxbuf = nouveau_resource_map_offset(&nv30->base, nv04_resource(nv30->idxbuf.buffer), nv30->idxbuf.offset, NOUVEAU_BO_RD); else ctx.idxbuf = nv30->idxbuf.user_buffer; if (!ctx.idxbuf) { nv30_state_release(nv30); return; } index_size = nv30->idxbuf.index_size; ctx.primitive_restart = info->primitive_restart; ctx.restart_index = info->restart_index; } else { ctx.idxbuf = NULL; index_size = 0; ctx.primitive_restart = FALSE; ctx.restart_index = 0; } if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) { BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2); PUSH_DATA (ctx.push, info->primitive_restart); PUSH_DATA (ctx.push, info->restart_index); nv30->state.prim_restart = info->primitive_restart; } ctx.prim = nv30_prim_gl(info->mode); PUSH_RESET(ctx.push, BUFCTX_IDXBUF); BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (ctx.push, ctx.prim); switch (index_size) { case 0: emit_vertices_seq(&ctx, info->start, info->count); break; case 1: emit_vertices_i08(&ctx, info->start, info->count); break; case 2: emit_vertices_i16(&ctx, info->start, info->count); break; case 4: emit_vertices_i32(&ctx, info->start, info->count); break; default: assert(0); break; } BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP); if (info->indexed) nouveau_resource_unmap(nv04_resource(nv30->idxbuf.buffer)); for (i = 0; i < nv30->num_vtxbufs; ++i) { if (nv30->vtxbuf[i].buffer) { nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer)); } } nv30_state_release(nv30); }
void nv30_fragtex_validate(struct nv30_context *nv30) { struct pipe_screen *pscreen = &nv30->screen->base.base; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned dirty = nv30->fragprog.dirty_samplers; while (dirty) { unsigned unit = ffs(dirty) - 1; struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit]; struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit]; PUSH_RESET(push, BUFCTX_FRAGTEX(unit)); if (ss && sv) { const struct nv30_texfmt *fmt = nv30_texfmt(pscreen, sv->pipe.format); struct pipe_resource *pt = sv->pipe.texture; struct nv30_miptree *mt = nv30_miptree(pt); unsigned min_lod, max_lod; u32 filter = sv->filt | (ss->filt & sv->filt_mask); u32 format = sv->fmt | ss->fmt; u32 enable = ss->en; /* handle base_level when not using a mip filter, min/max level * is unfortunately ignored by the hardware otherwise */ if (ss->pipe.min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { if (sv->base_lod) filter += 0x00020000; /* N/L -> NMN/LMN */ max_lod = sv->base_lod; min_lod = sv->base_lod; } else { max_lod = MIN2(ss->max_lod + sv->base_lod, sv->high_lod); min_lod = MIN2(ss->min_lod + sv->base_lod, max_lod); } if (eng3d->oclass >= NV40_3D_CLASS) { /* this is a tad stupid of the hardware, but there's no non-rcomp * z16/z24 texture formats to be had, we have to suffer and lose * some precision to handle this case. */ if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) { if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z16) format |= NV40_3D_TEX_FORMAT_FORMAT_A8L8; else if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z24) format |= NV40_3D_TEX_FORMAT_FORMAT_A16L16; else format |= fmt->nv40; } else { format |= fmt->nv40; } enable |= (min_lod << 19) | (max_lod << 7); enable |= NV40_3D_TEX_ENABLE_ENABLE; BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1); PUSH_DATA (push, sv->npot_size1); } else { /* this is a tad stupid of the hardware, but there's no non-rcomp * z16/z24 texture formats to be had, we have to suffer and lose * some precision to handle this case. */ if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) { if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z16) { if (ss->pipe.normalized_coords) format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8; else format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT; } else if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z24) { if (ss->pipe.normalized_coords) format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16; else format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT; } else { if (ss->pipe.normalized_coords) format |= fmt->nv30; else format |= fmt->nv30_rect; } } else { if (ss->pipe.normalized_coords) format |= fmt->nv30; else format |= fmt->nv30_rect; } enable |= NV30_3D_TEX_ENABLE_ENABLE; enable |= (min_lod << 18) | (max_lod << 6); } BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8); PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), BUFCTX_FRAGTEX(unit), mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), BUFCTX_FRAGTEX(unit), mt->base.bo, format, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); PUSH_DATA (push, sv->wrap | (ss->wrap & sv->wrap_mask)); PUSH_DATA (push, enable); PUSH_DATA (push, sv->swz); PUSH_DATA (push, filter); PUSH_DATA (push, sv->npot_size0); PUSH_DATA (push, ss->bcol); BEGIN_NV04(push, NV30_3D(TEX_FILTER_OPTIMIZATION(unit)), 1); PUSH_DATA (push, nv30->config.filter); } else { BEGIN_NV04(push, NV30_3D(TEX_ENABLE(unit)), 1); PUSH_DATA (push, 0); } dirty &= ~(1 << unit); } nv30->fragprog.dirty_samplers = 0; }
void nv20_emit_tex_obj(struct gl_context *ctx, int emit) { const int i = emit - NOUVEAU_STATE_TEX_OBJ0; struct nouveau_pushbuf *push = context_push(ctx); const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM; struct gl_texture_object *t; struct nouveau_surface *s; struct gl_texture_image *ti; const struct gl_sampler_object *sa; uint32_t tx_format, tx_filter, tx_wrap, tx_enable; PUSH_RESET(push, BUFCTX_TEX(i)); if (!ctx->Texture.Unit[i]._ReallyEnabled) { BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); PUSH_DATA (push, 0); context_dirty(ctx, TEX_SHADER); return; } t = ctx->Texture.Unit[i]._Current; s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; ti = t->Image[0][t->BaseLevel]; sa = _mesa_get_samplerobj(ctx, i); if (!nouveau_texture_validate(ctx, t)) return; /* Recompute the texturing registers. */ tx_format = ti->DepthLog2 << 28 | ti->HeightLog2 << 24 | ti->WidthLog2 << 20 | NV20_3D_TEX_FORMAT_DIMS_2D | NV20_3D_TEX_FORMAT_NO_BORDER | 1 << 16; tx_wrap = nvgl_wrap_mode(sa->WrapR) << 16 | nvgl_wrap_mode(sa->WrapT) << 8 | nvgl_wrap_mode(sa->WrapS) << 0; tx_filter = nvgl_filter_mode(sa->MagFilter) << 24 | nvgl_filter_mode(sa->MinFilter) << 16 | 2 << 12; tx_enable = NV20_3D_TEX_ENABLE_ENABLE | log2i(sa->MaxAnisotropy) << 4; if (t->Target == GL_TEXTURE_RECTANGLE) { BEGIN_NV04(push, NV20_3D(TEX_NPOT_PITCH(i)), 1); PUSH_DATA (push, s->pitch << 16); BEGIN_NV04(push, NV20_3D(TEX_NPOT_SIZE(i)), 1); PUSH_DATA (push, s->width << 16 | s->height); tx_format |= get_tex_format_rect(ti); } else { tx_format |= get_tex_format_pot(ti); } if (sa->MinFilter != GL_NEAREST && sa->MinFilter != GL_LINEAR) { int lod_min = sa->MinLod; int lod_max = MIN2(sa->MaxLod, t->_MaxLambda); int lod_bias = sa->LodBias + ctx->Texture.Unit[i].LodBias; lod_max = CLAMP(lod_max, 0, 15); lod_min = CLAMP(lod_min, 0, 15); lod_bias = CLAMP(lod_bias, 0, 15); tx_format |= NV20_3D_TEX_FORMAT_MIPMAP; tx_filter |= lod_bias << 8; tx_enable |= lod_min << 26 | lod_max << 14; } /* Write it to the hardware. */ BEGIN_NV04(push, NV20_3D(TEX_FORMAT(i)), 1); PUSH_MTHD (push, NV20_3D(TEX_FORMAT(i)), BUFCTX_TEX(i), s->bo, tx_format, bo_flags | NOUVEAU_BO_OR, NV20_3D_TEX_FORMAT_DMA0, NV20_3D_TEX_FORMAT_DMA1); BEGIN_NV04(push, NV20_3D(TEX_OFFSET(i)), 1); PUSH_MTHDl(push, NV20_3D(TEX_OFFSET(i)), BUFCTX_TEX(i), s->bo, s->offset, bo_flags); BEGIN_NV04(push, NV20_3D(TEX_WRAP(i)), 1); PUSH_DATA (push, tx_wrap); BEGIN_NV04(push, NV20_3D(TEX_FILTER(i)), 1); PUSH_DATA (push, tx_filter); BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); PUSH_DATA (push, tx_enable); context_dirty(ctx, TEX_SHADER); }
Bool NV30EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV30_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t sc, sa, mc, ma, solid[2]; if (!PUSH_SPACE(push, 128)) return FALSE; PUSH_RESET(push); /* setup render target and blending */ if (!NV30_SetupSurface(pScrn, pdPix, pdPict)) return FALSE; NV30_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); /* select picture sources */ if (!NV30EXAPicture(pScrn, psPix, psPict, 0, &sc, &sa, &solid[0])) return FALSE; if (!NV30EXAPicture(pScrn, pmPix, pmPict, 1, &mc, &ma, &solid[1])) return FALSE; /* configure register combiners */ BEGIN_NV04(push, NV30_3D(RC_IN_ALPHA(0)), 6); PUSH_DATA (push, sa | ma); if (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) PUSH_DATA(push, sa | mc); else PUSH_DATA(push, sc | mc); } else { PUSH_DATA(push, sc | ma); } PUSH_DATA (push, solid[0]); PUSH_DATA (push, solid[1]); PUSH_DATA (push, 0x00000c00); PUSH_DATA (push, 0x00000c00); BEGIN_NV04(push, NV30_3D(RC_FINAL0), 3); if (pdPict->format != PICT_a8) PUSH_DATA (push, 0x0000000c); else PUSH_DATA (push, 0x0000001c); PUSH_DATA (push, 0x00001c00); PUSH_DATA (push, 0x01000101); /* select fragprog which just sources textures for combiners */ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, PFP_PASS, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1); PUSH_DATA (push, 0x0001000f); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1); PUSH_DATA (push, 3); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }
static void nv10_render_release_vertices(struct gl_context *ctx) { PUSH_RESET(context_push(ctx), BUFCTX_VTX); }
static void setup_hierz_buffer(struct gl_context *ctx) { struct nouveau_pushbuf *push = context_push(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); unsigned pitch = align(fb->Width, 128), height = align(fb->Height, 2), size = pitch * height; if (!nfb->hierz.bo || nfb->hierz.bo->size != size) { union nouveau_bo_config config = { .nv04.surf_flags = NV04_BO_ZETA, .nv04.surf_pitch = 0 }; nouveau_bo_ref(NULL, &nfb->hierz.bo); nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size, &config, &nfb->hierz.bo); } PUSH_SPACE(push, 11); BEGIN_NV04(push, NV17_3D(HIERZ_OFFSET), 1); PUSH_MTHDl(push, NV17_3D(HIERZ_OFFSET), BUFCTX_FB, nfb->hierz.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); BEGIN_NV04(push, NV17_3D(HIERZ_WINDOW_X), 4); PUSH_DATAf(push, - 1792); PUSH_DATAf(push, - 2304 + fb->Height); PUSH_DATAf(push, fb->_DepthMaxF / 2); PUSH_DATAf(push, 0); BEGIN_NV04(push, NV17_3D(HIERZ_PITCH), 1); PUSH_DATA (push, pitch); BEGIN_NV04(push, NV17_3D(HIERZ_ENABLE), 1); PUSH_DATA (push, 1); } void nv10_emit_framebuffer(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct nouveau_surface *s; unsigned rt_format = NV10_3D_RT_FORMAT_TYPE_LINEAR; unsigned rt_pitch = 0, zeta_pitch = 0; unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR; if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) return; PUSH_RESET(push, BUFCTX_FB); /* At least nv11 seems to get sad if we don't do this before * swapping RTs.*/ if (context_eng3d(ctx)->oclass < NV17_3D_CLASS) { int i; for (i = 0; i < 6; i++) { BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); PUSH_DATA (push, 0); } } /* Render target */ if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; rt_format |= get_rt_format(s->format); zeta_pitch = rt_pitch = s->pitch; BEGIN_NV04(push, NV10_3D(COLOR_OFFSET), 1); PUSH_MTHDl(push, NV10_3D(COLOR_OFFSET), BUFCTX_FB, s->bo, 0, bo_flags); } /* depth/stencil */ if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { s = &to_nouveau_renderbuffer( fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; rt_format |= get_rt_format(s->format); zeta_pitch = s->pitch; BEGIN_NV04(push, NV10_3D(ZETA_OFFSET), 1); PUSH_MTHDl(push, NV10_3D(ZETA_OFFSET), BUFCTX_FB, s->bo, 0, bo_flags); if (context_eng3d(ctx)->oclass >= NV17_3D_CLASS) { setup_hierz_buffer(ctx); context_dirty(ctx, ZCLEAR); } } BEGIN_NV04(push, NV10_3D(RT_FORMAT), 2); PUSH_DATA (push, rt_format); PUSH_DATA (push, zeta_pitch << 16 | rt_pitch); context_dirty(ctx, VIEWPORT); context_dirty(ctx, SCISSOR); context_dirty(ctx, DEPTH); } void nv10_emit_render_mode(struct gl_context *ctx, int emit) { } void nv10_emit_scissor(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); int x, y, w, h; get_scissors(ctx->DrawBuffer, &x, &y, &w, &h); BEGIN_NV04(push, NV10_3D(RT_HORIZ), 2); PUSH_DATA (push, w << 16 | x); PUSH_DATA (push, h << 16 | y); } void nv10_emit_viewport(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); struct gl_viewport_attrib *vp = &ctx->ViewportArray[0]; struct gl_framebuffer *fb = ctx->DrawBuffer; float a[4] = {}; get_viewport_translate(ctx, a); a[0] -= 2048; a[1] -= 2048; if (nv10_use_viewport_zclear(ctx)) a[2] = nv10_transform_depth(ctx, (vp->Far + vp->Near) / 2); BEGIN_NV04(push, NV10_3D(VIEWPORT_TRANSLATE_X), 4); PUSH_DATAp(push, a, 4); BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_HORIZ(0)), 1); PUSH_DATA (push, (fb->Width - 1) << 16 | 0x08000800); BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_VERT(0)), 1); PUSH_DATA (push, (fb->Height - 1) << 16 | 0x08000800); context_dirty(ctx, PROJECTION); } void nv10_emit_zclear(struct gl_context *ctx, int emit) { struct nouveau_context *nctx = to_nouveau_context(ctx); struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(ctx->DrawBuffer); if (nfb->hierz.bo) { BEGIN_NV04(push, NV17_3D(ZCLEAR_ENABLE), 2); PUSH_DATAb(push, !nctx->hierz.clear_blocked); PUSH_DATA (push, nfb->hierz.clear_value | (nctx->hierz.clear_seq & 0xff)); } else { BEGIN_NV04(push, NV10_3D(DEPTH_RANGE_NEAR), 2); PUSH_DATAf(push, nv10_transform_depth(ctx, 0)); PUSH_DATAf(push, nv10_transform_depth(ctx, 1)); context_dirty(ctx, VIEWPORT); } }
void nv30_fragprog_validate(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nv30_fragprog *fp = nv30->fragprog.program; bool upload = false; int i; if (!fp->translated) { _nvfx_fragprog_translate(eng3d->oclass, fp); if (!fp->translated) return; upload = true; } /* update constants, also needs to be done on every fp switch as we * have no idea whether the constbuf changed in the meantime */ if (nv30->fragprog.constbuf) { struct pipe_resource *constbuf = nv30->fragprog.constbuf; uint32_t *cbuf = (uint32_t *)nv04_resource(constbuf)->data; for (i = 0; i < fp->nr_consts; i++) { unsigned off = fp->consts[i].offset; unsigned idx = fp->consts[i].index * 4; if (!memcmp(&fp->insn[off], &cbuf[idx], 4 * 4)) continue; memcpy(&fp->insn[off], &cbuf[idx], 4 * 4); upload = true; } } if (upload) nv30_fragprog_upload(nv30); /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts * were updated. TEX_CACHE_CTL magic is not enough to convince the * GPU that it should re-read the fragprog from VRAM... sigh. */ if (nv30->state.fragprog != fp || upload) { struct nv04_resource *r = nv04_resource(fp->buffer); if (!PUSH_SPACE(push, 8)) return; PUSH_RESET(push, BUFCTX_FRAGPROG); BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_RESRC(push, NV30_3D(FP_ACTIVE_PROGRAM), BUFCTX_FRAGPROG, r, 0, NOUVEAU_BO_LOW | NOUVEAU_BO_RD | 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, fp->fp_control); if (eng3d->oclass < NV40_3D_CLASS) { BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1); PUSH_DATA (push, 0x00010004); BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1); PUSH_DATA (push, fp->texcoords); } else { BEGIN_NV04(push, SUBC_3D(0x0b40), 1); PUSH_DATA (push, 0x00000000); } nv30->state.fragprog = fp; } }