static void nv30_draw_arrays(struct nv30_context *nv30, unsigned mode, unsigned start, unsigned count, unsigned instance_count) { struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned prim; prim = nv30_prim_gl(mode); 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_VERTEX_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); }
static void nouveau_vpe_fini(struct nouveau_decoder *dec) { struct nouveau_pushbuf *push = dec->push; if (!dec->cmds) return; nouveau_pushbuf_space(push, 16, 2, 0); nouveau_bufctx_reset(dec->bufctx, NV31_VIDEO_BIND_CMD); #define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_CMD, NOUVEAU_BO_RD BEGIN_NV04(push, NV31_MPEG(CMD_OFFSET), 2); PUSH_MTHDl(push, NV31_MPEG(CMD_OFFSET), dec->cmd_bo, 0, BCTX_ARGS); PUSH_DATA (push, dec->ofs * 4); BEGIN_NV04(push, NV31_MPEG(DATA_OFFSET), 2); PUSH_MTHDl(push, NV31_MPEG(DATA_OFFSET), dec->data_bo, 0, BCTX_ARGS); PUSH_DATA (push, dec->data_pos * 4); #undef BCTX_ARGS if (unlikely(nouveau_pushbuf_validate(dec->push))) return; BEGIN_NV04(push, NV31_MPEG(EXEC), 1); PUSH_DATA (push, 1); nouveau_vpe_synch(dec); dec->ofs = dec->data_pos = dec->num_surfaces = 0; dec->cmds = dec->data = NULL; dec->current = dec->future = dec->past = 8; }
static void setup_blend_function(NVPtr pNv, PicturePtr pdpict, int alu) { struct nouveau_pushbuf *push = pNv->pushbuf; struct pict_op *op = &nv10_pict_op[alu]; int src_factor = op->src; int dst_factor = op->dst; if (src_factor == SF(ONE_MINUS_DST_ALPHA) && !PICT_FORMAT_A(pdpict->format)) /* ONE_MINUS_DST_ALPHA doesn't always do the right thing for * framebuffers without alpha channel. But it's the same as * ZERO in that case. */ src_factor = SF(ZERO); if (effective_component_alpha(pNv->pmpict)) { if (dst_factor == DF(SRC_ALPHA)) dst_factor = DF(SRC_COLOR); else if (dst_factor == DF(ONE_MINUS_SRC_ALPHA)) dst_factor = DF(ONE_MINUS_SRC_COLOR); } BEGIN_NV04(push, NV10_3D(BLEND_FUNC_SRC), 2); PUSH_DATA (push, src_factor); PUSH_DATA (push, dst_factor); BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1); PUSH_DATA (push, 1); }
static void nv17_zclear(struct gl_context *ctx, GLbitfield *buffers) { struct nouveau_context *nctx = to_nouveau_context(ctx); struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_framebuffer *nfb = to_nouveau_framebuffer( ctx->DrawBuffer); struct nouveau_surface *s = &to_nouveau_renderbuffer( nfb->base.Attachment[BUFFER_DEPTH].Renderbuffer)->surface; /* Clear the hierarchical depth buffer */ BEGIN_NV04(push, NV17_3D(HIERZ_FILL_VALUE), 1); PUSH_DATA (push, pack_zs_f(s->format, ctx->Depth.Clear, 0)); BEGIN_NV04(push, NV17_3D(HIERZ_BUFFER_CLEAR), 1); PUSH_DATA (push, 1); /* Mark the depth buffer as cleared */ if (use_fast_zclear(ctx, *buffers)) { if (nctx->hierz.clear_seq) *buffers &= ~BUFFER_BIT_DEPTH; nfb->hierz.clear_value = pack_zs_f(s->format, ctx->Depth.Clear, 0); nctx->hierz.clear_seq++; context_dirty(ctx, ZCLEAR); } }
static void nv50_dac_disconnect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; struct nouveau_channel *evo = nv50_display(dev)->master; int ret; if (!nv_encoder->crtc) return; nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); ret = RING_SPACE(evo, 4); if (ret) { NV_ERROR(dev, "no space while disconnecting DAC\n"); return; } BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); OUT_RING (evo, 0); BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); OUT_RING (evo, 0); nv_encoder->crtc = NULL; }
void NV10EXAComposite(PixmapPtr pix_dst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height) { ScrnInfoPtr pScrn = xf86Screens[pix_dst->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; PicturePtr mask = pNv->pmpict, src = pNv->pspict; PictVector dstq[4] = QUAD(dstX, dstY, width, height), maskq[4] = QUAD(maskX, maskY, width, height), srcq[4] = QUAD(srcX, srcY, width, height); MAP(transform_vertex, src->transform, srcq); if (mask) MAP(transform_vertex, mask->transform, maskq); WAIT_RING (chan, 64); BEGIN_NV04(chan, NV10_3D(VERTEX_BEGIN_END), 1); OUT_RING (chan, NV10_3D_VERTEX_BEGIN_END_QUADS); MAP(emit_vertex, pNv, dstq, srcq, mask ? maskq : NULL); BEGIN_NV04(chan, NV10_3D(VERTEX_BEGIN_END), 1); OUT_RING (chan, NV10_3D_VERTEX_BEGIN_END_STOP); }
static void nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); struct nouveau_pushbuf *push = nv30->base.pushbuf; switch (q->type) { case PIPE_QUERY_TIME_ELAPSED: q->qo[0] = nv30_query_object_new(nv30->screen); if (q->qo[0]) { BEGIN_NV04(push, NV30_3D(QUERY_GET), 1); PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start); } break; case PIPE_QUERY_TIMESTAMP: return; default: BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1); PUSH_DATA (push, q->report); break; } if (q->enable) { BEGIN_NV04(push, SUBC_3D(q->enable), 1); PUSH_DATA (push, 1); } }
static void nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) { struct drm_device *dev = nv_crtc->base.dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; int ret; NV_DEBUG(drm, "\n"); if (update && !nv_crtc->cursor.visible) return; ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); if (ret) { NV_ERROR(drm, "no space while hiding cursor\n"); return; } BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE); OUT_RING(evo, 0); if (nv_device(drm->device)->chipset != 0x50) { BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE); } if (update) { BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); OUT_RING(evo, 0); FIRE_RING(evo); nv_crtc->cursor.visible = false; } }
/* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */ static Bool NVAccelInitContextSurfaces(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; uint32_t class; class = (pNv->Architecture >= NV_ARCH_10) ? NV10_SURFACE_2D_CLASS : NV04_SURFACE_2D_CLASS; if (!pNv->NvContextSurfaces) { if (nouveau_grobj_alloc(chan, NvContextSurfaces, class, &pNv->NvContextSurfaces)) return FALSE; } BEGIN_NV04(chan, NV01_SUBC(SF2D, OBJECT), 1); OUT_RING (chan, pNv->NvContextSurfaces->handle); BEGIN_NV04(chan, NV04_SF2D(DMA_NOTIFY), 1); OUT_RING (chan, chan->nullobj->handle); BEGIN_NV04(chan, NV04_SF2D(DMA_IMAGE_SOURCE), 2); OUT_RING (chan, pNv->chan->vram->handle); OUT_RING (chan, pNv->chan->vram->handle); return TRUE; }
static Bool NVAccelInitImagePattern(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; if (!pNv->NvImagePattern) { if (nouveau_grobj_alloc(chan, NvImagePattern, NV04_PATTERN_CLASS, &pNv->NvImagePattern)) return FALSE; } BEGIN_NV04(chan, NV01_SUBC(MISC, OBJECT), 1); OUT_RING (chan, pNv->NvImagePattern->handle); BEGIN_NV04(chan, NV01_PATT(DMA_NOTIFY), 1); OUT_RING (chan, chan->nullobj->handle); BEGIN_NV04(chan, NV01_PATT(MONOCHROME_FORMAT), 3); #if X_BYTE_ORDER == X_BIG_ENDIAN OUT_RING (chan, NV01_PATTERN_MONOCHROME_FORMAT_LE); #else OUT_RING (chan, NV01_PATTERN_MONOCHROME_FORMAT_CGA6); #endif OUT_RING (chan, NV01_PATTERN_MONOCHROME_SHAPE_8X8); OUT_RING (chan, NV04_PATTERN_PATTERN_SELECT_MONO); return TRUE; }
void nv50_vertprog_validate(struct nv50_context *nv50) { struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_program *vp = nv50->vertprog; if (!nv50_program_validate(nv50, vp)) return; nv50_program_update_context_state(nv50, vp, 0); BEGIN_NV04(push, NV50_3D(VP_ATTR_EN(0)), 2); PUSH_DATA (push, vp->vp.attrs[0]); PUSH_DATA (push, vp->vp.attrs[1]); BEGIN_NV04(push, NV50_3D(VP_REG_ALLOC_RESULT), 1); PUSH_DATA (push, vp->max_out); BEGIN_NV04(push, NV50_3D(VP_REG_ALLOC_TEMP), 1); PUSH_DATA (push, vp->max_gpr); BEGIN_NV04(push, NV50_3D(VP_START_ID), 1); PUSH_DATA (push, vp->code_base); if (unlikely(nv50->state.vport_bypass != vp->vp.vport_bypass)) { nv50->state.vport_bypass = vp->vp.vport_bypass; BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1); PUSH_DATA (push, !vp->vp.vport_bypass); /* TODO: don't do these twice if the vport changed, too: */ nv50_validate_viewport(nv50); #ifdef NV50_SCISSORS_CLIPPING nv50_validate_scissor(nv50); #endif } }
void NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; int crtcs; if (!nouveau_exa_pixmap_is_onscreen(ppix)) return; crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); if (!crtcs) return; BEGIN_NV04(chan, SUBC_BLIT(0x0000012C), 1); OUT_RING (chan, 0); BEGIN_NV04(chan, SUBC_BLIT(0x00000134), 1); OUT_RING (chan, ffs(crtcs) - 1); BEGIN_NV04(chan, SUBC_BLIT(0x00000100), 1); OUT_RING (chan, 0); BEGIN_NV04(chan, SUBC_BLIT(0x00000130), 1); OUT_RING (chan, 0); }
void nv20_emit_tex_gen(struct gl_context *ctx, int emit) { const int i = emit - NOUVEAU_STATE_TEX_GEN0; struct nouveau_context *nctx = to_nouveau_context(ctx); struct nouveau_pushbuf *push = context_push(ctx); struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; int j; for (j = 0; j < 4; j++) { if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { struct gl_texgen *coord = get_texgen_coord(unit, j); float *k = get_texgen_coeff(coord); if (k) { BEGIN_NV04(push, NV20_3D(TEX_GEN_COEFF(i, j)), 4); PUSH_DATAp(push, k, 4); } BEGIN_NV04(push, NV20_3D(TEX_GEN_MODE(i, j)), 1); PUSH_DATA (push, nvgl_texgen_mode(coord->Mode)); } else { BEGIN_NV04(push, NV20_3D(TEX_GEN_MODE(i, j)), 1); PUSH_DATA (push, 0); } } }
void NV40EXAComposite(PixmapPtr pdPix, int sx, int sy, int mx, int my, int dx, int dy, int w, int h) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; if (!PUSH_SPACE(push, 64)) return; /* We're drawing a triangle, we need to scissor it to a quad. */ /* The scissors are here for a good reason, we don't get the full * image, but just a part. */ /* Handling the cliprects is done for us already. */ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (w << 16) | dx); PUSH_DATA (push, (h << 16) | dy); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_TRIANGLES); PUSH_VTX2s(push, sx, sy + (h * 2), mx, my + (h * 2), dx, dy + (h * 2)); PUSH_VTX2s(push, sx, sy, mx, my, dx, dy); PUSH_VTX2s(push, sx + (w * 2), sy, mx + (w * 2), my, dx + (w * 2), dy); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); }
static void nv50_render_condition(struct pipe_context *pipe, struct pipe_query *pq, boolean condition, uint mode) { struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_query *q; nv50->cond_query = pq; nv50->cond_cond = condition; nv50->cond_mode = mode; PUSH_SPACE(push, 6); if (!pq) { BEGIN_NV04(push, NV50_3D(COND_MODE), 1); PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS); return; } q = nv50_query(pq); if (mode == PIPE_RENDER_COND_WAIT || mode == PIPE_RENDER_COND_BY_REGION_WAIT) { BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1); PUSH_DATA (push, 0); } BEGIN_NV04(push, NV50_3D(COND_ADDRESS_HIGH), 3); PUSH_DATAh(push, q->bo->offset + q->offset); PUSH_DATA (push, q->bo->offset + q->offset); PUSH_DATA (push, NV50_3D_COND_MODE_RES_NON_ZERO); }
static void nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) { struct nv50_screen *screen = nv50->screen; struct nouveau_pushbuf *push = screen->base.pushbuf; unsigned size = align(nv50->compprog->parm_size, 0x4); BEGIN_NV04(push, NV50_COMPUTE(USER_PARAM_COUNT), 1); PUSH_DATA (push, (size / 4) << 8); if (size) { struct nouveau_mm_allocation *mm; struct nouveau_bo *bo = NULL; unsigned offset; mm = nouveau_mm_allocate(screen->base.mm_GART, size, &bo, &offset); assert(mm); nouveau_bo_map(bo, 0, screen->base.client); memcpy(bo->map + offset, input, size); nouveau_bufctx_refn(nv50->bufctx, 0, bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); nouveau_pushbuf_bufctx(push, nv50->bufctx); nouveau_pushbuf_validate(push); BEGIN_NV04(push, NV50_COMPUTE(USER_PARAM(0)), size / 4); nouveau_pushbuf_data(push, bo, offset, size); nouveau_fence_work(screen->base.fence.current, nouveau_mm_free_work, mm); nouveau_bo_ref(NULL, &bo); nouveau_bufctx_reset(nv50->bufctx, 0); } }
static void nv40_query_render_condition(struct pipe_context *pipe, struct pipe_query *pq, boolean condition, enum pipe_render_cond_flag mode) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); struct nouveau_pushbuf *push = nv30->base.pushbuf; nv30->render_cond_query = pq; nv30->render_cond_mode = mode; nv30->render_cond_cond = condition; if (!pq) { BEGIN_NV04(push, SUBC_3D(0x1e98), 1); PUSH_DATA (push, 0x01000000); return; } if (mode == PIPE_RENDER_COND_WAIT || mode == PIPE_RENDER_COND_BY_REGION_WAIT) { BEGIN_NV04(push, SUBC_3D(0x0110), 1); PUSH_DATA (push, 0); } BEGIN_NV04(push, SUBC_3D(0x1e98), 1); PUSH_DATA (push, 0x02000000 | q->qo[1]->hw->start); }
void nv50_gmtyprog_validate(struct nv50_context *nv50) { struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_program *gp = nv50->gmtyprog; if (gp) { if (!nv50_program_validate(nv50, gp)) return; BEGIN_NV04(push, NV50_3D(GP_REG_ALLOC_TEMP), 1); PUSH_DATA (push, gp->max_gpr); BEGIN_NV04(push, NV50_3D(GP_REG_ALLOC_RESULT), 1); PUSH_DATA (push, gp->max_out); BEGIN_NV04(push, NV50_3D(GP_OUTPUT_PRIMITIVE_TYPE), 1); PUSH_DATA (push, gp->gp.prim_type); BEGIN_NV04(push, NV50_3D(GP_VERTEX_OUTPUT_COUNT), 1); PUSH_DATA (push, gp->gp.vert_count); BEGIN_NV04(push, NV50_3D(GP_START_ID), 1); PUSH_DATA (push, gp->code_base); nv50->state.prim_size = gp->gp.prim_type; /* enum matches vertex count */ } nv50_program_update_context_state(nv50, gp, 2); /* GP_ENABLE is updated in linkage validation */ }
static void nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_query *q = nv50_query(pq); /* For occlusion queries we have to change the storage, because a previous * query might set the initial render conition to FALSE even *after* we re- * initialized it to TRUE. */ if (q->type == PIPE_QUERY_OCCLUSION_COUNTER) { q->offset += 16; q->data += 16 / sizeof(*q->data); if (q->offset - q->base == NV50_QUERY_ALLOC_SPACE) nv50_query_allocate(nv50, q, NV50_QUERY_ALLOC_SPACE); /* XXX: can we do this with the GPU, and sync with respect to a previous * query ? */ q->data[1] = 1; /* initial render condition = TRUE */ } if (!q->is64bit) q->data[0] = q->sequence++; /* the previously used one */ switch (q->type) { case PIPE_QUERY_OCCLUSION_COUNTER: PUSH_SPACE(push, 4); BEGIN_NV04(push, NV50_3D(COUNTER_RESET), 1); PUSH_DATA (push, NV50_3D_COUNTER_RESET_SAMPLECNT); BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1); PUSH_DATA (push, 1); break; case PIPE_QUERY_PRIMITIVES_GENERATED: /* store before & after instead ? */ PUSH_SPACE(push, 2); BEGIN_NV04(push, NV50_3D(COUNTER_RESET), 1); PUSH_DATA (push, NV50_3D_COUNTER_RESET_GENERATED_PRIMITIVES); break; case PIPE_QUERY_PRIMITIVES_EMITTED: PUSH_SPACE(push, 2); BEGIN_NV04(push, NV50_3D(COUNTER_RESET), 1); PUSH_DATA (push, NV50_3D_COUNTER_RESET_TRANSFORM_FEEDBACK); break; case PIPE_QUERY_SO_STATISTICS: PUSH_SPACE(push, 3); BEGIN_NI04(push, NV50_3D(COUNTER_RESET), 2); PUSH_DATA (push, NV50_3D_COUNTER_RESET_TRANSFORM_FEEDBACK); PUSH_DATA (push, NV50_3D_COUNTER_RESET_GENERATED_PRIMITIVES); break; case PIPE_QUERY_TIMESTAMP_DISJOINT: case PIPE_QUERY_TIME_ELAPSED: nv50_query_get(push, q, 0x10, 0x00005002); break; default: break; } q->ready = FALSE; }
static void nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, const union pipe_color_union *color, unsigned x, unsigned y, unsigned w, unsigned h) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_surface *sf = nv30_surface(ps); struct nv30_miptree *mt = nv30_miptree(ps->texture); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nouveau_pushbuf_refn refn; uint32_t rt_format; rt_format = nv30_format(pipe->screen, ps->format)->hw; if (util_format_get_blocksize(ps->format) == 4) rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8; else rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16; if (nv30_miptree(ps->texture)->swizzled) { rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; rt_format |= util_logbase2(sf->width) << 16; rt_format |= util_logbase2(sf->height) << 24; } else { rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; } refn.bo = mt->base.bo; refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; if (nouveau_pushbuf_space(push, 16, 1, 0) || nouveau_pushbuf_refn (push, &refn, 1)) return; BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); PUSH_DATA (push, sf->width << 16); PUSH_DATA (push, sf->height << 16); PUSH_DATA (push, rt_format); BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2); if (eng3d->oclass < NV40_3D_CLASS) PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); else PUSH_DATA (push, sf->pitch); PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (w << 16) | x); PUSH_DATA (push, (h << 16) | y); BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2); PUSH_DATA (push, pack_rgba(ps->format, color->f)); PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R | NV30_3D_CLEAR_BUFFERS_COLOR_G | NV30_3D_CLEAR_BUFFERS_COLOR_B | NV30_3D_CLEAR_BUFFERS_COLOR_A); nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; }
static void nv20_clear(struct gl_context *ctx, GLbitfield buffers) { struct nouveau_context *nctx = to_nouveau_context(ctx); struct nouveau_pushbuf *push = context_push(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; uint32_t clear = 0; nouveau_validate_framebuffer(ctx); nouveau_pushbuf_bufctx(push, nctx->hw.bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return; } if (buffers & BUFFER_BITS_COLOR) { struct nouveau_surface *s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; if (ctx->Color.ColorMask[0][RCOMP]) clear |= NV20_3D_CLEAR_BUFFERS_COLOR_R; if (ctx->Color.ColorMask[0][GCOMP]) clear |= NV20_3D_CLEAR_BUFFERS_COLOR_G; if (ctx->Color.ColorMask[0][BCOMP]) clear |= NV20_3D_CLEAR_BUFFERS_COLOR_B; if (ctx->Color.ColorMask[0][ACOMP]) clear |= NV20_3D_CLEAR_BUFFERS_COLOR_A; BEGIN_NV04(push, NV20_3D(CLEAR_VALUE), 1); PUSH_DATA (push, pack_rgba_clamp_f(s->format, ctx->Color.ClearColor.f)); buffers &= ~BUFFER_BITS_COLOR; } if (buffers & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) { struct nouveau_surface *s = &to_nouveau_renderbuffer( fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; if (buffers & BUFFER_BIT_DEPTH && ctx->Depth.Mask) clear |= NV20_3D_CLEAR_BUFFERS_DEPTH; if (buffers & BUFFER_BIT_STENCIL && ctx->Stencil.WriteMask[0]) clear |= NV20_3D_CLEAR_BUFFERS_STENCIL; BEGIN_NV04(push, NV20_3D(CLEAR_DEPTH_VALUE), 1); PUSH_DATA (push, pack_zs_f(s->format, ctx->Depth.Clear, ctx->Stencil.Clear)); buffers &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); } BEGIN_NV04(push, NV20_3D(CLEAR_BUFFERS), 1); PUSH_DATA (push, clear); nouveau_pushbuf_bufctx(push, NULL); nouveau_clear(ctx, buffers); }
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 nv50_texture_barrier(struct pipe_context *pipe) { struct nouveau_pushbuf *push = nv50_context(pipe)->base.pushbuf; BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 0x20); }
static __inline__ void PUSH_VTX2s(struct nouveau_pushbuf *push, int x1, int y1, int x2, int y2, int dx, int dy) { BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(8)), 2); PUSH_DATA (push, ((y1 & 0xffff) << 16) | (x1 & 0xffff)); PUSH_DATA (push, ((y2 & 0xffff) << 16) | (x2 & 0xffff)); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, ((dy & 0xffff) << 16) | (dx & 0xffff)); }
static __inline__ void PUSH_VTX2s(struct nouveau_pushbuf *push, int x1, int y1, int x2, int y2, int dx, int dy) { BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(8)), 2); PUSH_DATA (push, (y1 << 16) | x1); PUSH_DATA (push, (y2 << 16) | x2); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dy << 16) | dx); }
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 {
static void nv50_sprite_coords_validate(struct nv50_context *nv50) { struct nouveau_pushbuf *push = nv50->base.pushbuf; uint32_t pntc[8], mode; struct nv50_program *fp = nv50->fragprog; unsigned i, c; unsigned m = (nv50->state.interpolant_ctrl >> 8) & 0xff; if (!nv50->rast->pipe.point_quad_rasterization) { if (nv50->state.point_sprite) { BEGIN_NV04(push, NV50_3D(POINT_COORD_REPLACE_MAP(0)), 8); for (i = 0; i < 8; ++i) PUSH_DATA(push, 0); nv50->state.point_sprite = FALSE; } return; } else { nv50->state.point_sprite = TRUE; } memset(pntc, 0, sizeof(pntc)); for (i = 0; i < fp->in_nr; i++) { unsigned n = util_bitcount(fp->in[i].mask); if (fp->in[i].sn != TGSI_SEMANTIC_GENERIC) { m += n; continue; } if (!(nv50->rast->pipe.sprite_coord_enable & (1 << fp->in[i].si))) { m += n; continue; } for (c = 0; c < 4; ++c) { if (fp->in[i].mask & (1 << c)) { pntc[m / 8] |= (c + 1) << ((m % 8) * 4); ++m; } } } if (nv50->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) mode = 0x00; else mode = 0x10; BEGIN_NV04(push, NV50_3D(POINT_SPRITE_CTRL), 1); PUSH_DATA (push, mode); BEGIN_NV04(push, NV50_3D(POINT_COORD_REPLACE_MAP(0)), 8); PUSH_DATAp(push, pntc, 8); }
void nv10_emit_blend_equation(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1); PUSH_DATAb(push, ctx->Color.BlendEnabled); BEGIN_NV04(push, NV10_3D(BLEND_EQUATION), 1); PUSH_DATA (push, nvgl_blend_eqn(ctx->Color.Blend[0].EquationRGB)); }
void nv10_emit_depth(struct gl_context *ctx, int emit) { struct nouveau_pushbuf *push = context_push(ctx); BEGIN_NV04(push, NV10_3D(DEPTH_TEST_ENABLE), 1); PUSH_DATAb(push, ctx->Depth.Test); BEGIN_NV04(push, NV10_3D(DEPTH_WRITE_ENABLE), 1); PUSH_DATAb(push, ctx->Depth.Mask); BEGIN_NV04(push, NV10_3D(DEPTH_FUNC), 1); PUSH_DATA (push, nvgl_comparison_op(ctx->Depth.Func)); }
static int nv50_2d_texture_do_copy(struct nouveau_pushbuf *push, struct nv50_miptree *dst, unsigned dst_level, unsigned dx, unsigned dy, unsigned dz, struct nv50_miptree *src, unsigned src_level, unsigned sx, unsigned sy, unsigned sz, unsigned w, unsigned h) { static const uint32_t duvdxy[5] = { 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004 }; int ret; uint32_t ctrl; #if 0 ret = MARK_RING(chan, 2 * 16 + 32, 4); if (ret) return ret; #endif ret = nv50_2d_texture_set(push, 1, dst, dst_level, dz); if (ret) return ret; ret = nv50_2d_texture_set(push, 0, src, src_level, sz); if (ret) return ret; /* NOTE: 2D engine doesn't work for MS8 */ if (src->ms_x) ctrl = 0x11; /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */ BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1); PUSH_DATA (push, ctrl); BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 4); PUSH_DATA (push, dx << dst->ms_x); PUSH_DATA (push, dy << dst->ms_y); PUSH_DATA (push, w << dst->ms_x); PUSH_DATA (push, h << dst->ms_y); BEGIN_NV04(push, NV50_2D(BLIT_DU_DX_FRACT), 4); PUSH_DATA (push, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000); PUSH_DATA (push, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f); PUSH_DATA (push, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000); PUSH_DATA (push, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f); BEGIN_NV04(push, NV50_2D(BLIT_SRC_X_FRACT), 4); PUSH_DATA (push, 0); PUSH_DATA (push, sx << src->ms_x); PUSH_DATA (push, 0); PUSH_DATA (push, sy << src->ms_y); return 0; }