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
;