Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv30/nv30_transfer.c
4574 views
/*1* Copyright 2012 Red Hat Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21* Authors: Ben Skeggs22*23*/2425#define XFER_ARGS \26struct nv30_context *nv30, enum nv30_transfer_filter filter, \27struct nv30_rect *src, struct nv30_rect *dst2829#include "util/u_math.h"3031#include "nv_object.xml.h"32#include "nv_m2mf.xml.h"33#include "nv30/nv01_2d.xml.h"34#include "nv30/nv30-40_3d.xml.h"3536#include "nv30/nv30_context.h"37#include "nv30/nv30_transfer.h"3839/* Various helper functions to transfer different types of data in a number40* of different ways.41*/4243static inline bool44nv30_transfer_scaled(struct nv30_rect *src, struct nv30_rect *dst)45{46if (src->x1 - src->x0 != dst->x1 - dst->x0)47return true;48if (src->y1 - src->y0 != dst->y1 - dst->y0)49return true;50return false;51}5253static inline bool54nv30_transfer_blit(XFER_ARGS)55{56if (nv30->screen->eng3d->oclass < NV40_3D_CLASS)57return false;58if (dst->offset & 63 || dst->pitch & 63 || dst->d > 1)59return false;60if (dst->w < 2 || dst->h < 2)61return false;62if (dst->cpp > 4 || (dst->cpp == 1 && !dst->pitch))63return false;64if (src->cpp > 4)65return false;66return true;67}6869static inline struct nouveau_heap *70nv30_transfer_rect_vertprog(struct nv30_context *nv30)71{72struct nouveau_heap *heap = nv30->screen->vp_exec_heap;73struct nouveau_heap *vp;7475vp = nv30->blit_vp;76if (!vp) {77if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp)) {78while (heap->next && heap->size < 2) {79struct nouveau_heap **evict = heap->next->priv;80nouveau_heap_free(evict);81}8283if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp))84return NULL;85}8687vp = nv30->blit_vp;88if (vp) {89struct nouveau_pushbuf *push = nv30->base.pushbuf;9091BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);92PUSH_DATA (push, vp->start);93BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);94PUSH_DATA (push, 0x401f9c6c); /* mov o[hpos], a[0]; */95PUSH_DATA (push, 0x0040000d);96PUSH_DATA (push, 0x8106c083);97PUSH_DATA (push, 0x6041ff80);98BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);99PUSH_DATA (push, 0x401f9c6c); /* mov o[tex0], a[8]; end; */100PUSH_DATA (push, 0x0040080d);101PUSH_DATA (push, 0x8106c083);102PUSH_DATA (push, 0x6041ff9d);103}104}105106return vp;107}108109110static inline struct nv04_resource *111nv30_transfer_rect_fragprog(struct nv30_context *nv30)112{113struct nv04_resource *fp = nv04_resource(nv30->blit_fp);114struct pipe_context *pipe = &nv30->base.pipe;115116if (!fp) {117nv30->blit_fp =118pipe_buffer_create(pipe->screen, 0, PIPE_USAGE_STAGING, 12 * 4);119if (nv30->blit_fp) {120struct pipe_transfer *transfer;121u32 *map = pipe_buffer_map(pipe, nv30->blit_fp,122PIPE_MAP_WRITE, &transfer);123if (map) {124map[0] = 0x17009e00; /* texr r0, i[tex0], texture[0]; end; */125map[1] = 0x1c9dc801;126map[2] = 0x0001c800;127map[3] = 0x3fe1c800;128map[4] = 0x01401e81; /* end; */129map[5] = 0x1c9dc800;130map[6] = 0x0001c800;131map[7] = 0x0001c800;132pipe_buffer_unmap(pipe, transfer);133}134135fp = nv04_resource(nv30->blit_fp);136nouveau_buffer_migrate(&nv30->base, fp, NOUVEAU_BO_VRAM);137}138}139140return fp;141}142143static void144nv30_transfer_rect_blit(XFER_ARGS)145{146struct nv04_resource *fp = nv30_transfer_rect_fragprog(nv30);147struct nouveau_heap *vp = nv30_transfer_rect_vertprog(nv30);148struct nouveau_pushbuf *push = nv30->base.pushbuf;149struct nouveau_pushbuf_refn refs[] = {150{ fp->bo, fp->domain | NOUVEAU_BO_RD },151{ src->bo, src->domain | NOUVEAU_BO_RD },152{ dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR },153};154u32 texfmt, texswz;155u32 format, stride;156157if (nouveau_pushbuf_space(push, 512, 8, 0) ||158nouveau_pushbuf_refn (push, refs, ARRAY_SIZE(refs)))159return;160161/* various switches depending on cpp of the transfer */162switch (dst->cpp) {163case 4:164format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 |165NV30_3D_RT_FORMAT_ZETA_Z24S8;166texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8;167texswz = 0x0000aae4;168break;169case 2:170format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 |171NV30_3D_RT_FORMAT_ZETA_Z16;172texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5;173texswz = 0x0000a9e4;174break;175case 1:176format = NV30_3D_RT_FORMAT_COLOR_B8 |177NV30_3D_RT_FORMAT_ZETA_Z16;178texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8;179texswz = 0x0000aaff;180break;181default:182assert(0);183return;184}185186/* render target */187if (!dst->pitch) {188format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;189format |= util_logbase2(dst->w) << 16;190format |= util_logbase2(dst->h) << 24;191stride = 64;192} else {193format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;194stride = dst->pitch;195}196197BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);198PUSH_DATA (push, dst->w << 16);199PUSH_DATA (push, dst->h << 16);200BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5);201PUSH_DATA (push, dst->w << 16);202PUSH_DATA (push, dst->h << 16);203PUSH_DATA (push, format);204PUSH_DATA (push, stride);205PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);206BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);207PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);208209nv30->dirty |= NV30_NEW_FRAMEBUFFER;210211/* viewport state */212BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);213PUSH_DATAf(push, 0.0);214PUSH_DATAf(push, 0.0);215PUSH_DATAf(push, 0.0);216PUSH_DATAf(push, 0.0);217PUSH_DATAf(push, 1.0);218PUSH_DATAf(push, 1.0);219PUSH_DATAf(push, 1.0);220PUSH_DATAf(push, 1.0);221BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);222PUSH_DATAf(push, 0.0);223PUSH_DATAf(push, 1.0);224225nv30->dirty |= NV30_NEW_VIEWPORT;226227/* blend state */228BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1);229PUSH_DATA (push, 0);230BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1);231PUSH_DATA (push, 0);232BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);233PUSH_DATA (push, 0);234BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1);235PUSH_DATA (push, 0x01010101);236237nv30->dirty |= NV30_NEW_BLEND;238239/* depth-stencil-alpha state */240BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2);241PUSH_DATA (push, 0);242PUSH_DATA (push, 0);243BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1);244PUSH_DATA (push, 0);245BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1);246PUSH_DATA (push, 0);247BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1);248PUSH_DATA (push, 0);249250nv30->dirty |= NV30_NEW_ZSA;251252/* rasterizer state */253BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1);254PUSH_DATA (push, NV30_3D_SHADE_MODEL_FLAT);255BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1);256PUSH_DATA (push, 0);257BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2);258PUSH_DATA (push, NV30_3D_POLYGON_MODE_FRONT_FILL);259PUSH_DATA (push, NV30_3D_POLYGON_MODE_BACK_FILL);260BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FILL_ENABLE), 1);261PUSH_DATA (push, 0);262BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1);263PUSH_DATA (push, 0);264265nv30->state.scissor_off = 0;266nv30->dirty |= NV30_NEW_RASTERIZER;267268/* vertex program */269BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);270PUSH_DATA (push, vp->start);271BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);272PUSH_DATA (push, 0x00000101); /* attrib: 0, 8 */273PUSH_DATA (push, 0x00004000); /* result: hpos, tex0 */274BEGIN_NV04(push, NV30_3D(ENGINE), 1);275PUSH_DATA (push, 0x00000103);276BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);277PUSH_DATA (push, 0x00000000);278279nv30->dirty |= NV30_NEW_VERTPROG;280nv30->dirty |= NV30_NEW_CLIP;281282/* fragment program */283BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);284PUSH_RELOC(push, fp->bo, fp->offset, fp->domain |285NOUVEAU_BO_LOW | NOUVEAU_BO_OR,286NV30_3D_FP_ACTIVE_PROGRAM_DMA0,287NV30_3D_FP_ACTIVE_PROGRAM_DMA1);288BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);289PUSH_DATA (push, 0x02000000);290291nv30->state.fragprog = NULL;292nv30->dirty |= NV30_NEW_FRAGPROG;293294/* texture */295texfmt |= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;296texfmt |= NV30_3D_TEX_FORMAT_NO_BORDER;297texfmt |= NV40_3D_TEX_FORMAT_RECT;298texfmt |= 0x00008000;299if (src->d < 2)300texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D;301else302texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D;303if (src->pitch)304texfmt |= NV40_3D_TEX_FORMAT_LINEAR;305306BEGIN_NV04(push, NV30_3D(TEX_OFFSET(0)), 8);307PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);308PUSH_RELOC(push, src->bo, texfmt, NOUVEAU_BO_OR,309NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);310PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE |311NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE |312NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE);313PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE);314PUSH_DATA (push, texswz);315switch (filter) {316case BILINEAR:317PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |318NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000);319break;320default:321PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST |322NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000);323break;324}325PUSH_DATA (push, (src->w << 16) | src->h);326PUSH_DATA (push, 0x00000000);327BEGIN_NV04(push, NV40_3D(TEX_SIZE1(0)), 1);328PUSH_DATA (push, 0x00100000 | src->pitch);329BEGIN_NV04(push, SUBC_3D(0x0b40), 1);330PUSH_DATA (push, src->d < 2 ? 0x00000001 : 0x00000000);331BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);332PUSH_DATA (push, 1);333334nv30->fragprog.dirty_samplers |= 1;335nv30->dirty |= NV30_NEW_FRAGTEX;336337/* blit! */338BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);339PUSH_DATA (push, (dst->x1 - dst->x0) << 16 | dst->x0);340PUSH_DATA (push, (dst->y1 - dst->y0) << 16 | dst->y0);341BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);342PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_QUADS);343BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);344PUSH_DATAf(push, src->x0);345PUSH_DATAf(push, src->y0);346PUSH_DATAf(push, src->z);347BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);348PUSH_DATA (push, (dst->y0 << 16) | dst->x0);349BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);350PUSH_DATAf(push, src->x1);351PUSH_DATAf(push, src->y0);352PUSH_DATAf(push, src->z);353BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);354PUSH_DATA (push, (dst->y0 << 16) | dst->x1);355BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);356PUSH_DATAf(push, src->x1);357PUSH_DATAf(push, src->y1);358PUSH_DATAf(push, src->z);359BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);360PUSH_DATA (push, (dst->y1 << 16) | dst->x1);361BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);362PUSH_DATAf(push, src->x0);363PUSH_DATAf(push, src->y1);364PUSH_DATAf(push, src->z);365BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);366PUSH_DATA (push, (dst->y1 << 16) | dst->x0);367BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);368PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);369}370371static bool372nv30_transfer_sifm(XFER_ARGS)373{374if (!src->pitch || src->w > 1024 || src->h > 1024 || src->w < 2 || src->h < 2)375return false;376377if (src->d > 1 || dst->d > 1)378return false;379380if (dst->offset & 63)381return false;382383if (!dst->pitch) {384if (dst->w > 2048 || dst->h > 2048 || dst->w < 2 || dst->h < 2)385return false;386} else {387if (dst->domain != NOUVEAU_BO_VRAM)388return false;389if (dst->pitch & 63)390return false;391}392393return true;394}395396static void397nv30_transfer_rect_sifm(XFER_ARGS)398399{400struct nouveau_pushbuf *push = nv30->base.pushbuf;401struct nouveau_pushbuf_refn refs[] = {402{ src->bo, src->domain | NOUVEAU_BO_RD },403{ dst->bo, dst->domain | NOUVEAU_BO_WR },404};405struct nv04_fifo *fifo = push->channel->data;406unsigned si_fmt, si_arg;407unsigned ss_fmt;408409switch (dst->cpp) {410case 4: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8; break;411case 2: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5; break;412default:413ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_Y8;414break;415}416417switch (src->cpp) {418case 4: si_fmt = NV03_SIFM_COLOR_FORMAT_A8R8G8B8; break;419case 2: si_fmt = NV03_SIFM_COLOR_FORMAT_R5G6B5; break;420default:421si_fmt = NV03_SIFM_COLOR_FORMAT_AY8;422break;423}424425if (filter == NEAREST) {426si_arg = NV03_SIFM_FORMAT_ORIGIN_CENTER;427si_arg |= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE;428} else {429si_arg = NV03_SIFM_FORMAT_ORIGIN_CORNER;430si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR;431}432433if (nouveau_pushbuf_space(push, 64, 6, 0) ||434nouveau_pushbuf_refn (push, refs, 2))435return;436437if (dst->pitch) {438BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);439PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);440PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);441BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);442PUSH_DATA (push, ss_fmt);443PUSH_DATA (push, dst->pitch << 16 | dst->pitch);444PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);445PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);446BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);447PUSH_DATA (push, nv30->screen->surf2d->handle);448} else {449BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);450PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);451BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);452PUSH_DATA (push, ss_fmt | (util_logbase2(dst->w) << 16) |453(util_logbase2(dst->h) << 24));454PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);455BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);456PUSH_DATA (push, nv30->screen->swzsurf->handle);457}458459BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);460PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);461BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);462PUSH_DATA (push, si_fmt);463PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY);464PUSH_DATA (push, ( dst->y0 << 16) | dst->x0);465PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));466PUSH_DATA (push, ( dst->y0 << 16) | dst->x0);467PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));468PUSH_DATA (push, ((src->x1 - src->x0) << 20) / (dst->x1 - dst->x0));469PUSH_DATA (push, ((src->y1 - src->y0) << 20) / (dst->y1 - dst->y0));470BEGIN_NV04(push, NV03_SIFM(SIZE), 4);471PUSH_DATA (push, align(src->h, 2) << 16 | align(src->w, 2));472PUSH_DATA (push, src->pitch | si_arg);473PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);474PUSH_DATA (push, (src->y0 << 20) | src->x0 << 4);475}476477/* The NOP+OFFSET_OUT stuff after each M2MF transfer *is* actually required478* to prevent some odd things from happening, easily reproducible by479* attempting to do conditional rendering that has a M2MF transfer done480* some time before it. 0x1e98 will fail with a DMA_W_PROTECTION (assuming481* that name is still accurate on nv4x) error.482*/483484static bool485nv30_transfer_m2mf(XFER_ARGS)486{487if (!src->pitch || !dst->pitch)488return false;489if (nv30_transfer_scaled(src, dst))490return false;491return true;492}493494static void495nv30_transfer_rect_m2mf(XFER_ARGS)496{497struct nouveau_pushbuf *push = nv30->base.pushbuf;498struct nouveau_pushbuf_refn refs[] = {499{ src->bo, src->domain | NOUVEAU_BO_RD },500{ dst->bo, dst->domain | NOUVEAU_BO_WR },501};502struct nv04_fifo *fifo = push->channel->data;503unsigned src_offset = src->offset;504unsigned dst_offset = dst->offset;505unsigned w = dst->x1 - dst->x0;506unsigned h = dst->y1 - dst->y0;507508src_offset += (src->y0 * src->pitch) + (src->x0 * src->cpp);509dst_offset += (dst->y0 * dst->pitch) + (dst->x0 * dst->cpp);510511BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);512PUSH_DATA (push, (src->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);513PUSH_DATA (push, (dst->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);514515while (h) {516unsigned lines = (h > 2047) ? 2047 : h;517518if (nouveau_pushbuf_space(push, 32, 2, 0) ||519nouveau_pushbuf_refn (push, refs, 2))520return;521522BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);523PUSH_RELOC(push, src->bo, src_offset, NOUVEAU_BO_LOW, 0, 0);524PUSH_RELOC(push, dst->bo, dst_offset, NOUVEAU_BO_LOW, 0, 0);525PUSH_DATA (push, src->pitch);526PUSH_DATA (push, dst->pitch);527PUSH_DATA (push, w * src->cpp);528PUSH_DATA (push, lines);529PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |530NV03_M2MF_FORMAT_OUTPUT_INC_1);531PUSH_DATA (push, 0x00000000);532BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);533PUSH_DATA (push, 0x00000000);534BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);535PUSH_DATA (push, 0x00000000);536537h -= lines;538src_offset += src->pitch * lines;539dst_offset += dst->pitch * lines;540}541}542543static bool544nv30_transfer_cpu(XFER_ARGS)545{546if (nv30_transfer_scaled(src, dst))547return false;548return true;549}550551static char *552linear_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)553{554return base + (y * rect->pitch) + (x * rect->cpp);555}556557static inline unsigned558swizzle2d(unsigned v, unsigned s)559{560v = (v | (v << 8)) & 0x00ff00ff;561v = (v | (v << 4)) & 0x0f0f0f0f;562v = (v | (v << 2)) & 0x33333333;563v = (v | (v << 1)) & 0x55555555;564return v << s;565}566567static char *568swizzle2d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)569{570unsigned k = util_logbase2(MIN2(rect->w, rect->h));571unsigned km = (1 << k) - 1;572unsigned nx = rect->w >> k;573unsigned tx = x >> k;574unsigned ty = y >> k;575unsigned m;576577m = swizzle2d(x & km, 0);578m |= swizzle2d(y & km, 1);579m += ((ty * nx) + tx) << k << k;580581return base + (m * rect->cpp);582}583584static char *585swizzle3d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)586{587unsigned w = rect->w >> 1;588unsigned h = rect->h >> 1;589unsigned d = rect->d >> 1;590unsigned i = 0, o;591unsigned v = 0;592593do {594o = i;595if (w) {596v |= (x & 1) << i++;597x >>= 1;598w >>= 1;599}600if (h) {601v |= (y & 1) << i++;602y >>= 1;603h >>= 1;604}605if (d) {606v |= (z & 1) << i++;607z >>= 1;608d >>= 1;609}610} while(o != i);611612return base + (v * rect->cpp);613}614615typedef char *(*get_ptr_t)(struct nv30_rect *, char *, int, int, int);616617static inline get_ptr_t618get_ptr(struct nv30_rect *rect)619{620if (rect->pitch)621return linear_ptr;622623if (rect->d <= 1)624return swizzle2d_ptr;625626return swizzle3d_ptr;627}628629static void630nv30_transfer_rect_cpu(XFER_ARGS)631{632get_ptr_t sp = get_ptr(src);633get_ptr_t dp = get_ptr(dst);634char *srcmap, *dstmap;635int x, y;636637nouveau_bo_map(src->bo, NOUVEAU_BO_RD, nv30->base.client);638nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, nv30->base.client);639srcmap = src->bo->map + src->offset;640dstmap = dst->bo->map + dst->offset;641642for (y = 0; y < (dst->y1 - dst->y0); y++) {643for (x = 0; x < (dst->x1 - dst->x0); x++) {644memcpy(dp(dst, dstmap, dst->x0 + x, dst->y0 + y, dst->z),645sp(src, srcmap, src->x0 + x, src->y0 + y, src->z), dst->cpp);646}647}648}649650void651nv30_transfer_rect(struct nv30_context *nv30, enum nv30_transfer_filter filter,652struct nv30_rect *src, struct nv30_rect *dst)653{654static const struct {655char *name;656bool (*possible)(XFER_ARGS);657void (*execute)(XFER_ARGS);658} *method, methods[] = {659{ "m2mf", nv30_transfer_m2mf, nv30_transfer_rect_m2mf },660{ "sifm", nv30_transfer_sifm, nv30_transfer_rect_sifm },661{ "blit", nv30_transfer_blit, nv30_transfer_rect_blit },662{ "rect", nv30_transfer_cpu, nv30_transfer_rect_cpu },663{}664};665666for (method = methods; method->possible; method++) {667if (method->possible(nv30, filter, src, dst)) {668method->execute(nv30, filter, src, dst);669return;670}671}672673assert(0);674}675676void677nv30_transfer_push_data(struct nouveau_context *nv,678struct nouveau_bo *bo, unsigned offset, unsigned domain,679unsigned size, void *data)680{681/* use ifc, or scratch + copy_data? */682fprintf(stderr, "nv30: push_data not implemented\n");683}684685void686nv30_transfer_copy_data(struct nouveau_context *nv,687struct nouveau_bo *dst, unsigned d_off, unsigned d_dom,688struct nouveau_bo *src, unsigned s_off, unsigned s_dom,689unsigned size)690{691struct nv04_fifo *fifo = nv->screen->channel->data;692struct nouveau_pushbuf_refn refs[] = {693{ src, s_dom | NOUVEAU_BO_RD },694{ dst, d_dom | NOUVEAU_BO_WR },695};696struct nouveau_pushbuf *push = nv->pushbuf;697unsigned pages, lines;698699pages = size >> 12;700size -= (pages << 12);701702BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);703PUSH_DATA (push, (s_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);704PUSH_DATA (push, (d_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);705706while (pages) {707lines = (pages > 2047) ? 2047 : pages;708pages -= lines;709710if (nouveau_pushbuf_space(push, 32, 2, 0) ||711nouveau_pushbuf_refn (push, refs, 2))712return;713714BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);715PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);716PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);717PUSH_DATA (push, 4096);718PUSH_DATA (push, 4096);719PUSH_DATA (push, 4096);720PUSH_DATA (push, lines);721PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |722NV03_M2MF_FORMAT_OUTPUT_INC_1);723PUSH_DATA (push, 0x00000000);724BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);725PUSH_DATA (push, 0x00000000);726BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);727PUSH_DATA (push, 0x00000000);728729s_off += (lines << 12);730d_off += (lines << 12);731}732733if (size) {734if (nouveau_pushbuf_space(push, 32, 2, 0) ||735nouveau_pushbuf_refn (push, refs, 2))736return;737738BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);739PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);740PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);741PUSH_DATA (push, size);742PUSH_DATA (push, size);743PUSH_DATA (push, size);744PUSH_DATA (push, 1);745PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |746NV03_M2MF_FORMAT_OUTPUT_INC_1);747PUSH_DATA (push, 0x00000000);748BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);749PUSH_DATA (push, 0x00000000);750BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);751PUSH_DATA (push, 0x00000000);752}753}754755756