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