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