Squashed commit of the following:
[profile/ivi/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