1 #include "pipe/p_state.h"
2 #include "pipe/p_defines.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
5 #include "util/u_memory.h"
6 #include "util/u_math.h"
7 #include "nouveau/nouveau_winsys.h"
8 #include "nvfx_context.h"
9 #include "nvfx_screen.h"
10 #include "nvfx_state.h"
12 struct nvfx_transfer {
13 struct pipe_transfer base;
14 struct pipe_surface *surface;
19 nvfx_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height,
20 struct pipe_texture *template)
22 memset(template, 0, sizeof(struct pipe_texture));
23 template->target = pt->target;
24 template->format = pt->format;
25 template->width0 = width;
26 template->height0 = height;
28 template->last_level = 0;
29 template->nr_samples = pt->nr_samples;
31 template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
32 NOUVEAU_TEXTURE_USAGE_LINEAR;
35 static struct pipe_transfer *
36 nvfx_transfer_new(struct pipe_context *pipe, struct pipe_texture *pt,
37 unsigned face, unsigned level, unsigned zslice,
38 enum pipe_transfer_usage usage,
39 unsigned x, unsigned y, unsigned w, unsigned h)
41 struct pipe_screen *pscreen = pipe->screen;
42 struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
43 struct nvfx_transfer *tx;
44 struct pipe_texture tx_tex_template, *tx_tex;
45 static int no_transfer = -1;
47 no_transfer = debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/);
49 tx = CALLOC_STRUCT(nvfx_transfer);
53 pipe_texture_reference(&tx->base.texture, pt);
58 tx->base.stride = mt->level[level].pitch;
59 tx->base.usage = usage;
61 tx->base.level = level;
62 tx->base.zslice = zslice;
64 /* Direct access to texture */
65 if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || no_transfer) &&
66 pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
69 tx->surface = pscreen->get_tex_surface(pscreen, pt,
71 pipe_transfer_buffer_flags(&tx->base));
77 nvfx_compatible_transfer_tex(pt, w, h, &tx_tex_template);
79 tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
86 tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch;
88 tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
90 pipe_transfer_buffer_flags(&tx->base));
92 pipe_texture_reference(&tx_tex, NULL);
96 pipe_surface_reference(&tx->surface, NULL);
101 if (usage & PIPE_TRANSFER_READ) {
102 struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
103 struct pipe_surface *src;
105 src = pscreen->get_tex_surface(pscreen, pt,
107 PIPE_BUFFER_USAGE_GPU_READ);
109 /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
110 /* TODO: Check if SIFM can un-swizzle */
111 nvscreen->eng2d->copy(nvscreen->eng2d,
116 pipe_surface_reference(&src, NULL);
123 nvfx_transfer_del(struct pipe_context *pipe,
124 struct pipe_transfer *ptx)
126 struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
128 if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) {
129 struct pipe_screen *pscreen = pipe->screen;
130 struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
131 struct pipe_surface *dst;
133 dst = pscreen->get_tex_surface(pscreen, ptx->texture,
134 ptx->face, ptx->level, ptx->zslice,
135 PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER);
137 /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
138 nvscreen->eng2d->copy(nvscreen->eng2d,
139 dst, tx->base.x, tx->base.y,
141 tx->base.width, tx->base.height);
143 pipe_surface_reference(&dst, NULL);
146 pipe_surface_reference(&tx->surface, NULL);
147 pipe_texture_reference(&ptx->texture, NULL);
152 nvfx_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
154 struct pipe_screen *pscreen = pipe->screen;
155 struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
156 struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
157 struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
158 void *map = pipe_buffer_map(pscreen, mt->buffer,
159 pipe_transfer_buffer_flags(ptx));
162 return map + ns->base.offset;
164 return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format);
168 nvfx_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
170 struct pipe_screen *pscreen = pipe->screen;
171 struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
172 struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
174 pipe_buffer_unmap(pscreen, mt->buffer);
178 nvfx_init_transfer_functions(struct nvfx_context *nvfx)
180 nvfx->pipe.get_tex_transfer = nvfx_transfer_new;
181 nvfx->pipe.tex_transfer_destroy = nvfx_transfer_del;
182 nvfx->pipe.transfer_map = nvfx_transfer_map;
183 nvfx->pipe.transfer_unmap = nvfx_transfer_unmap;