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 "util/u_staging.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_staging_transfer
16 struct util_staging_transfer base
;
22 struct pipe_transfer
*
23 nvfx_transfer_new(struct pipe_context
*pipe
,
24 struct pipe_resource
*pt
,
27 const struct pipe_box
*box
)
29 if((usage
& (PIPE_TRANSFER_UNSYNCHRONIZED
| PIPE_TRANSFER_DONTBLOCK
)) == PIPE_TRANSFER_DONTBLOCK
)
31 struct nouveau_bo
* bo
= ((struct nvfx_resource
*)pt
)->bo
;
32 if(bo
&& nouveau_bo_busy(bo
, NOUVEAU_BO_WR
))
36 if(pt
->target
== PIPE_BUFFER
)
38 // it would be nice if we could avoid all this ridiculous overhead...
39 struct pipe_transfer
* tx
;
40 struct nvfx_buffer
* buffer
= nvfx_buffer(pt
);
42 tx
= CALLOC_STRUCT(pipe_transfer
);
46 pipe_resource_reference(&tx
->resource
, pt
);
51 tx
->layer_stride
= tx
->stride
= util_format_get_stride(pt
->format
, box
->width
);
52 tx
->data
= buffer
->data
+ util_format_get_stride(pt
->format
, box
->x
);
58 struct nvfx_staging_transfer
* tx
;
59 boolean direct
= !nvfx_resource_on_gpu(pt
) && pt
->flags
& NVFX_RESOURCE_FLAG_LINEAR
;
61 tx
= CALLOC_STRUCT(nvfx_staging_transfer
);
65 util_staging_transfer_init(pipe
, pt
, level
, usage
, box
, direct
, &tx
->base
);
69 tx
->base
.base
.stride
= nvfx_subresource_pitch(pt
, level
);
70 tx
->base
.base
.layer_stride
= tx
->base
.base
.stride
* u_minify(pt
->height0
, level
);
71 tx
->offset
= nvfx_subresource_offset(pt
, box
->z
, level
, box
->z
)
72 + util_format_get_2d_size(pt
->format
, tx
->base
.base
.stride
, box
->y
)
73 + util_format_get_stride(pt
->format
, box
->x
);
77 tx
->base
.base
.stride
= nvfx_subresource_pitch(tx
->base
.staging_resource
, 0);
78 tx
->base
.base
.layer_stride
= tx
->base
.base
.stride
* tx
->base
.staging_resource
->height0
;
82 assert(tx
->base
.base
.stride
);
84 return &tx
->base
.base
;
88 static void nvfx_buffer_dirty_interval(struct nvfx_buffer
* buffer
, unsigned begin
, unsigned size
, boolean unsynchronized
)
90 struct nvfx_screen
* screen
= nvfx_screen(buffer
->base
.base
.screen
);
91 buffer
->last_update_static
= buffer
->bytes_to_draw_until_static
< 0;
92 if(buffer
->dirty_begin
== buffer
->dirty_end
)
94 buffer
->dirty_begin
= begin
;
95 buffer
->dirty_end
= begin
+ size
;
96 buffer
->dirty_unsynchronized
= unsynchronized
;
100 buffer
->dirty_begin
= MIN2(buffer
->dirty_begin
, begin
);
101 buffer
->dirty_end
= MAX2(buffer
->dirty_end
, begin
+ size
);
102 buffer
->dirty_unsynchronized
&= unsynchronized
;
107 // TODO: revisit this, it doesn't seem quite right
108 //printf("UNSYNC UPDATE %p %u %u\n", buffer, begin, size);
109 buffer
->bytes_to_draw_until_static
+= size
* screen
->static_reuse_threshold
;
112 buffer
->bytes_to_draw_until_static
= buffer
->size
* screen
->static_reuse_threshold
;
115 static void nvfx_transfer_flush_region( struct pipe_context
*pipe
,
116 struct pipe_transfer
*ptx
,
117 const struct pipe_box
*box
)
119 if(ptx
->resource
->target
== PIPE_BUFFER
&& (ptx
->usage
& PIPE_TRANSFER_FLUSH_EXPLICIT
))
121 struct nvfx_buffer
* buffer
= nvfx_buffer(ptx
->resource
);
122 nvfx_buffer_dirty_interval(buffer
,
123 (uint8_t*)ptx
->data
- buffer
->data
+ util_format_get_stride(buffer
->base
.base
.format
, box
->x
),
124 util_format_get_stride(buffer
->base
.base
.format
, box
->width
),
125 !!(ptx
->usage
& PIPE_TRANSFER_UNSYNCHRONIZED
));
130 nvfx_transfer_destroy(struct pipe_context
*pipe
, struct pipe_transfer
*ptx
)
132 if(ptx
->resource
->target
== PIPE_BUFFER
)
134 struct nvfx_buffer
* buffer
= nvfx_buffer(ptx
->resource
);
135 if((ptx
->usage
& (PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_FLUSH_EXPLICIT
)) == PIPE_TRANSFER_WRITE
)
136 nvfx_buffer_dirty_interval(buffer
,
137 (uint8_t*)ptx
->data
- buffer
->data
,
139 !!(ptx
->usage
& PIPE_TRANSFER_UNSYNCHRONIZED
));
140 pipe_resource_reference(&ptx
->resource
, 0);
145 struct nouveau_channel
* chan
= nvfx_context(pipe
)->screen
->base
.channel
;
146 util_staging_transfer_destroy(pipe
, ptx
);
153 nvfx_transfer_map(struct pipe_context
*pipe
, struct pipe_transfer
*ptx
)
155 if(ptx
->resource
->target
== PIPE_BUFFER
)
159 struct nvfx_staging_transfer
*tx
= (struct nvfx_staging_transfer
*)ptx
;
162 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)tx
->base
.staging_resource
;
163 uint8_t *map
= nouveau_screen_bo_map(pipe
->screen
, mt
->base
.bo
, nouveau_screen_transfer_flags(ptx
->usage
));
164 ptx
->data
= map
+ tx
->offset
;
173 nvfx_transfer_unmap(struct pipe_context
*pipe
, struct pipe_transfer
*ptx
)
175 if(ptx
->resource
->target
!= PIPE_BUFFER
)
177 struct nvfx_staging_transfer
*tx
= (struct nvfx_staging_transfer
*)ptx
;
178 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)tx
->base
.staging_resource
;
182 nouveau_screen_bo_unmap(pipe
->screen
, mt
->base
.bo
);
188 static void nvfx_transfer_inline_write( struct pipe_context
*pipe
,
189 struct pipe_resource
*pr
,
192 const struct pipe_box
*box
,
195 unsigned slice_stride
)
197 if(pr
->target
!= PIPE_BUFFER
)
199 u_default_transfer_inline_write(pipe
, pr
, level
, usage
, box
, data
, stride
, slice_stride
);
203 struct nvfx_buffer
* buffer
= nvfx_buffer(pr
);
204 unsigned begin
= util_format_get_stride(pr
->format
, box
->x
);
205 unsigned size
= util_format_get_stride(pr
->format
, box
->width
);
206 memcpy(buffer
->data
+ begin
, data
, size
);
207 nvfx_buffer_dirty_interval(buffer
, begin
, size
,
208 !!(pr
->flags
& PIPE_TRANSFER_UNSYNCHRONIZED
));
213 nvfx_init_transfer_functions(struct pipe_context
*pipe
)
215 pipe
->get_transfer
= nvfx_transfer_new
;
216 pipe
->transfer_map
= nvfx_transfer_map
;
217 pipe
->transfer_flush_region
= nvfx_transfer_flush_region
;
218 pipe
->transfer_unmap
= nvfx_transfer_unmap
;
219 pipe
->transfer_destroy
= nvfx_transfer_destroy
;
220 pipe
->transfer_inline_write
= nvfx_transfer_inline_write
;