nouveau_screen.c 5.64 KB
Newer Older
1 2 3
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
4

5 6
#include "util/u_memory.h"
#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 13
#include <errno.h>

14 15 16 17
#include "nouveau/nouveau_bo.h"
#include "nouveau_winsys.h"
#include "nouveau_screen.h"

18
/* XXX this should go away */
19
#include "state_tracker/drm_driver.h"
20
#include "util/u_simple_screen.h"
21

22 23 24 25 26 27
static const char *
nouveau_screen_get_name(struct pipe_screen *pscreen)
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	static char buffer[128];

28
	util_snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
29 30 31 32 33 34 35 36 37 38 39
	return buffer;
}

static const char *
nouveau_screen_get_vendor(struct pipe_screen *pscreen)
{
	return "nouveau";
}



40
struct nouveau_bo *
41
nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
42
		      unsigned usage, unsigned bind, unsigned size)
43 44 45
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	struct nouveau_bo *bo = NULL;
46
	uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0;
47 48
	int ret;

49 50 51 52
	if (bind & PIPE_BIND_VERTEX_BUFFER)
		flags |= nouveau_screen(pscreen)->vertex_buffer_flags;
	else if (bind & PIPE_BIND_INDEX_BUFFER)
		flags |= nouveau_screen(pscreen)->index_buffer_flags;
53

54 55 56 57 58 59 60 61
	if (bind & (PIPE_BIND_RENDER_TARGET |
			PIPE_BIND_DEPTH_STENCIL |
			PIPE_BIND_SCANOUT |
			PIPE_BIND_DISPLAY_TARGET |
			PIPE_BIND_SAMPLER_VIEW))
	{
		/* TODO: this may be incorrect or suboptimal */
		if (!(bind & PIPE_BIND_SCANOUT))
62
			flags |= NOUVEAU_BO_GART;
63
		if (usage != PIPE_USAGE_DYNAMIC)
64 65 66
			flags |= NOUVEAU_BO_VRAM;

		if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
67
			if (bind & PIPE_BIND_DEPTH_STENCIL)
68 69 70
				tile_flags = 0x2800;
			else
				tile_flags = 0x7000;
71 72 73
		}
	}

74 75
	ret = nouveau_bo_new_tile(dev, flags, alignment, size,
				  tile_mode, tile_flags, &bo);
76 77 78
	if (ret)
		return NULL;

79
	return bo;
80 81
}

82
struct nouveau_bo *
83 84 85 86 87 88 89 90 91 92
nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes)
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	struct nouveau_bo *bo = NULL;
	int ret;

	ret = nouveau_bo_user(dev, ptr, bytes, &bo);
	if (ret)
		return NULL;

93
	return bo;
94 95
}

96 97 98 99
void *
nouveau_screen_bo_map(struct pipe_screen *pscreen,
		      struct nouveau_bo *bo,
		      unsigned map_flags)
100 101 102
{
	int ret;

103
	ret = nouveau_bo_map(bo, map_flags);
104 105 106 107 108 109 110 111
	if (ret) {
		debug_printf("map failed: %d\n", ret);
		return NULL;
	}

	return bo->map;
}

112 113 114
void *
nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct nouveau_bo *bo,
			    unsigned offset, unsigned length, unsigned flags)
115 116 117
{
	int ret;

118
	ret = nouveau_bo_map_range(bo, offset, length, flags);
119
	if (ret) {
120
		nouveau_bo_unmap(bo);
121 122
		if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
			debug_printf("map_range failed: %d\n", ret);
123 124 125
		return NULL;
	}

126
	return (char *)bo->map - offset; /* why gallium? why? */
127 128
}

129 130 131
void
nouveau_screen_bo_map_flush_range(struct pipe_screen *pscreen, struct nouveau_bo *bo,
				  unsigned offset, unsigned length)
132 133 134 135
{
	nouveau_bo_map_flush(bo, offset, length);
}

136 137
void
nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct nouveau_bo *bo)
138 139 140 141
{
	nouveau_bo_unmap(bo);
}

142 143
void
nouveau_screen_bo_release(struct pipe_screen *pscreen, struct nouveau_bo *bo)
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
{
	nouveau_bo_ref(NULL, &bo);
}

static void
nouveau_screen_fence_ref(struct pipe_screen *pscreen,
			 struct pipe_fence_handle **ptr,
			 struct pipe_fence_handle *pfence)
{
	*ptr = pfence;
}

static int
nouveau_screen_fence_signalled(struct pipe_screen *screen,
			       struct pipe_fence_handle *pfence,
			       unsigned flags)
{
	return 0;
}

static int
nouveau_screen_fence_finish(struct pipe_screen *screen,
			    struct pipe_fence_handle *pfence,
			    unsigned flags)
{
	return 0;
}

172

173 174 175 176
struct nouveau_bo *
nouveau_screen_bo_from_handle(struct pipe_screen *pscreen,
			      struct winsys_handle *whandle,
			      unsigned *out_stride)
177 178
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
179
	struct nouveau_bo *bo = 0;
180
	int ret;
181 182
 
	ret = nouveau_bo_handle_ref(dev, whandle->handle, &bo);
183 184
	if (ret) {
		debug_printf("%s: ref name 0x%08x failed with %d\n",
Vinson Lee's avatar
Vinson Lee committed
185
			     __FUNCTION__, whandle->handle, ret);
186 187 188
		return NULL;
	}

189 190
	*out_stride = whandle->stride;
	return bo;
191 192 193
}


194 195 196 197 198 199 200
boolean
nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,
			     struct nouveau_bo *bo,
			     unsigned stride,
			     struct winsys_handle *whandle)
{
	whandle->stride = stride;
201 202

	if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { 
203
		return nouveau_bo_handle_get(bo, &whandle->handle) == 0;
204
	} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
205
		whandle->handle = bo->handle;
206 207 208 209 210 211
		return TRUE;
	} else {
		return FALSE;
	}
}

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

unsigned int
nouveau_reference_flags(struct nouveau_bo *bo)
{
	uint32_t bo_flags;
	int flags = 0;

	bo_flags = nouveau_bo_pending(bo);
	if (bo_flags & NOUVEAU_BO_RD)
		flags |= PIPE_REFERENCED_FOR_READ;
	if (bo_flags & NOUVEAU_BO_WR)
		flags |= PIPE_REFERENCED_FOR_WRITE;

	return flags;
}





232 233 234 235
int
nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
{
	struct pipe_screen *pscreen = &screen->base;
236
	int ret;
237

238 239 240 241
	ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
				    &screen->channel);
	if (ret)
		return ret;
242 243 244 245 246 247 248 249 250
	screen->device = dev;

	pscreen->get_name = nouveau_screen_get_name;
	pscreen->get_vendor = nouveau_screen_get_vendor;

	pscreen->fence_reference = nouveau_screen_fence_ref;
	pscreen->fence_signalled = nouveau_screen_fence_signalled;
	pscreen->fence_finish = nouveau_screen_fence_finish;

251 252
	util_format_s3tc_init();

253 254 255 256 257 258
	return 0;
}

void
nouveau_screen_fini(struct nouveau_screen *screen)
{
259
	struct pipe_winsys *ws = screen->base.winsys;
260
	nouveau_channel_free(&screen->channel);
261 262
	if (ws)
		ws->destroy(ws);
263 264
}