1 #include <pipe/p_state.h>
2 #include <pipe/p_defines.h>
3 #include <pipe/p_inlines.h>
4 #include <util/u_memory.h>
5 #include <nouveau/nouveau_winsys.h>
6 #include "nv20_context.h"
7 #include "nv20_screen.h"
8 #include "nv20_state.h"
10 struct nv20_transfer {
11 struct pipe_transfer base;
12 struct pipe_surface *surface;
16 static unsigned nv20_usage_tx_to_buf(unsigned tx_usage)
19 case PIPE_TRANSFER_READ:
20 return PIPE_BUFFER_USAGE_CPU_READ;
21 case PIPE_TRANSFER_WRITE:
22 return PIPE_BUFFER_USAGE_CPU_WRITE;
23 case PIPE_TRANSFER_READ_WRITE:
24 return PIPE_BUFFER_USAGE_CPU_READ_WRITE;
33 nv20_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
34 struct pipe_texture *template)
36 memset(template, 0, sizeof(struct pipe_texture));
37 template->target = pt->target;
38 template->format = pt->format;
39 template->width[0] = pt->width[level];
40 template->height[0] = pt->height[level];
41 template->depth[0] = 1;
42 template->block = pt->block;
43 template->nblocksx[0] = pt->nblocksx[level];
44 template->nblocksy[0] = pt->nblocksx[level];
45 template->last_level = 0;
46 template->compressed = pt->compressed;
47 template->nr_samples = pt->nr_samples;
49 template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
50 NOUVEAU_TEXTURE_USAGE_LINEAR;
53 static struct pipe_transfer *
54 nv20_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
55 unsigned face, unsigned level, unsigned zslice,
56 enum pipe_transfer_usage usage,
57 unsigned x, unsigned y, unsigned w, unsigned h)
59 struct nv20_miptree *mt = (struct nv20_miptree *)pt;
60 struct nv20_transfer *tx;
61 struct pipe_texture tx_tex_template, *tx_tex;
63 tx = CALLOC_STRUCT(nv20_transfer);
67 tx->base.refcount = 1;
68 pipe_texture_reference(&tx->base.texture, pt);
69 tx->base.format = pt->format;
74 tx->base.block = pt->block;
75 tx->base.nblocksx = pt->nblocksx[level];
76 tx->base.nblocksy = pt->nblocksy[level];
77 tx->base.stride = mt->level[level].pitch;
78 tx->base.usage = usage;
80 tx->base.level = level;
81 tx->base.zslice = zslice;
83 /* Direct access to texture */
84 if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
85 debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
86 pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
89 tx->surface = pscreen->get_tex_surface(pscreen, pt,
91 nv20_usage_tx_to_buf(usage));
97 nv20_compatible_transfer_tex(pt, level, &tx_tex_template);
99 tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
106 tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
108 nv20_usage_tx_to_buf(usage));
110 pipe_texture_reference(&tx_tex, NULL);
114 pipe_surface_reference(&tx->surface, NULL);
119 if (usage != PIPE_TRANSFER_WRITE) {
120 struct nv20_screen *nvscreen = nv20_screen(pscreen);
121 struct pipe_surface *src;
123 src = pscreen->get_tex_surface(pscreen, pt,
125 PIPE_BUFFER_USAGE_GPU_READ);
127 /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
128 /* TODO: Check if SIFM can un-swizzle */
129 nvscreen->eng2d->copy(nvscreen->eng2d,
132 src->width, src->height);
134 pipe_surface_reference(&src, NULL);
141 nv20_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx)
143 struct pipe_transfer *ptx = *pptx;
144 struct nv20_transfer *tx = (struct nv20_transfer *)ptx;
146 if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) {
147 struct nv20_screen *nvscreen = nv20_screen(pscreen);
148 struct pipe_surface *dst;
150 dst = pscreen->get_tex_surface(pscreen, ptx->texture,
151 ptx->face, ptx->level, ptx->zslice,
152 PIPE_BUFFER_USAGE_GPU_WRITE);
154 /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
155 nvscreen->eng2d->copy(nvscreen->eng2d,
158 dst->width, dst->height);
160 pipe_surface_reference(&dst, NULL);
167 pipe_surface_reference(&tx->surface, NULL);
168 pipe_texture_reference(&ptx->texture, NULL);
173 nv20_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
175 struct nv20_transfer *tx = (struct nv20_transfer *)ptx;
176 struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
177 struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture;
178 void *map = pipe_buffer_map(pscreen, mt->buffer,
179 nv20_usage_tx_to_buf(ptx->usage));
181 return map + ns->base.offset +
182 ptx->y * ns->pitch + ptx->x * ptx->block.size;
186 nv20_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
188 struct nv20_transfer *tx = (struct nv20_transfer *)ptx;
189 struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture;
191 pipe_buffer_unmap(pscreen, mt->buffer);
195 nv20_screen_init_transfer_functions(struct pipe_screen *pscreen)
197 pscreen->get_tex_transfer = nv20_transfer_new;
198 pscreen->tex_transfer_release = nv20_transfer_del;
199 pscreen->transfer_map = nv20_transfer_map;
200 pscreen->transfer_unmap = nv20_transfer_unmap;