Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / nvfx / nvfx_buffer.c
1
2 #include "util/u_inlines.h"
3 #include "util/u_memory.h"
4 #include "util/u_math.h"
5
6 #include "nouveau/nouveau_screen.h"
7 #include "nouveau/nouveau_winsys.h"
8 #include "nvfx_resource.h"
9
10
11 /* Currently using separate implementations for buffers and textures,
12 * even though gallium has a unified abstraction of these objects.
13 * Eventually these should be combined, and mechanisms like transfers
14 * be adapted to work for both buffer and texture uploads.
15 */
16 static void nvfx_buffer_destroy(struct pipe_screen *pscreen,
17 struct pipe_resource *presource)
18 {
19 struct nvfx_resource *buffer = nvfx_resource(presource);
20
21 nouveau_screen_bo_release(pscreen, buffer->bo);
22 FREE(buffer);
23 }
24
25
26
27
28 /* Utility functions for transfer create/destroy are hooked in and
29 * just record the arguments to those functions.
30 */
31 static void *
32 nvfx_buffer_transfer_map( struct pipe_context *pipe,
33 struct pipe_transfer *transfer )
34 {
35 struct nvfx_resource *buffer = nvfx_resource(transfer->resource);
36 uint8_t *map;
37
38 map = nouveau_screen_bo_map_range( pipe->screen,
39 buffer->bo,
40 transfer->box.x,
41 transfer->box.width,
42 nouveau_screen_transfer_flags(transfer->usage) );
43 if (map == NULL)
44 return NULL;
45
46 return map + transfer->box.x;
47 }
48
49
50
51 static void nvfx_buffer_transfer_flush_region( struct pipe_context *pipe,
52 struct pipe_transfer *transfer,
53 const struct pipe_box *box)
54 {
55 struct nvfx_resource *buffer = nvfx_resource(transfer->resource);
56
57 nouveau_screen_bo_map_flush_range(pipe->screen,
58 buffer->bo,
59 transfer->box.x + box->x,
60 box->width);
61 }
62
63 static void nvfx_buffer_transfer_unmap( struct pipe_context *pipe,
64 struct pipe_transfer *transfer )
65 {
66 struct nvfx_resource *buffer = nvfx_resource(transfer->resource);
67
68 nouveau_screen_bo_unmap(pipe->screen, buffer->bo);
69 }
70
71
72
73
74 struct u_resource_vtbl nvfx_buffer_vtbl =
75 {
76 u_default_resource_get_handle, /* get_handle */
77 nvfx_buffer_destroy, /* resource_destroy */
78 NULL, /* is_resource_referenced */
79 u_default_get_transfer, /* get_transfer */
80 u_default_transfer_destroy, /* transfer_destroy */
81 nvfx_buffer_transfer_map, /* transfer_map */
82 nvfx_buffer_transfer_flush_region, /* transfer_flush_region */
83 nvfx_buffer_transfer_unmap, /* transfer_unmap */
84 u_default_transfer_inline_write /* transfer_inline_write */
85 };
86
87
88
89 struct pipe_resource *
90 nvfx_buffer_create(struct pipe_screen *pscreen,
91 const struct pipe_resource *template)
92 {
93 struct nvfx_resource *buffer;
94
95 buffer = CALLOC_STRUCT(nvfx_resource);
96 if (!buffer)
97 return NULL;
98
99 buffer->base = *template;
100 buffer->vtbl = &nvfx_buffer_vtbl;
101 pipe_reference_init(&buffer->base.reference, 1);
102 buffer->base.screen = pscreen;
103
104 buffer->bo = nouveau_screen_bo_new(pscreen,
105 16,
106 buffer->base.usage,
107 buffer->base.bind,
108 buffer->base.width0);
109
110 if (buffer->bo == NULL)
111 goto fail;
112
113 return &buffer->base;
114
115 fail:
116 FREE(buffer);
117 return NULL;
118 }
119
120
121 struct pipe_resource *
122 nvfx_user_buffer_create(struct pipe_screen *pscreen,
123 void *ptr,
124 unsigned bytes,
125 unsigned usage)
126 {
127 struct nvfx_resource *buffer;
128
129 buffer = CALLOC_STRUCT(nvfx_resource);
130 if (!buffer)
131 return NULL;
132
133 pipe_reference_init(&buffer->base.reference, 1);
134 buffer->vtbl = &nvfx_buffer_vtbl;
135 buffer->base.screen = pscreen;
136 buffer->base.format = PIPE_FORMAT_R8_UNORM;
137 buffer->base.usage = PIPE_USAGE_IMMUTABLE;
138 buffer->base.bind = usage;
139 buffer->base.width0 = bytes;
140 buffer->base.height0 = 1;
141 buffer->base.depth0 = 1;
142
143 buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes);
144 if (!buffer->bo)
145 goto fail;
146
147 return &buffer->base;
148
149 fail:
150 FREE(buffer);
151 return NULL;
152 }
153