Home | History | Annotate | Download | only in nouveau
      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