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 "os/os_time.h" 12 13 #include <stdio.h> 14 #include <errno.h> 15 #include <stdlib.h> 16 17 #include <nouveau_drm.h> 18 19 #include "nouveau_winsys.h" 20 #include "nouveau_screen.h" 21 #include "nouveau_context.h" 22 #include "nouveau_fence.h" 23 #include "nouveau_mm.h" 24 #include "nouveau_buffer.h" 25 26 /* XXX this should go away */ 27 #include "state_tracker/drm_driver.h" 28 29 int nouveau_mesa_debug = 0; 30 31 static const char * 32 nouveau_screen_get_name(struct pipe_screen *pscreen) 33 { 34 struct nouveau_device *dev = nouveau_screen(pscreen)->device; 35 static char buffer[128]; 36 37 util_snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); 38 return buffer; 39 } 40 41 static const char * 42 nouveau_screen_get_vendor(struct pipe_screen *pscreen) 43 { 44 return "nouveau"; 45 } 46 47 static const char * 48 nouveau_screen_get_device_vendor(struct pipe_screen *pscreen) 49 { 50 return "NVIDIA"; 51 } 52 53 static uint64_t 54 nouveau_screen_get_timestamp(struct pipe_screen *pscreen) 55 { 56 int64_t cpu_time = os_time_get() * 1000; 57 58 /* getparam of PTIMER_TIME takes about x10 as long (several usecs) */ 59 60 return cpu_time + nouveau_screen(pscreen)->cpu_gpu_time_delta; 61 } 62 63 static void 64 nouveau_screen_fence_ref(struct pipe_screen *pscreen, 65 struct pipe_fence_handle **ptr, 66 struct pipe_fence_handle *pfence) 67 { 68 nouveau_fence_ref(nouveau_fence(pfence), (struct nouveau_fence **)ptr); 69 } 70 71 static boolean 72 nouveau_screen_fence_finish(struct pipe_screen *screen, 73 struct pipe_context *ctx, 74 struct pipe_fence_handle *pfence, 75 uint64_t timeout) 76 { 77 if (!timeout) 78 return nouveau_fence_signalled(nouveau_fence(pfence)); 79 80 return nouveau_fence_wait(nouveau_fence(pfence), NULL); 81 } 82 83 84 struct nouveau_bo * 85 nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, 86 struct winsys_handle *whandle, 87 unsigned *out_stride) 88 { 89 struct nouveau_device *dev = nouveau_screen(pscreen)->device; 90 struct nouveau_bo *bo = 0; 91 int ret; 92 93 if (whandle->offset != 0) { 94 debug_printf("%s: attempt to import unsupported winsys offset %d\n", 95 __FUNCTION__, whandle->offset); 96 return NULL; 97 } 98 99 if (whandle->type != DRM_API_HANDLE_TYPE_SHARED && 100 whandle->type != DRM_API_HANDLE_TYPE_FD) { 101 debug_printf("%s: attempt to import unsupported handle type %d\n", 102 __FUNCTION__, whandle->type); 103 return NULL; 104 } 105 106 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) 107 ret = nouveau_bo_name_ref(dev, whandle->handle, &bo); 108 else 109 ret = nouveau_bo_prime_handle_ref(dev, whandle->handle, &bo); 110 111 if (ret) { 112 debug_printf("%s: ref name 0x%08x failed with %d\n", 113 __FUNCTION__, whandle->handle, ret); 114 return NULL; 115 } 116 117 *out_stride = whandle->stride; 118 return bo; 119 } 120 121 122 bool 123 nouveau_screen_bo_get_handle(struct pipe_screen *pscreen, 124 struct nouveau_bo *bo, 125 unsigned stride, 126 struct winsys_handle *whandle) 127 { 128 whandle->stride = stride; 129 130 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { 131 return nouveau_bo_name_get(bo, &whandle->handle) == 0; 132 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { 133 whandle->handle = bo->handle; 134 return true; 135 } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { 136 return nouveau_bo_set_prime(bo, (int *)&whandle->handle) == 0; 137 } else { 138 return false; 139 } 140 } 141 142 int 143 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) 144 { 145 struct pipe_screen *pscreen = &screen->base; 146 struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; 147 struct nvc0_fifo nvc0_data = { }; 148 uint64_t time; 149 int size, ret; 150 void *data; 151 union nouveau_bo_config mm_config; 152 153 char *nv_dbg = getenv("NOUVEAU_MESA_DEBUG"); 154 if (nv_dbg) 155 nouveau_mesa_debug = atoi(nv_dbg); 156 157 /* These must be set before any failure is possible, as the cleanup 158 * paths assume they're responsible for deleting them. 159 */ 160 screen->drm = nouveau_drm(&dev->object); 161 screen->device = dev; 162 163 /* 164 * this is initialized to 1 in nouveau_drm_screen_create after screen 165 * is fully constructed and added to the global screen list. 166 */ 167 screen->refcount = -1; 168 169 if (dev->chipset < 0xc0) { 170 data = &nv04_data; 171 size = sizeof(nv04_data); 172 } else { 173 data = &nvc0_data; 174 size = sizeof(nvc0_data); 175 } 176 177 /* 178 * Set default VRAM domain if not overridden 179 */ 180 if (!screen->vram_domain) { 181 if (dev->vram_size > 0) 182 screen->vram_domain = NOUVEAU_BO_VRAM; 183 else 184 screen->vram_domain = NOUVEAU_BO_GART; 185 } 186 187 ret = nouveau_object_new(&dev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, 188 data, size, &screen->channel); 189 if (ret) 190 return ret; 191 192 ret = nouveau_client_new(screen->device, &screen->client); 193 if (ret) 194 return ret; 195 ret = nouveau_pushbuf_new(screen->client, screen->channel, 196 4, 512 * 1024, 1, 197 &screen->pushbuf); 198 if (ret) 199 return ret; 200 201 /* getting CPU time first appears to be more accurate */ 202 screen->cpu_gpu_time_delta = os_time_get(); 203 204 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_PTIMER_TIME, &time); 205 if (!ret) 206 screen->cpu_gpu_time_delta = time - screen->cpu_gpu_time_delta * 1000; 207 208 pscreen->get_name = nouveau_screen_get_name; 209 pscreen->get_vendor = nouveau_screen_get_vendor; 210 pscreen->get_device_vendor = nouveau_screen_get_device_vendor; 211 212 pscreen->get_timestamp = nouveau_screen_get_timestamp; 213 214 pscreen->fence_reference = nouveau_screen_fence_ref; 215 pscreen->fence_finish = nouveau_screen_fence_finish; 216 217 util_format_s3tc_init(); 218 219 screen->lowmem_bindings = PIPE_BIND_GLOBAL; /* gallium limit */ 220 screen->vidmem_bindings = 221 PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL | 222 PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | 223 PIPE_BIND_CURSOR | 224 PIPE_BIND_SAMPLER_VIEW | 225 PIPE_BIND_SHADER_BUFFER | PIPE_BIND_SHADER_IMAGE | 226 PIPE_BIND_COMPUTE_RESOURCE | 227 PIPE_BIND_GLOBAL; 228 screen->sysmem_bindings = 229 PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT | 230 PIPE_BIND_COMMAND_ARGS_BUFFER; 231 232 memset(&mm_config, 0, sizeof(mm_config)); 233 234 screen->mm_GART = nouveau_mm_create(dev, 235 NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 236 &mm_config); 237 screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config); 238 return 0; 239 } 240 241 void 242 nouveau_screen_fini(struct nouveau_screen *screen) 243 { 244 int fd = screen->drm->fd; 245 246 nouveau_mm_destroy(screen->mm_GART); 247 nouveau_mm_destroy(screen->mm_VRAM); 248 249 nouveau_pushbuf_del(&screen->pushbuf); 250 251 nouveau_client_del(&screen->client); 252 nouveau_object_del(&screen->channel); 253 254 nouveau_device_del(&screen->device); 255 nouveau_drm_del(&screen->drm); 256 close(fd); 257 } 258 259 static void 260 nouveau_set_debug_callback(struct pipe_context *pipe, 261 const struct pipe_debug_callback *cb) 262 { 263 struct nouveau_context *context = nouveau_context(pipe); 264 265 if (cb) 266 context->debug = *cb; 267 else 268 memset(&context->debug, 0, sizeof(context->debug)); 269 } 270 271 void 272 nouveau_context_init(struct nouveau_context *context) 273 { 274 context->pipe.set_debug_callback = nouveau_set_debug_callback; 275 } 276