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 "util/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 29int nouveau_mesa_debug = 0; 30 31static const char * 32nouveau_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 41static const char * 42nouveau_screen_get_vendor(struct pipe_screen *pscreen) 43{ 44 return "nouveau"; 45} 46 47static const char * 48nouveau_screen_get_device_vendor(struct pipe_screen *pscreen) 49{ 50 return "NVIDIA"; 51} 52 53static uint64_t 54nouveau_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 63static struct disk_cache * 64nouveau_screen_get_disk_shader_cache(struct pipe_screen *pscreen) 65{ 66 return nouveau_screen(pscreen)->disk_shader_cache; 67} 68 69static void 70nouveau_screen_fence_ref(struct pipe_screen *pscreen, 71 struct pipe_fence_handle **ptr, 72 struct pipe_fence_handle *pfence) 73{ 74 nouveau_fence_ref(nouveau_fence(pfence), (struct nouveau_fence **)ptr); 75} 76 77static boolean 78nouveau_screen_fence_finish(struct pipe_screen *screen, 79 struct pipe_context *ctx, 80 struct pipe_fence_handle *pfence, 81 uint64_t timeout) 82{ 83 if (!timeout) 84 return nouveau_fence_signalled(nouveau_fence(pfence)); 85 86 return nouveau_fence_wait(nouveau_fence(pfence), NULL); 87} 88 89 90struct nouveau_bo * 91nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, 92 struct winsys_handle *whandle, 93 unsigned *out_stride) 94{ 95 struct nouveau_device *dev = nouveau_screen(pscreen)->device; 96 struct nouveau_bo *bo = 0; 97 int ret; 98 99 if (whandle->offset != 0) { 100 debug_printf("%s: attempt to import unsupported winsys offset %d\n", 101 __FUNCTION__, whandle->offset); 102 return NULL; 103 } 104 105 if (whandle->type != WINSYS_HANDLE_TYPE_SHARED && 106 whandle->type != WINSYS_HANDLE_TYPE_FD) { 107 debug_printf("%s: attempt to import unsupported handle type %d\n", 108 __FUNCTION__, whandle->type); 109 return NULL; 110 } 111 112 if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) 113 ret = nouveau_bo_name_ref(dev, whandle->handle, &bo); 114 else 115 ret = nouveau_bo_prime_handle_ref(dev, whandle->handle, &bo); 116 117 if (ret) { 118 debug_printf("%s: ref name 0x%08x failed with %d\n", 119 __FUNCTION__, whandle->handle, ret); 120 return NULL; 121 } 122 123 *out_stride = whandle->stride; 124 return bo; 125} 126 127 128bool 129nouveau_screen_bo_get_handle(struct pipe_screen *pscreen, 130 struct nouveau_bo *bo, 131 unsigned stride, 132 struct winsys_handle *whandle) 133{ 134 whandle->stride = stride; 135 136 if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) { 137 return nouveau_bo_name_get(bo, &whandle->handle) == 0; 138 } else if (whandle->type == WINSYS_HANDLE_TYPE_KMS) { 139 whandle->handle = bo->handle; 140 return true; 141 } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) { 142 return nouveau_bo_set_prime(bo, (int *)&whandle->handle) == 0; 143 } else { 144 return false; 145 } 146} 147 148static void 149nouveau_disk_cache_create(struct nouveau_screen *screen) 150{ 151 struct mesa_sha1 ctx; 152 unsigned char sha1[20]; 153 char cache_id[20 * 2 + 1]; 154 uint64_t driver_flags = 0; 155 156 _mesa_sha1_init(&ctx); 157 if (!disk_cache_get_function_identifier(nouveau_disk_cache_create, 158 &ctx)) 159 return; 160 161 _mesa_sha1_final(&ctx, sha1); 162 disk_cache_format_hex_id(cache_id, sha1, 20 * 2); 163 164 if (screen->prefer_nir) 165 driver_flags |= NOUVEAU_SHADER_CACHE_FLAGS_IR_NIR; 166 else 167 driver_flags |= NOUVEAU_SHADER_CACHE_FLAGS_IR_TGSI; 168 169 screen->disk_shader_cache = 170 disk_cache_create(nouveau_screen_get_name(&screen->base), 171 cache_id, driver_flags); 172} 173 174int 175nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) 176{ 177 struct pipe_screen *pscreen = &screen->base; 178 struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; 179 struct nvc0_fifo nvc0_data = { }; 180 uint64_t time; 181 int size, ret; 182 void *data; 183 union nouveau_bo_config mm_config; 184 185 char *nv_dbg = getenv("NOUVEAU_MESA_DEBUG"); 186 if (nv_dbg) 187 nouveau_mesa_debug = atoi(nv_dbg); 188 189 screen->prefer_nir = debug_get_bool_option("NV50_PROG_USE_NIR", false); 190 191 /* These must be set before any failure is possible, as the cleanup 192 * paths assume they're responsible for deleting them. 193 */ 194 screen->drm = nouveau_drm(&dev->object); 195 screen->device = dev; 196 197 /* 198 * this is initialized to 1 in nouveau_drm_screen_create after screen 199 * is fully constructed and added to the global screen list. 200 */ 201 screen->refcount = -1; 202 203 if (dev->chipset < 0xc0) { 204 data = &nv04_data; 205 size = sizeof(nv04_data); 206 } else { 207 data = &nvc0_data; 208 size = sizeof(nvc0_data); 209 } 210 211 /* 212 * Set default VRAM domain if not overridden 213 */ 214 if (!screen->vram_domain) { 215 if (dev->vram_size > 0) 216 screen->vram_domain = NOUVEAU_BO_VRAM; 217 else 218 screen->vram_domain = NOUVEAU_BO_GART; 219 } 220 221 ret = nouveau_object_new(&dev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, 222 data, size, &screen->channel); 223 if (ret) 224 return ret; 225 226 ret = nouveau_client_new(screen->device, &screen->client); 227 if (ret) 228 return ret; 229 ret = nouveau_pushbuf_new(screen->client, screen->channel, 230 4, 512 * 1024, 1, 231 &screen->pushbuf); 232 if (ret) 233 return ret; 234 235 /* getting CPU time first appears to be more accurate */ 236 screen->cpu_gpu_time_delta = os_time_get(); 237 238 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_PTIMER_TIME, &time); 239 if (!ret) 240 screen->cpu_gpu_time_delta = time - screen->cpu_gpu_time_delta * 1000; 241 242 pscreen->get_name = nouveau_screen_get_name; 243 pscreen->get_vendor = nouveau_screen_get_vendor; 244 pscreen->get_device_vendor = nouveau_screen_get_device_vendor; 245 pscreen->get_disk_shader_cache = nouveau_screen_get_disk_shader_cache; 246 247 pscreen->get_timestamp = nouveau_screen_get_timestamp; 248 249 pscreen->fence_reference = nouveau_screen_fence_ref; 250 pscreen->fence_finish = nouveau_screen_fence_finish; 251 252 nouveau_disk_cache_create(screen); 253 254 screen->transfer_pushbuf_threshold = 192; 255 screen->lowmem_bindings = PIPE_BIND_GLOBAL; /* gallium limit */ 256 screen->vidmem_bindings = 257 PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL | 258 PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | 259 PIPE_BIND_CURSOR | 260 PIPE_BIND_SAMPLER_VIEW | 261 PIPE_BIND_SHADER_BUFFER | PIPE_BIND_SHADER_IMAGE | 262 PIPE_BIND_COMPUTE_RESOURCE | 263 PIPE_BIND_GLOBAL; 264 screen->sysmem_bindings = 265 PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT | 266 PIPE_BIND_COMMAND_ARGS_BUFFER; 267 268 memset(&mm_config, 0, sizeof(mm_config)); 269 270 screen->mm_GART = nouveau_mm_create(dev, 271 NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 272 &mm_config); 273 screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config); 274 return 0; 275} 276 277void 278nouveau_screen_fini(struct nouveau_screen *screen) 279{ 280 int fd = screen->drm->fd; 281 282 nouveau_mm_destroy(screen->mm_GART); 283 nouveau_mm_destroy(screen->mm_VRAM); 284 285 nouveau_pushbuf_del(&screen->pushbuf); 286 287 nouveau_client_del(&screen->client); 288 nouveau_object_del(&screen->channel); 289 290 nouveau_device_del(&screen->device); 291 nouveau_drm_del(&screen->drm); 292 close(fd); 293 294 disk_cache_destroy(screen->disk_shader_cache); 295} 296 297static void 298nouveau_set_debug_callback(struct pipe_context *pipe, 299 const struct pipe_debug_callback *cb) 300{ 301 struct nouveau_context *context = nouveau_context(pipe); 302 303 if (cb) 304 context->debug = *cb; 305 else 306 memset(&context->debug, 0, sizeof(context->debug)); 307} 308 309void 310nouveau_context_init(struct nouveau_context *context) 311{ 312 context->pipe.set_debug_callback = nouveau_set_debug_callback; 313} 314