r600g: make r600_db_format static.
[mesa.git] / src / gallium / drivers / nvfx / nvfx_transfer.c
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"
11 #include "nvfx_resource.h"
12 #include "nvfx_transfer.h"
13
14 struct nvfx_transfer {
15 struct pipe_transfer base;
16 struct pipe_surface *surface;
17 boolean direct;
18 };
19
20 static void
21 nvfx_compatible_transfer_tex(struct pipe_resource *pt, unsigned width, unsigned height,
22 unsigned bind,
23 struct pipe_resource *template)
24 {
25 memset(template, 0, sizeof(struct pipe_resource));
26 template->target = pt->target;
27 template->format = pt->format;
28 template->width0 = width;
29 template->height0 = height;
30 template->depth0 = 1;
31 template->last_level = 0;
32 template->nr_samples = pt->nr_samples;
33 template->bind = bind;
34 template->usage = PIPE_USAGE_DYNAMIC;
35 template->flags = NVFX_RESOURCE_FLAG_LINEAR;
36 }
37
38
39 static unsigned nvfx_transfer_bind_flags( unsigned transfer_usage )
40 {
41 unsigned bind = 0;
42
43 #if 0
44 if (transfer_usage & PIPE_TRANSFER_WRITE)
45 bind |= PIPE_BIND_BLIT_SOURCE;
46
47 if (transfer_usage & PIPE_TRANSFER_READ)
48 bind |= PIPE_BIND_BLIT_DESTINATION;
49 #endif
50
51 return bind;
52 }
53
54 struct pipe_transfer *
55 nvfx_miptree_transfer_new(struct pipe_context *pipe,
56 struct pipe_resource *pt,
57 struct pipe_subresource sr,
58 unsigned usage,
59 const struct pipe_box *box)
60 {
61 struct pipe_screen *pscreen = pipe->screen;
62 struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
63 struct nvfx_transfer *tx;
64 struct pipe_resource tx_tex_template, *tx_tex;
65 static int no_transfer = -1;
66 unsigned bind = nvfx_transfer_bind_flags(usage);
67 if(no_transfer < 0)
68 no_transfer = debug_get_bool_option("NOUVEAU_NO_TRANSFER", FALSE);
69
70
71 tx = CALLOC_STRUCT(nvfx_transfer);
72 if (!tx)
73 return NULL;
74
75 /* Don't handle 3D transfers yet.
76 */
77 assert(box->depth == 1);
78
79 pipe_resource_reference(&tx->base.resource, pt);
80 tx->base.sr = sr;
81 tx->base.usage = usage;
82 tx->base.box = *box;
83 tx->base.stride = mt->level[sr.level].pitch;
84
85 /* Direct access to texture */
86 if ((pt->usage == PIPE_USAGE_DYNAMIC ||
87 no_transfer) &&
88 pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
89 {
90 tx->direct = true;
91
92 /* XXX: just call the internal nvfx function.
93 */
94 tx->surface = pscreen->get_tex_surface(pscreen, pt,
95 sr.face, sr.level,
96 box->z,
97 bind);
98 return &tx->base;
99 }
100
101 tx->direct = false;
102
103 nvfx_compatible_transfer_tex(pt, box->width, box->height, bind, &tx_tex_template);
104
105 tx_tex = pscreen->resource_create(pscreen, &tx_tex_template);
106 if (!tx_tex)
107 {
108 FREE(tx);
109 return NULL;
110 }
111
112 tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch;
113
114 tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
115 0, 0, 0,
116 bind);
117
118 pipe_resource_reference(&tx_tex, NULL);
119
120 if (!tx->surface)
121 {
122 pipe_surface_reference(&tx->surface, NULL);
123 FREE(tx);
124 return NULL;
125 }
126
127 if (usage & PIPE_TRANSFER_READ) {
128 struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
129 struct pipe_surface *src;
130
131 src = pscreen->get_tex_surface(pscreen, pt,
132 sr.face, sr.level, box->z,
133 0 /*PIPE_BIND_BLIT_SOURCE*/);
134
135 /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
136 /* TODO: Check if SIFM can un-swizzle */
137 nvscreen->eng2d->copy(nvscreen->eng2d,
138 tx->surface, 0, 0,
139 src,
140 box->x, box->y,
141 box->width, box->height);
142
143 pipe_surface_reference(&src, NULL);
144 }
145
146 return &tx->base;
147 }
148
149 void
150 nvfx_miptree_transfer_del(struct pipe_context *pipe,
151 struct pipe_transfer *ptx)
152 {
153 struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
154
155 if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) {
156 struct pipe_screen *pscreen = pipe->screen;
157 struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
158 struct pipe_surface *dst;
159
160 dst = pscreen->get_tex_surface(pscreen,
161 ptx->resource,
162 ptx->sr.face,
163 ptx->sr.level,
164 ptx->box.z,
165 0 /*PIPE_BIND_BLIT_DESTINATION*/);
166
167 /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
168 nvscreen->eng2d->copy(nvscreen->eng2d,
169 dst, ptx->box.x, ptx->box.y,
170 tx->surface, 0, 0,
171 ptx->box.width, ptx->box.height);
172
173 pipe_surface_reference(&dst, NULL);
174 }
175
176 pipe_surface_reference(&tx->surface, NULL);
177 pipe_resource_reference(&ptx->resource, NULL);
178 FREE(ptx);
179 }
180
181 void *
182 nvfx_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
183 {
184 struct pipe_screen *pscreen = pipe->screen;
185 struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
186 struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
187 struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
188 uint8_t *map = nouveau_screen_bo_map(pscreen, mt->base.bo,
189 nouveau_screen_transfer_flags(ptx->usage));
190
191 if(!tx->direct)
192 return map + ns->base.offset;
193 else
194 return (map + ns->base.offset +
195 ptx->box.y * ns->pitch +
196 ptx->box.x * util_format_get_blocksize(ptx->resource->format));
197 }
198
199 void
200 nvfx_miptree_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
201 {
202 struct pipe_screen *pscreen = pipe->screen;
203 struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
204 struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
205
206 nouveau_screen_bo_unmap(pscreen, mt->base.bo);
207 }