Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / winsys / i915 / drm / i915_drm_buffer.c
1
2 #include "state_tracker/drm_driver.h"
3 #include "i915_drm_winsys.h"
4 #include "util/u_memory.h"
5
6 #include "i915_drm.h"
7
8 static struct i915_winsys_buffer *
9 i915_drm_buffer_create(struct i915_winsys *iws,
10 unsigned size, unsigned alignment,
11 enum i915_winsys_buffer_type type)
12 {
13 struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer);
14 struct i915_drm_winsys *idws = i915_drm_winsys(iws);
15 char *name;
16
17 if (!buf)
18 return NULL;
19
20 buf->magic = 0xDEAD1337;
21 buf->flinked = FALSE;
22 buf->flink = 0;
23
24 if (type == I915_NEW_TEXTURE) {
25 name = "gallium3d_texture";
26 } else if (type == I915_NEW_VERTEX) {
27 name = "gallium3d_vertex";
28 } else if (type == I915_NEW_SCANOUT) {
29 name = "gallium3d_scanout";
30 } else {
31 assert(0);
32 name = "gallium3d_unknown";
33 }
34
35 buf->bo = drm_intel_bo_alloc(idws->gem_manager, name, size, alignment);
36
37 if (!buf->bo)
38 goto err;
39
40 return (struct i915_winsys_buffer *)buf;
41
42 err:
43 assert(0);
44 FREE(buf);
45 return NULL;
46 }
47
48 static struct i915_winsys_buffer *
49 i915_drm_buffer_from_handle(struct i915_winsys *iws,
50 struct winsys_handle *whandle,
51 unsigned *stride)
52 {
53 struct i915_drm_winsys *idws = i915_drm_winsys(iws);
54 struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer);
55 uint32_t tile = 0, swizzle = 0;
56
57 if (!buf)
58 return NULL;
59
60 buf->magic = 0xDEAD1337;
61 buf->bo = drm_intel_bo_gem_create_from_name(idws->gem_manager, "gallium3d_from_handle", whandle->handle);
62 buf->flinked = TRUE;
63 buf->flink = whandle->handle;
64
65 if (!buf->bo)
66 goto err;
67
68 drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle);
69
70 *stride = whandle->stride;
71
72 return (struct i915_winsys_buffer *)buf;
73
74 err:
75 FREE(buf);
76 return NULL;
77 }
78
79 static boolean
80 i915_drm_buffer_get_handle(struct i915_winsys *iws,
81 struct i915_winsys_buffer *buffer,
82 struct winsys_handle *whandle,
83 unsigned stride)
84 {
85 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
86
87 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
88 if (!buf->flinked) {
89 if (drm_intel_bo_flink(buf->bo, &buf->flink))
90 return FALSE;
91 buf->flinked = TRUE;
92 }
93
94 whandle->handle = buf->flink;
95 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
96 whandle->handle = buf->bo->handle;
97 } else {
98 assert(!"unknown usage");
99 return FALSE;
100 }
101
102 whandle->stride = stride;
103 return TRUE;
104 }
105
106 static int
107 i915_drm_buffer_set_fence_reg(struct i915_winsys *iws,
108 struct i915_winsys_buffer *buffer,
109 unsigned stride,
110 enum i915_winsys_buffer_tile tile)
111 {
112 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
113 assert(I915_TILING_NONE == I915_TILE_NONE);
114 assert(I915_TILING_X == I915_TILE_X);
115 assert(I915_TILING_Y == I915_TILE_Y);
116
117 if (tile != I915_TILE_NONE) {
118 assert(buf->map_count == 0);
119 }
120
121 return drm_intel_bo_set_tiling(buf->bo, &tile, stride);
122 }
123
124 static void *
125 i915_drm_buffer_map(struct i915_winsys *iws,
126 struct i915_winsys_buffer *buffer,
127 boolean write)
128 {
129 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
130 drm_intel_bo *bo = intel_bo(buffer);
131 int ret = 0;
132
133 assert(bo);
134
135 if (buf->map_count)
136 goto out;
137
138 ret = drm_intel_gem_bo_map_gtt(bo);
139
140 buf->ptr = bo->virtual;
141
142 assert(ret == 0);
143 out:
144 if (ret)
145 return NULL;
146
147 buf->map_count++;
148 return buf->ptr;
149 }
150
151 static void
152 i915_drm_buffer_unmap(struct i915_winsys *iws,
153 struct i915_winsys_buffer *buffer)
154 {
155 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
156
157 if (--buf->map_count)
158 return;
159
160 drm_intel_gem_bo_unmap_gtt(intel_bo(buffer));
161 }
162
163 static int
164 i915_drm_buffer_write(struct i915_winsys *iws,
165 struct i915_winsys_buffer *buffer,
166 size_t offset,
167 size_t size,
168 const void *data)
169 {
170 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
171
172 return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
173 }
174
175 static void
176 i915_drm_buffer_destroy(struct i915_winsys *iws,
177 struct i915_winsys_buffer *buffer)
178 {
179 drm_intel_bo_unreference(intel_bo(buffer));
180
181 #ifdef DEBUG
182 i915_drm_buffer(buffer)->magic = 0;
183 i915_drm_buffer(buffer)->bo = NULL;
184 #endif
185
186 FREE(buffer);
187 }
188
189 void
190 i915_drm_winsys_init_buffer_functions(struct i915_drm_winsys *idws)
191 {
192 idws->base.buffer_create = i915_drm_buffer_create;
193 idws->base.buffer_from_handle = i915_drm_buffer_from_handle;
194 idws->base.buffer_get_handle = i915_drm_buffer_get_handle;
195 idws->base.buffer_set_fence_reg = i915_drm_buffer_set_fence_reg;
196 idws->base.buffer_map = i915_drm_buffer_map;
197 idws->base.buffer_unmap = i915_drm_buffer_unmap;
198 idws->base.buffer_write = i915_drm_buffer_write;
199 idws->base.buffer_destroy = i915_drm_buffer_destroy;
200 }