Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / nouveau / nouveau_screen.c
1 #include "pipe/p_defines.h"
2 #include "pipe/p_screen.h"
3 #include "pipe/p_state.h"
4
5 #include "util/u_memory.h"
6 #include "util/u_inlines.h"
7 #include "util/u_format.h"
8 #include "util/u_format_s3tc.h"
9 #include "util/u_string.h"
10
11 #include <stdio.h>
12 #include <errno.h>
13
14 #include "nouveau/nouveau_bo.h"
15 #include "nouveau/nouveau_mm.h"
16 #include "nouveau_winsys.h"
17 #include "nouveau_screen.h"
18 #include "nouveau_fence.h"
19
20 /* XXX this should go away */
21 #include "state_tracker/drm_driver.h"
22 #include "util/u_simple_screen.h"
23
24 static const char *
25 nouveau_screen_get_name(struct pipe_screen *pscreen)
26 {
27         struct nouveau_device *dev = nouveau_screen(pscreen)->device;
28         static char buffer[128];
29
30         util_snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
31         return buffer;
32 }
33
34 static const char *
35 nouveau_screen_get_vendor(struct pipe_screen *pscreen)
36 {
37         return "nouveau";
38 }
39
40
41
42 struct nouveau_bo *
43 nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
44                       unsigned usage, unsigned bind, unsigned size)
45 {
46         struct nouveau_device *dev = nouveau_screen(pscreen)->device;
47         struct nouveau_bo *bo = NULL;
48         uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0;
49         int ret;
50
51         if (bind & PIPE_BIND_VERTEX_BUFFER)
52                 flags |= nouveau_screen(pscreen)->vertex_buffer_flags;
53         else if (bind & PIPE_BIND_INDEX_BUFFER)
54                 flags |= nouveau_screen(pscreen)->index_buffer_flags;
55
56         if (bind & (PIPE_BIND_RENDER_TARGET |
57                         PIPE_BIND_DEPTH_STENCIL |
58                         PIPE_BIND_SCANOUT |
59                         PIPE_BIND_DISPLAY_TARGET |
60                         PIPE_BIND_SAMPLER_VIEW))
61         {
62                 /* TODO: this may be incorrect or suboptimal */
63                 if (!(bind & PIPE_BIND_SCANOUT))
64                         flags |= NOUVEAU_BO_GART;
65                 if (usage != PIPE_USAGE_DYNAMIC)
66                         flags |= NOUVEAU_BO_VRAM;
67
68                 if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
69                         if (bind & PIPE_BIND_DEPTH_STENCIL)
70                                 tile_flags = 0x2800;
71                         else
72                                 tile_flags = 0x7000;
73                 }
74         }
75
76         ret = nouveau_bo_new_tile(dev, flags, alignment, size,
77                                   tile_mode, tile_flags, &bo);
78         if (ret)
79                 return NULL;
80
81         return bo;
82 }
83
84 void *
85 nouveau_screen_bo_map(struct pipe_screen *pscreen,
86                       struct nouveau_bo *bo,
87                       unsigned map_flags)
88 {
89         int ret;
90
91         ret = nouveau_bo_map(bo, map_flags);
92         if (ret) {
93                 debug_printf("map failed: %d\n", ret);
94                 return NULL;
95         }
96
97         return bo->map;
98 }
99
100 void *
101 nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct nouveau_bo *bo,
102                             unsigned offset, unsigned length, unsigned flags)
103 {
104         int ret;
105
106         ret = nouveau_bo_map_range(bo, offset, length, flags);
107         if (ret) {
108                 nouveau_bo_unmap(bo);
109                 if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
110                         debug_printf("map_range failed: %d\n", ret);
111                 return NULL;
112         }
113
114         return (char *)bo->map - offset; /* why gallium? why? */
115 }
116
117 void
118 nouveau_screen_bo_map_flush_range(struct pipe_screen *pscreen, struct nouveau_bo *bo,
119                                   unsigned offset, unsigned length)
120 {
121         nouveau_bo_map_flush(bo, offset, length);
122 }
123
124 void
125 nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct nouveau_bo *bo)
126 {
127         nouveau_bo_unmap(bo);
128 }
129
130 void
131 nouveau_screen_bo_release(struct pipe_screen *pscreen, struct nouveau_bo *bo)
132 {
133         nouveau_bo_ref(NULL, &bo);
134 }
135
136 static void
137 nouveau_screen_fence_ref(struct pipe_screen *pscreen,
138                          struct pipe_fence_handle **ptr,
139                          struct pipe_fence_handle *pfence)
140 {
141         nouveau_fence_ref(nouveau_fence(pfence), (struct nouveau_fence **)ptr);
142 }
143
144 static boolean
145 nouveau_screen_fence_signalled(struct pipe_screen *screen,
146                                struct pipe_fence_handle *pfence)
147 {
148         return nouveau_fence_signalled(nouveau_fence(pfence));
149 }
150
151 static boolean
152 nouveau_screen_fence_finish(struct pipe_screen *screen,
153                             struct pipe_fence_handle *pfence,
154                             uint64_t timeout)
155 {
156         return nouveau_fence_wait(nouveau_fence(pfence));
157 }
158
159
160 struct nouveau_bo *
161 nouveau_screen_bo_from_handle(struct pipe_screen *pscreen,
162                               struct winsys_handle *whandle,
163                               unsigned *out_stride)
164 {
165         struct nouveau_device *dev = nouveau_screen(pscreen)->device;
166         struct nouveau_bo *bo = 0;
167         int ret;
168  
169         ret = nouveau_bo_handle_ref(dev, whandle->handle, &bo);
170         if (ret) {
171                 debug_printf("%s: ref name 0x%08x failed with %d\n",
172                              __FUNCTION__, whandle->handle, ret);
173                 return NULL;
174         }
175
176         *out_stride = whandle->stride;
177         return bo;
178 }
179
180
181 boolean
182 nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,
183                              struct nouveau_bo *bo,
184                              unsigned stride,
185                              struct winsys_handle *whandle)
186 {
187         whandle->stride = stride;
188
189         if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { 
190                 return nouveau_bo_handle_get(bo, &whandle->handle) == 0;
191         } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
192                 whandle->handle = bo->handle;
193                 return TRUE;
194         } else {
195                 return FALSE;
196         }
197 }
198
199 int
200 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
201 {
202         struct pipe_screen *pscreen = &screen->base;
203         int ret;
204
205         ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
206                                     512*1024, &screen->channel);
207         if (ret)
208                 return ret;
209         screen->device = dev;
210
211         pscreen->get_name = nouveau_screen_get_name;
212         pscreen->get_vendor = nouveau_screen_get_vendor;
213
214         pscreen->fence_reference = nouveau_screen_fence_ref;
215         pscreen->fence_signalled = nouveau_screen_fence_signalled;
216         pscreen->fence_finish = nouveau_screen_fence_finish;
217
218         util_format_s3tc_init();
219
220         screen->mm_GART = nouveau_mm_create(dev,
221                                             NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
222                                             0x000);
223         screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0x000);
224         return 0;
225 }
226
227 void
228 nouveau_screen_fini(struct nouveau_screen *screen)
229 {
230         struct pipe_winsys *ws = screen->base.winsys;
231
232         nouveau_mm_destroy(screen->mm_GART);
233         nouveau_mm_destroy(screen->mm_VRAM);
234
235         nouveau_channel_free(&screen->channel);
236
237         if (ws)
238                 ws->destroy(ws);
239 }
240