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"
14 struct nvfx_transfer
{
15 struct pipe_transfer base
;
16 struct pipe_surface
*surface
;
21 nvfx_compatible_transfer_tex(struct pipe_resource
*pt
, unsigned width
, unsigned height
,
23 struct pipe_resource
*template)
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
;
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
;
39 static unsigned nvfx_transfer_bind_flags( unsigned transfer_usage
)
44 if (transfer_usage
& PIPE_TRANSFER_WRITE
)
45 bind
|= PIPE_BIND_BLIT_SOURCE
;
47 if (transfer_usage
& PIPE_TRANSFER_READ
)
48 bind
|= PIPE_BIND_BLIT_DESTINATION
;
54 struct pipe_transfer
*
55 nvfx_miptree_transfer_new(struct pipe_context
*pipe
,
56 struct pipe_resource
*pt
,
57 struct pipe_subresource sr
,
59 const struct pipe_box
*box
)
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
);
68 no_transfer
= debug_get_bool_option("NOUVEAU_NO_TRANSFER", FALSE
);
71 tx
= CALLOC_STRUCT(nvfx_transfer
);
75 /* Don't handle 3D transfers yet.
77 assert(box
->depth
== 1);
79 pipe_resource_reference(&tx
->base
.resource
, pt
);
81 tx
->base
.usage
= usage
;
83 tx
->base
.stride
= mt
->level
[sr
.level
].pitch
;
85 /* Direct access to texture */
86 if ((pt
->usage
== PIPE_USAGE_DYNAMIC
||
88 pt
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)
92 /* XXX: just call the internal nvfx function.
94 tx
->surface
= pscreen
->get_tex_surface(pscreen
, pt
,
103 nvfx_compatible_transfer_tex(pt
, box
->width
, box
->height
, bind
, &tx_tex_template
);
105 tx_tex
= pscreen
->resource_create(pscreen
, &tx_tex_template
);
112 tx
->base
.stride
= ((struct nvfx_miptree
*)tx_tex
)->level
[0].pitch
;
114 tx
->surface
= pscreen
->get_tex_surface(pscreen
, tx_tex
,
118 pipe_resource_reference(&tx_tex
, NULL
);
122 pipe_surface_reference(&tx
->surface
, NULL
);
127 if (usage
& PIPE_TRANSFER_READ
) {
128 struct nvfx_screen
*nvscreen
= nvfx_screen(pscreen
);
129 struct pipe_surface
*src
;
131 src
= pscreen
->get_tex_surface(pscreen
, pt
,
132 sr
.face
, sr
.level
, box
->z
,
133 0 /*PIPE_BIND_BLIT_SOURCE*/);
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
,
141 box
->width
, box
->height
);
143 pipe_surface_reference(&src
, NULL
);
150 nvfx_miptree_transfer_del(struct pipe_context
*pipe
,
151 struct pipe_transfer
*ptx
)
153 struct nvfx_transfer
*tx
= (struct nvfx_transfer
*)ptx
;
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
;
160 dst
= pscreen
->get_tex_surface(pscreen
,
165 0 /*PIPE_BIND_BLIT_DESTINATION*/);
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
,
171 ptx
->box
.width
, ptx
->box
.height
);
173 pipe_surface_reference(&dst
, NULL
);
176 pipe_surface_reference(&tx
->surface
, NULL
);
177 pipe_resource_reference(&ptx
->resource
, NULL
);
182 nvfx_miptree_transfer_map(struct pipe_context
*pipe
, struct pipe_transfer
*ptx
)
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
));
192 return map
+ ns
->base
.offset
;
194 return (map
+ ns
->base
.offset
+
195 ptx
->box
.y
* ns
->pitch
+
196 ptx
->box
.x
* util_format_get_blocksize(ptx
->resource
->format
));
200 nvfx_miptree_transfer_unmap(struct pipe_context
*pipe
, struct pipe_transfer
*ptx
)
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
;
206 nouveau_screen_bo_unmap(pscreen
, mt
->base
.bo
);