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