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 <libdrm/nouveau_drm.h> 18 19 #include "nouveau_winsys.h" 20 #include "nouveau_screen.h" 21 #include "nouveau_fence.h" 22 #include "nouveau_mm.h" 23 #include "nouveau_buffer.h" 24 25 /* XXX this should go away */ 26 #include "state_tracker/drm_driver.h" 27 28 int nouveau_mesa_debug = 0; 29 30 static const char * 31 nouveau_screen_get_name(struct pipe_screen *pscreen) 32 { 33 struct nouveau_device *dev = nouveau_screen(pscreen)->device; 34 static char buffer[128]; 35 36 util_snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); 37 return buffer; 38 } 39 40 static const char * 41 nouveau_screen_get_vendor(struct pipe_screen *pscreen) 42 { 43 return "nouveau"; 44 } 45 46 static uint64_t 47 nouveau_screen_get_timestamp(struct pipe_screen *pscreen) 48 { 49 int64_t cpu_time = os_time_get() * 1000; 50 51 /* getparam of PTIMER_TIME takes about x10 as long (several usecs) */ 52 53 return cpu_time + nouveau_screen(pscreen)->cpu_gpu_time_delta; 54 } 55 56 static void 57 nouveau_screen_fence_ref(struct pipe_screen *pscreen, 58 struct pipe_fence_handle **ptr, 59 struct pipe_fence_handle *pfence) 60 { 61 nouveau_fence_ref(nouveau_fence(pfence), (struct nouveau_fence **)ptr); 62 } 63 64 static boolean 65 nouveau_screen_fence_signalled(struct pipe_screen *screen, 66 struct pipe_fence_handle *pfence) 67 { 68 return nouveau_fence_signalled(nouveau_fence(pfence)); 69 } 70 71 static boolean 72 nouveau_screen_fence_finish(struct pipe_screen *screen, 73 struct pipe_fence_handle *pfence, 74 uint64_t timeout) 75 { 76 return nouveau_fence_wait(nouveau_fence(pfence)); 77 } 78 79 80 struct nouveau_bo * 81 nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, 82 struct winsys_handle *whandle, 83 unsigned *out_stride) 84 { 85 struct nouveau_device *dev = nouveau_screen(pscreen)->device; 86 struct nouveau_bo *bo = 0; 87 int ret; 88 89 ret = nouveau_bo_name_ref(dev, whandle->handle, &bo); 90 if (ret) { 91 debug_printf("%s: ref name 0x%08x failed with %d\n", 92 __FUNCTION__, whandle->handle, ret); 93 return NULL; 94 } 95 96 *out_stride = whandle->stride; 97 return bo; 98 } 99 100 101 boolean 102 nouveau_screen_bo_get_handle(struct pipe_screen *pscreen, 103 struct nouveau_bo *bo, 104 unsigned stride, 105 struct winsys_handle *whandle) 106 { 107 whandle->stride = stride; 108 109 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { 110 return nouveau_bo_name_get(bo, &whandle->handle) == 0; 111 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { 112 whandle->handle = bo->handle; 113 return TRUE; 114 } else { 115 return FALSE; 116 } 117 } 118 119 int 120 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) 121 { 122 struct pipe_screen *pscreen = &screen->base; 123 struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; 124 struct nvc0_fifo nvc0_data = { }; 125 uint64_t time; 126 int size, ret; 127 void *data; 128 union nouveau_bo_config mm_config; 129 130 char *nv_dbg = getenv("NOUVEAU_MESA_DEBUG"); 131 if (nv_dbg) 132 nouveau_mesa_debug = atoi(nv_dbg); 133 134 if (dev->chipset < 0xc0) { 135 data = &nv04_data; 136 size = sizeof(nv04_data); 137 } else { 138 data = &nvc0_data; 139 size = sizeof(nvc0_data); 140 } 141 142 ret = nouveau_object_new(&dev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, 143 data, size, &screen->channel); 144 if (ret) 145 return ret; 146 screen->device = dev; 147 148 ret = nouveau_client_new(screen->device, &screen->client); 149 if (ret) 150 return ret; 151 ret = nouveau_pushbuf_new(screen->client, screen->channel, 152 4, 512 * 1024, 1, 153 &screen->pushbuf); 154 if (ret) 155 return ret; 156 157 /* getting CPU time first appears to be more accurate */ 158 screen->cpu_gpu_time_delta = os_time_get(); 159 160 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_PTIMER_TIME, &time); 161 if (!ret) 162 screen->cpu_gpu_time_delta = time - screen->cpu_gpu_time_delta * 1000; 163 164 pscreen->get_name = nouveau_screen_get_name; 165 pscreen->get_vendor = nouveau_screen_get_vendor; 166 167 pscreen->get_timestamp = nouveau_screen_get_timestamp; 168 169 pscreen->fence_reference = nouveau_screen_fence_ref; 170 pscreen->fence_signalled = nouveau_screen_fence_signalled; 171 pscreen->fence_finish = nouveau_screen_fence_finish; 172 173 util_format_s3tc_init(); 174 175 screen->lowmem_bindings = PIPE_BIND_GLOBAL; /* gallium limit */ 176 screen->vidmem_bindings = 177 PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL | 178 PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_CURSOR | 179 PIPE_BIND_SAMPLER_VIEW | 180 PIPE_BIND_SHADER_RESOURCE | PIPE_BIND_COMPUTE_RESOURCE | 181 PIPE_BIND_GLOBAL; 182 screen->sysmem_bindings = 183 PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT; 184 185 memset(&mm_config, 0, sizeof(mm_config)); 186 187 screen->mm_GART = nouveau_mm_create(dev, 188 NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 189 &mm_config); 190 screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config); 191 return 0; 192 } 193 194 void 195 nouveau_screen_fini(struct nouveau_screen *screen) 196 { 197 nouveau_mm_destroy(screen->mm_GART); 198 nouveau_mm_destroy(screen->mm_VRAM); 199 200 nouveau_pushbuf_del(&screen->pushbuf); 201 202 nouveau_client_del(&screen->client); 203 nouveau_object_del(&screen->channel); 204 205 nouveau_device_del(&screen->device); 206 } 207