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 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; }
void nvc0_query_pushbuf_submit(struct nouveau_pushbuf *push, struct pipe_query *pq, unsigned result_offset) { struct nvc0_query *q = nvc0_query(pq); #define NVC0_IB_ENTRY_1_NO_PREFETCH (1 << (31 - 8)) nouveau_pushbuf_space(push, 0, 0, 1); nouveau_pushbuf_data(push, q->bo, q->offset + result_offset, 4 | NVC0_IB_ENTRY_1_NO_PREFETCH); }
void nv50_query_pushbuf_submit(struct nouveau_pushbuf *push, struct pipe_query *pq, unsigned result_offset) { struct nv50_query *q = nv50_query(pq); /* XXX: does this exist ? */ #define NV50_IB_ENTRY_1_NO_PREFETCH (0 << (31 - 8)) nouveau_pushbuf_space(push, 0, 0, 1); nouveau_pushbuf_data(push, q->bo, q->offset + result_offset, 4 | NV50_IB_ENTRY_1_NO_PREFETCH); }
static void nv30_transfer_rect_m2mf(XFER_ARGS) { struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_pushbuf_refn refs[] = { { src->bo, src->domain | NOUVEAU_BO_RD }, { dst->bo, dst->domain | NOUVEAU_BO_WR }, }; struct nv04_fifo *fifo = push->channel->data; unsigned src_offset = src->offset; unsigned dst_offset = dst->offset; unsigned w = dst->x1 - dst->x0; unsigned h = dst->y1 - dst->y0; src_offset += (src->y0 * src->pitch) + (src->x0 * src->cpp); dst_offset += (dst->y0 * dst->pitch) + (dst->x0 * dst->cpp); BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2); PUSH_DATA (push, (src->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart); PUSH_DATA (push, (dst->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart); while (h) { unsigned lines = (h > 2047) ? 2047 : h; if (nouveau_pushbuf_space(push, 13, 2, 0) || nouveau_pushbuf_refn (push, refs, 2)) return; BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); PUSH_RELOC(push, src->bo, src_offset, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, dst->bo, dst_offset, NOUVEAU_BO_LOW, 0, 0); PUSH_DATA (push, src->pitch); PUSH_DATA (push, dst->pitch); PUSH_DATA (push, w * src->cpp); PUSH_DATA (push, lines); PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 | NV03_M2MF_FORMAT_OUTPUT_INC_1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1); PUSH_DATA (push, 0x00000000); h -= lines; src_offset += src->pitch * lines; dst_offset += dst->pitch * lines; } }
static void nouveau_finish(struct gl_context *ctx) { struct nouveau_context *nctx = to_nouveau_context(ctx); struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_pushbuf_refn refn = { nctx->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR }; nouveau_flush(ctx); if (!nouveau_pushbuf_space(push, 16, 0, 0) && !nouveau_pushbuf_refn(push, &refn, 1)) { PUSH_DATA(push, 0); PUSH_KICK(push); } nouveau_bo_wait(nctx->fence, NOUVEAU_BO_RDWR, context_client(ctx)); }
static void nv04_surface_copy_m2mf(struct gl_context *ctx, struct nouveau_surface *dst, struct nouveau_surface *src, int dx, int dy, int sx, int sy, int w, int h) { struct nouveau_pushbuf_refn refs[] = { { src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, }; struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; struct nv04_fifo *fifo = hw->chan->data; unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp; unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp; while (h) { int count = (h > 2047) ? 2047 : h; if (nouveau_pushbuf_space(push, 16, 4, 0) || nouveau_pushbuf_refn (push, refs, 2)) return; BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2); PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_DATA (push, src->pitch); PUSH_DATA (push, dst->pitch); PUSH_DATA (push, w * src->cpp); PUSH_DATA (push, count); PUSH_DATA (push, 0x0101); PUSH_DATA (push, 0); src_offset += src->pitch * count; dst_offset += dst->pitch * count; h -= count; } }
void nv04_surface_fill(struct gl_context *ctx, struct nouveau_surface *dst, unsigned mask, unsigned value, int dx, int dy, int w, int h) { struct nouveau_pushbuf_refn refs[] = { { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, }; struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; struct nv04_fifo *fifo = hw->chan->data; if (nouveau_pushbuf_space(push, 64, 4, 0) || nouveau_pushbuf_refn (push, refs, 1)) return; BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2); PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); PUSH_DATA (push, surf2d_format(dst->format)); PUSH_DATA (push, (dst->pitch << 16) | dst->pitch); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1); PUSH_DATA (push, rect_format(dst->format)); BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1); PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp)); BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1); PUSH_DATA (push, rect_format(dst->format)); BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1); PUSH_DATA (push, value); BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2); PUSH_DATA (push, (dx << 16) | dy); PUSH_DATA (push, ( w << 16) | h); }
static void nv30_transfer_rect_sifm(XFER_ARGS) { struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_pushbuf_refn refs[] = { { src->bo, src->domain | NOUVEAU_BO_RD }, { dst->bo, dst->domain | NOUVEAU_BO_WR }, }; struct nv04_fifo *fifo = push->channel->data; unsigned si_fmt, si_arg; unsigned ss_fmt; switch (dst->cpp) { case 4: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8; break; case 2: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5; break; default: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_Y8; break; } switch (src->cpp) { case 4: si_fmt = NV03_SIFM_COLOR_FORMAT_A8R8G8B8; break; case 2: si_fmt = NV03_SIFM_COLOR_FORMAT_R5G6B5; break; default: si_fmt = NV03_SIFM_COLOR_FORMAT_AY8; break; } if (filter == NEAREST) { si_arg = NV03_SIFM_FORMAT_ORIGIN_CENTER; si_arg |= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE; } else { si_arg = NV03_SIFM_FORMAT_ORIGIN_CORNER; si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR; } if (nouveau_pushbuf_space(push, 32, 6, 0) || nouveau_pushbuf_refn (push, refs, 2)) return; if (dst->pitch) { BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2); PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); PUSH_DATA (push, ss_fmt); PUSH_DATA (push, dst->pitch << 16 | dst->pitch); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV05_SIFM(SURFACE), 1); PUSH_DATA (push, nv30->screen->surf2d->handle); } else { BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1); PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2); PUSH_DATA (push, ss_fmt | (util_logbase2(dst->w) << 16) | (util_logbase2(dst->h) << 24)); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV05_SIFM(SURFACE), 1); PUSH_DATA (push, nv30->screen->swzsurf->handle); } BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1); PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8); PUSH_DATA (push, si_fmt); PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY); PUSH_DATA (push, ( dst->y0 << 16) | dst->x0); PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0)); PUSH_DATA (push, ( dst->y0 << 16) | dst->x0); PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0)); PUSH_DATA (push, ((src->x1 - src->x0) << 20) / (dst->x1 - dst->x0)); PUSH_DATA (push, ((src->y1 - src->y0) << 20) / (dst->y1 - dst->y0)); BEGIN_NV04(push, NV03_SIFM(SIZE), 4); PUSH_DATA (push, align(src->h, 2) << 16 | align(src->w, 2)); PUSH_DATA (push, src->pitch | si_arg); PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_DATA (push, (src->y0 << 20) | src->x0 << 4); }
static void nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, unsigned buffers, double depth, unsigned stencil, 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, mode = 0; rt_format = nv30_format(pipe->screen, ps->format)->hw; if (util_format_get_blocksize(ps->format) == 4) rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8; else rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5; 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; } if (buffers & PIPE_CLEAR_DEPTH) mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; if (buffers & PIPE_CLEAR_STENCIL) mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; refn.bo = mt->base.bo; refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; if (nouveau_pushbuf_space(push, 32, 1, 0) || nouveau_pushbuf_refn (push, &refn, 1)) return; BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, 0); 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); if (eng3d->oclass < NV40_3D_CLASS) { BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1); PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); } else { BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1); PUSH_DATA (push, sf->pitch); } BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1); 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_DEPTH_VALUE), 1); PUSH_DATA (push, pack_zeta(ps->format, depth, stencil)); BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1); PUSH_DATA (push, mode); nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; }
void nvc0_tfb_validate(struct nvc0_context *nvc0) { struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nvc0_transform_feedback_state *tfb; unsigned b; if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb; else if (nvc0->tevlprog) tfb = nvc0->tevlprog->tfb; else tfb = nvc0->vertprog->tfb; IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0); if (tfb && tfb != nvc0->state.tfb) { for (b = 0; b < 4; ++b) { if (tfb->varying_count[b]) { unsigned n = (tfb->varying_count[b] + 3) / 4; BEGIN_NVC0(push, NVC0_3D(TFB_STREAM(b)), 3); PUSH_DATA (push, tfb->stream[b]); PUSH_DATA (push, tfb->varying_count[b]); PUSH_DATA (push, tfb->stride[b]); BEGIN_NVC0(push, NVC0_3D(TFB_VARYING_LOCS(b, 0)), n); PUSH_DATAp(push, tfb->varying_index[b], n); if (nvc0->tfbbuf[b]) nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b]; } else { IMMED_NVC0(push, NVC0_3D(TFB_VARYING_COUNT(b)), 0); } } } nvc0->state.tfb = tfb; if (!(nvc0->dirty_3d & NVC0_NEW_3D_TFB_TARGETS)) return; for (b = 0; b < nvc0->num_tfbbufs; ++b) { struct nvc0_so_target *targ = nvc0_so_target(nvc0->tfbbuf[b]); struct nv04_resource *buf; if (!targ) { IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0); continue; } if (tfb) targ->stride = tfb->stride[b]; buf = nv04_resource(targ->pipe.buffer); BCTX_REFN(nvc0->bufctx_3d, 3D_TFB, buf, WR); if (!(nvc0->tfbbuf_dirty & (1 << b))) continue; if (!targ->clean) nvc0_hw_query_fifo_wait(nvc0, nvc0_query(targ->pq)); nouveau_pushbuf_space(push, 0, 0, 1); BEGIN_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 5); PUSH_DATA (push, 1); PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset); PUSH_DATA (push, buf->address + targ->pipe.buffer_offset); PUSH_DATA (push, targ->pipe.buffer_size); if (!targ->clean) { nvc0_hw_query_pushbuf_submit(push, nvc0_query(targ->pq), 0x4); } else { PUSH_DATA(push, 0); /* TFB_BUFFER_OFFSET */ targ->clean = false; } } for (; b < 4; ++b) IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0); }
void nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info) { struct nvc0_context *nvc0 = nvc0_context(pipe); struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nvc0_program *cp = nvc0->compprog; int ret; ret = !nvc0_state_validate_cp(nvc0, ~0); if (ret) { NOUVEAU_ERR("Failed to launch grid !\n"); return; } nvc0_compute_upload_input(nvc0, info); BEGIN_NVC0(push, NVC0_CP(CP_START_ID), 1); PUSH_DATA (push, nvc0_program_symbol_offset(cp, info->pc)); BEGIN_NVC0(push, NVC0_CP(LOCAL_POS_ALLOC), 3); PUSH_DATA (push, (cp->hdr[1] & 0xfffff0) + align(cp->cp.lmem_size, 0x10)); PUSH_DATA (push, 0); PUSH_DATA (push, 0x800); /* WARP_CSTACK_SIZE */ BEGIN_NVC0(push, NVC0_CP(SHARED_SIZE), 3); PUSH_DATA (push, align(cp->cp.smem_size, 0x100)); PUSH_DATA (push, info->block[0] * info->block[1] * info->block[2]); PUSH_DATA (push, cp->num_barriers); BEGIN_NVC0(push, NVC0_CP(CP_GPR_ALLOC), 1); PUSH_DATA (push, cp->num_gprs); /* launch preliminary setup */ BEGIN_NVC0(push, NVC0_CP(GRIDID), 1); PUSH_DATA (push, 0x1); BEGIN_NVC0(push, SUBC_CP(0x036c), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_CP(FLUSH), 1); PUSH_DATA (push, NVC0_COMPUTE_FLUSH_GLOBAL | NVC0_COMPUTE_FLUSH_UNK8); /* block setup */ BEGIN_NVC0(push, NVC0_CP(BLOCKDIM_YX), 2); PUSH_DATA (push, (info->block[1] << 16) | info->block[0]); PUSH_DATA (push, info->block[2]); if (unlikely(info->indirect)) { struct nv04_resource *res = nv04_resource(info->indirect); uint32_t offset = res->offset + info->indirect_offset; unsigned macro = NVC0_CP_MACRO_LAUNCH_GRID_INDIRECT; nouveau_pushbuf_space(push, 16, 0, 1); PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain); PUSH_DATA(push, NVC0_FIFO_PKHDR_1I(1, macro, 3)); nouveau_pushbuf_data(push, res->bo, offset, NVC0_IB_ENTRY_1_NO_PREFETCH | 3 * 4); } else { /* grid setup */ BEGIN_NVC0(push, NVC0_CP(GRIDDIM_YX), 2); PUSH_DATA (push, (info->grid[1] << 16) | info->grid[0]); PUSH_DATA (push, info->grid[2]); /* kernel launching */ BEGIN_NVC0(push, NVC0_CP(COMPUTE_BEGIN), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, SUBC_CP(0x0a08), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_CP(LAUNCH), 1); PUSH_DATA (push, 0x1000); BEGIN_NVC0(push, NVC0_CP(COMPUTE_END), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, SUBC_CP(0x0360), 1); PUSH_DATA (push, 0x1); } /* TODO: Not sure if this is really necessary. */ nvc0_compute_invalidate_surfaces(nvc0, 5); nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); nvc0->dirty_cp |= NVC0_NEW_CP_SURFACES; nvc0->images_dirty[5] |= nvc0->images_valid[5]; }
struct pipe_video_decoder * nvc0_create_decoder(struct pipe_context *context, enum pipe_video_profile profile, enum pipe_video_entrypoint entrypoint, enum pipe_video_chroma_format chroma_format, unsigned width, unsigned height, unsigned max_references, bool chunked_decode) { struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base; struct nvc0_decoder *dec; struct nouveau_pushbuf **push; union nouveau_bo_config cfg; bool kepler = screen->device->chipset >= 0xe0; cfg.nvc0.tile_mode = 0x10; cfg.nvc0.memtype = 0xfe; int ret, i; uint32_t codec = 1, ppp_codec = 3; uint32_t timeout; u32 tmp_size = 0; if (getenv("XVMC_VL")) return vl_create_decoder(context, profile, entrypoint, chroma_format, width, height, max_references, chunked_decode); if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { debug_printf("%x\n", entrypoint); return NULL; } dec = CALLOC_STRUCT(nvc0_decoder); if (!dec) return NULL; dec->client = screen->client; if (!kepler) { dec->bsp_idx = 5; dec->vp_idx = 6; dec->ppp_idx = 7; } else { dec->bsp_idx = 2; dec->vp_idx = 2; dec->ppp_idx = 2; } for (i = 0; i < 3; ++i) if (i && !kepler) { dec->channel[i] = dec->channel[0]; dec->pushbuf[i] = dec->pushbuf[0]; } else { void *data; u32 size; struct nvc0_fifo nvc0_args = {}; struct nve0_fifo nve0_args = {}; if (!kepler) { size = sizeof(nvc0_args); data = &nvc0_args; } else { unsigned engine[] = { NVE0_FIFO_ENGINE_BSP, NVE0_FIFO_ENGINE_VP, NVE0_FIFO_ENGINE_PPP }; nve0_args.engine = engine[i]; size = sizeof(nve0_args); data = &nve0_args; } ret = nouveau_object_new(&screen->device->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, data, size, &dec->channel[i]); if (!ret) ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4, 32 * 1024, true, &dec->pushbuf[i]); if (ret) break; } push = dec->pushbuf; if (!kepler) { if (!ret) ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp); if (!ret) ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp); if (!ret) ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp); } else { if (!ret) ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp); if (!ret) ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp); if (!ret) ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp); } if (ret) goto fail; BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push[0], dec->bsp->handle); BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push[1], dec->vp->handle); BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push[2], dec->ppp->handle); dec->base.context = context; dec->base.profile = profile; dec->base.entrypoint = entrypoint; dec->base.chroma_format = chroma_format; dec->base.width = width; dec->base.height = height; dec->base.max_references = max_references; dec->base.destroy = nvc0_decoder_destroy; dec->base.flush = nvc0_decoder_flush; dec->base.decode_bitstream = nvc0_decoder_decode_bitstream; dec->base.begin_frame = nvc0_decoder_begin_frame; dec->base.end_frame = nvc0_decoder_end_frame; for (i = 0; i < NVC0_VIDEO_QDEPTH && !ret; ++i) ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, 1 << 20, &cfg, &dec->bsp_bo[i]); if (!ret) ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0x100, 4 << 20, &cfg, &dec->inter_bo[0]); if (!ret) { if (!kepler) nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]); else ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0x100, dec->inter_bo[0]->size, &cfg, &dec->inter_bo[1]); } if (ret) goto fail; switch (u_reduce_video_profile(profile)) { case PIPE_VIDEO_CODEC_MPEG12: { codec = 1; assert(max_references <= 2); break; } case PIPE_VIDEO_CODEC_MPEG4: { codec = 4; tmp_size = mb(height)*16 * mb(width)*16; assert(max_references <= 2); break; } case PIPE_VIDEO_CODEC_VC1: { ppp_codec = codec = 2; tmp_size = mb(height)*16 * mb(width)*16; assert(max_references <= 2); break; } case PIPE_VIDEO_CODEC_MPEG4_AVC: { codec = 3; dec->tmp_stride = 16 * mb_half(width) * nvc0_video_align(height) * 3 / 2; tmp_size = dec->tmp_stride * (max_references + 1); assert(max_references <= 16); break; } default: fprintf(stderr, "invalid codec\n"); goto fail; } if (screen->device->chipset < 0xd0) { int fd; char path[PATH_MAX]; ssize_t r; uint32_t *end, endval; ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, 0x4000, &cfg, &dec->fw_bo); if (!ret) ret = nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client); if (ret) goto fail; nvc0_video_getpath(profile, path); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) { fprintf(stderr, "opening firmware file %s failed: %m\n", path); goto fw_fail; } r = read(fd, dec->fw_bo->map, 0x4000); close(fd); if (r < 0) { fprintf(stderr, "reading firmware file %s failed: %m\n", path); goto fw_fail; } if (r == 0x4000) { fprintf(stderr, "firmware file %s too large!\n", path); goto fw_fail; } if (r & 0xff) { fprintf(stderr, "firmware file %s wrong size!\n", path); goto fw_fail; } end = dec->fw_bo->map + r - 4; endval = *end; while (endval == *end) end--; r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4; switch (u_reduce_video_profile(profile)) { case PIPE_VIDEO_CODEC_MPEG12: { assert((r & 0xff) == 0xe0); dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0); break; } case PIPE_VIDEO_CODEC_MPEG4: { assert((r & 0xff) == 0xe0); dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0); break; } case PIPE_VIDEO_CODEC_VC1: { assert((r & 0xff) == 0xac); dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac); break; } case PIPE_VIDEO_CODEC_MPEG4_AVC: { assert((r & 0xff) == 0x70); dec->fw_sizes = (0x370<<16) | (r - 0x370); break; } default: goto fw_fail; } munmap(dec->fw_bo->map, dec->fw_bo->size); dec->fw_bo->map = NULL; } if (codec != 3) { ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, 0x400, &cfg, &dec->bitplane_bo); if (ret) goto fail; } dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nvc0_video_align(height)/2); ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, dec->ref_stride * (max_references+2) + tmp_size, &cfg, &dec->ref_bo); if (ret) goto fail; timeout = 0; BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2); PUSH_DATA (push[0], codec); PUSH_DATA (push[0], timeout); BEGIN_NVC0(push[1], SUBC_VP(0x200), 2); PUSH_DATA (push[1], codec); PUSH_DATA (push[1], timeout); BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2); PUSH_DATA (push[2], ppp_codec); PUSH_DATA (push[2], timeout); ++dec->fence_seq; #if NVC0_DEBUG_FENCE ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP, 0, 0x1000, NULL, &dec->fence_bo); if (ret) goto fail; nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); dec->fence_map = dec->fence_bo->map; dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0; dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); /* So lets test if the fence is working? */ nouveau_pushbuf_space(push[0], 6, 1, 0); PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3); PUSH_DATAh(push[0], dec->fence_bo->offset); PUSH_DATA (push[0], dec->fence_bo->offset); PUSH_DATA (push[0], dec->fence_seq); BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1); PUSH_DATA (push[0], 0); PUSH_KICK (push[0]); nouveau_pushbuf_space(push[1], 6, 1, 0); PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); BEGIN_NVC0(push[1], SUBC_VP(0x240), 3); PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10)); PUSH_DATA (push[1], dec->fence_seq); BEGIN_NVC0(push[1], SUBC_VP(0x304), 1); PUSH_DATA (push[1], 0); PUSH_KICK (push[1]); nouveau_pushbuf_space(push[2], 6, 1, 0); PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3); PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20)); PUSH_DATA (push[2], dec->fence_seq); BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1); PUSH_DATA (push[2], 0); PUSH_KICK (push[2]); usleep(100); while (dec->fence_seq > dec->fence_map[0] || dec->fence_seq > dec->fence_map[4] || dec->fence_seq > dec->fence_map[8]) { debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]); usleep(100); } debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]); #endif return &dec->base; fw_fail: debug_printf("Cannot create decoder without firmware..\n"); nvc0_decoder_destroy(&dec->base); return NULL; fail: debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret); nvc0_decoder_destroy(&dec->base); return NULL; }
static void nv04_surface_copy_swizzle(struct gl_context *ctx, struct nouveau_surface *dst, struct nouveau_surface *src, int dx, int dy, int sx, int sy, int w, int h) { struct nouveau_pushbuf_refn refs[] = { { src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, }; struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; struct nouveau_object *swzsurf = hw->swzsurf; struct nv04_fifo *fifo = hw->chan->data; /* Max width & height may not be the same on all HW, but must be POT */ const unsigned max_w = 1024; const unsigned max_h = 1024; unsigned sub_w = w > max_w ? max_w : w; unsigned sub_h = h > max_h ? max_h : h; unsigned x, y; /* Swizzled surfaces must be POT */ assert(_mesa_is_pow_two(dst->width) && _mesa_is_pow_two(dst->height)); if (context_chipset(ctx) < 0x10) { BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1); PUSH_DATA (push, swzsurf->handle); } for (y = 0; y < h; y += sub_h) { sub_h = MIN2(sub_h, h - y); for (x = 0; x < w; x += sub_w) { sub_w = MIN2(sub_w, w - x); if (nouveau_pushbuf_space(push, 64, 4, 0) || nouveau_pushbuf_refn (push, refs, 2)) return; BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1); PUSH_DATA (push, fifo->vram); BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2); PUSH_DATA (push, swzsurf_format(dst->format) | log2i(dst->width) << 16 | log2i(dst->height) << 24); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1); PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); BEGIN_NV04(push, NV05_SIFM(SURFACE), 1); PUSH_DATA (push, swzsurf->handle); BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8); PUSH_DATA (push, sifm_format(src->format)); PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); PUSH_DATA (push, (y + dy) << 16 | (x + dx)); PUSH_DATA (push, sub_h << 16 | sub_w); PUSH_DATA (push, (y + dy) << 16 | (x + dx)); PUSH_DATA (push, sub_h << 16 | sub_w); PUSH_DATA (push, 1 << 20); PUSH_DATA (push, 1 << 20); BEGIN_NV04(push, NV03_SIFM(SIZE), 4); PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2)); PUSH_DATA (push, src->pitch | NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch + (x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0); PUSH_DATA (push, 0); } } if (context_chipset(ctx) < 0x10) { BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1); PUSH_DATA (push, hw->surf3d->handle); } }
void nv30_transfer_copy_data(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned d_off, unsigned d_dom, struct nouveau_bo *src, unsigned s_off, unsigned s_dom, unsigned size) { struct nv04_fifo *fifo = nv->screen->channel->data; struct nouveau_pushbuf_refn refs[] = { { src, s_dom | NOUVEAU_BO_RD }, { dst, d_dom | NOUVEAU_BO_WR }, }; struct nouveau_pushbuf *push = nv->pushbuf; unsigned pages, lines; pages = size >> 12; size -= (pages << 12); BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2); PUSH_DATA (push, (s_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart); PUSH_DATA (push, (d_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart); while (pages) { lines = (pages > 2047) ? 2047 : pages; pages -= lines; if (nouveau_pushbuf_space(push, 13, 2, 0) || nouveau_pushbuf_refn (push, refs, 2)) return; BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0); PUSH_DATA (push, 4096); PUSH_DATA (push, 4096); PUSH_DATA (push, 4096); PUSH_DATA (push, lines); PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 | NV03_M2MF_FORMAT_OUTPUT_INC_1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1); PUSH_DATA (push, 0x00000000); s_off += (lines << 12); d_off += (lines << 12); } if (size) { if (nouveau_pushbuf_space(push, 13, 2, 0) || nouveau_pushbuf_refn (push, refs, 2)) return; BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0); PUSH_DATA (push, size); PUSH_DATA (push, size); PUSH_DATA (push, size); PUSH_DATA (push, 1); PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 | NV03_M2MF_FORMAT_OUTPUT_INC_1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1); PUSH_DATA (push, 0x00000000); } }
struct pipe_video_codec * nvc0_create_decoder(struct pipe_context *context, const struct pipe_video_codec *templ) { struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base; struct nouveau_vp3_decoder *dec; struct nouveau_pushbuf **push; union nouveau_bo_config cfg; bool kepler = screen->device->chipset >= 0xe0; cfg.nvc0.tile_mode = 0x10; cfg.nvc0.memtype = 0xfe; int ret, i; uint32_t codec = 1, ppp_codec = 3; uint32_t timeout; u32 tmp_size = 0; if (getenv("XVMC_VL")) return vl_create_decoder(context, templ); if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { debug_printf("%x\n", templ->entrypoint); return NULL; } dec = CALLOC_STRUCT(nouveau_vp3_decoder); if (!dec) return NULL; dec->client = screen->client; dec->base = *templ; nouveau_vp3_decoder_init_common(&dec->base); if (!kepler) { dec->bsp_idx = 5; dec->vp_idx = 6; dec->ppp_idx = 7; } else { dec->bsp_idx = 2; dec->vp_idx = 2; dec->ppp_idx = 2; } for (i = 0; i < 3; ++i) if (i && !kepler) { dec->channel[i] = dec->channel[0]; dec->pushbuf[i] = dec->pushbuf[0]; } else { void *data; u32 size; struct nvc0_fifo nvc0_args = {}; struct nve0_fifo nve0_args = {}; if (!kepler) { size = sizeof(nvc0_args); data = &nvc0_args; } else { unsigned engine[] = { NVE0_FIFO_ENGINE_BSP, NVE0_FIFO_ENGINE_VP, NVE0_FIFO_ENGINE_PPP }; nve0_args.engine = engine[i]; size = sizeof(nve0_args); data = &nve0_args; } ret = nouveau_object_new(&screen->device->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, data, size, &dec->channel[i]); if (!ret) ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4, 32 * 1024, true, &dec->pushbuf[i]); if (ret) break; } push = dec->pushbuf; if (!kepler) { if (!ret) ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp); if (!ret) ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp); if (!ret) ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp); } else { if (!ret) ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp); if (!ret) ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp); if (!ret) ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp); } if (ret) goto fail; BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push[0], dec->bsp->handle); BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push[1], dec->vp->handle); BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1); PUSH_DATA (push[2], dec->ppp->handle); dec->base.context = context; dec->base.decode_bitstream = nvc0_decoder_decode_bitstream; for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i) ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, 1 << 20, &cfg, &dec->bsp_bo[i]); if (!ret) ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0x100, 4 << 20, &cfg, &dec->inter_bo[0]); if (!ret) { ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0x100, dec->inter_bo[0]->size, &cfg, &dec->inter_bo[1]); } if (ret) goto fail; switch (u_reduce_video_profile(templ->profile)) { case PIPE_VIDEO_FORMAT_MPEG12: { codec = 1; assert(templ->max_references <= 2); break; } case PIPE_VIDEO_FORMAT_MPEG4: { codec = 4; tmp_size = mb(templ->height)*16 * mb(templ->width)*16; assert(templ->max_references <= 2); break; } case PIPE_VIDEO_FORMAT_VC1: { ppp_codec = codec = 2; tmp_size = mb(templ->height)*16 * mb(templ->width)*16; assert(templ->max_references <= 2); break; } case PIPE_VIDEO_FORMAT_MPEG4_AVC: { codec = 3; dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2; tmp_size = dec->tmp_stride * (templ->max_references + 1); assert(templ->max_references <= 16); break; } default: fprintf(stderr, "invalid codec\n"); goto fail; } if (screen->device->chipset < 0xd0) { ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, 0x4000, &cfg, &dec->fw_bo); if (ret) goto fail; ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset); if (ret) goto fw_fail; } if (codec != 3) { ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, 0x400, &cfg, &dec->bitplane_bo); if (ret) goto fail; } dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2); ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, dec->ref_stride * (templ->max_references+2) + tmp_size, &cfg, &dec->ref_bo); if (ret) goto fail; timeout = 0; BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2); PUSH_DATA (push[0], codec); PUSH_DATA (push[0], timeout); BEGIN_NVC0(push[1], SUBC_VP(0x200), 2); PUSH_DATA (push[1], codec); PUSH_DATA (push[1], timeout); BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2); PUSH_DATA (push[2], ppp_codec); PUSH_DATA (push[2], timeout); ++dec->fence_seq; #if NOUVEAU_VP3_DEBUG_FENCE ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP, 0, 0x1000, NULL, &dec->fence_bo); if (ret) goto fail; nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); dec->fence_map = dec->fence_bo->map; dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0; dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); /* So lets test if the fence is working? */ nouveau_pushbuf_space(push[0], 6, 1, 0); PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3); PUSH_DATAh(push[0], dec->fence_bo->offset); PUSH_DATA (push[0], dec->fence_bo->offset); PUSH_DATA (push[0], dec->fence_seq); BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1); PUSH_DATA (push[0], 0); PUSH_KICK (push[0]); nouveau_pushbuf_space(push[1], 6, 1, 0); PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); BEGIN_NVC0(push[1], SUBC_VP(0x240), 3); PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10)); PUSH_DATA (push[1], dec->fence_seq); BEGIN_NVC0(push[1], SUBC_VP(0x304), 1); PUSH_DATA (push[1], 0); PUSH_KICK (push[1]); nouveau_pushbuf_space(push[2], 6, 1, 0); PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3); PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20)); PUSH_DATA (push[2], dec->fence_seq); BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1); PUSH_DATA (push[2], 0); PUSH_KICK (push[2]); usleep(100); while (dec->fence_seq > dec->fence_map[0] || dec->fence_seq > dec->fence_map[4] || dec->fence_seq > dec->fence_map[8]) { debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]); usleep(100); } debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]); #endif return &dec->base; fw_fail: debug_printf("Cannot create decoder without firmware..\n"); dec->base.destroy(&dec->base); return NULL; fail: debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret); dec->base.destroy(&dec->base); return NULL; }
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); }