2 * Copyright 2007 Nouveau Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #include "nouveau_drmif.h"
28 #include "nouveau_dma.h"
29 #include "nouveau_local.h"
32 nouveau_bo_init(struct nouveau_device
*userdev
)
38 nouveau_bo_takedown(struct nouveau_device
*userdev
)
43 nouveau_bo_realloc_gpu(struct nouveau_bo_priv
*bo
, uint32_t flags
, int size
)
45 struct nouveau_device_priv
*nv
= nouveau_device(bo
->base
.device
);
48 if (bo
->drm
.size
&& bo
->drm
.size
!= size
) {
49 struct drm_nouveau_mem_free f
;
52 drmUnmap(bo
->map
, bo
->drm
.size
);
56 f
.flags
= bo
->drm
.flags
;
57 f
.offset
= bo
->drm
.offset
;
58 drmCommandWrite(nv
->fd
, DRM_NOUVEAU_MEM_FREE
, &f
, sizeof(f
));
63 if (size
&& !bo
->drm
.size
) {
66 if (flags
& NOUVEAU_BO_VRAM
)
67 bo
->drm
.flags
|= NOUVEAU_MEM_FB
;
68 if (flags
& NOUVEAU_BO_GART
)
69 bo
->drm
.flags
|= (NOUVEAU_MEM_AGP
|
71 bo
->drm
.flags
|= NOUVEAU_MEM_MAPPED
;
76 ret
= drmCommandWriteRead(nv
->fd
, DRM_NOUVEAU_MEM_ALLOC
,
77 &bo
->drm
, sizeof(bo
->drm
));
83 ret
= drmMap(nv
->fd
, bo
->drm
.map_handle
, bo
->drm
.size
,
87 nouveau_bo_del((void *)&bo
);
96 nouveau_bo_new(struct nouveau_device
*userdev
, uint32_t flags
, int align
,
97 int size
, struct nouveau_bo
**userbo
)
99 struct nouveau_bo_priv
*bo
;
102 if (!userdev
|| !userbo
|| *userbo
)
105 bo
= calloc(1, sizeof(*bo
));
108 bo
->base
.device
= userdev
;
109 bo
->drm
.alignment
= align
;
111 if (flags
& NOUVEAU_BO_PIN
) {
112 ret
= nouveau_bo_realloc_gpu(bo
, flags
, size
);
118 bo
->sysmem
= malloc(size
);
125 bo
->base
.size
= size
;
126 bo
->base
.offset
= bo
->drm
.offset
;
127 bo
->base
.handle
= (unsigned long)bo
;
134 nouveau_bo_user(struct nouveau_device
*userdev
, void *ptr
, int size
,
135 struct nouveau_bo
**userbo
)
137 struct nouveau_bo_priv
*bo
;
139 if (!userdev
|| !userbo
|| *userbo
)
142 bo
= calloc(1, sizeof(*bo
));
145 bo
->base
.device
= userdev
;
150 bo
->base
.size
= size
;
151 bo
->base
.offset
= bo
->drm
.offset
;
152 bo
->base
.handle
= (unsigned long)bo
;
159 nouveau_bo_ref(struct nouveau_device
*userdev
, uint64_t handle
,
160 struct nouveau_bo
**userbo
)
162 struct nouveau_bo_priv
*bo
= (void *)(unsigned long)handle
;
164 if (!userdev
|| !userbo
|| *userbo
)
173 nouveau_bo_resize(struct nouveau_bo
*userbo
, int size
)
175 struct nouveau_bo_priv
*bo
= nouveau_bo(userbo
);
182 bo
->sysmem
= realloc(bo
->sysmem
, size
);
186 ret
= nouveau_bo_realloc_gpu(bo
, 0, size
);
191 bo
->base
.size
= size
;
196 nouveau_bo_del(struct nouveau_bo
**userbo
)
198 struct nouveau_bo_priv
*bo
;
200 if (!userbo
|| !*userbo
)
202 bo
= nouveau_bo(*userbo
);
209 nouveau_fence_wait(&bo
->fence
);
211 nouveau_bo_realloc_gpu(bo
, 0, 0);
212 if (bo
->sysmem
&& !bo
->user
)
218 nouveau_bo_map(struct nouveau_bo
*userbo
, uint32_t flags
)
220 struct nouveau_bo_priv
*bo
= nouveau_bo(userbo
);
226 userbo
->map
= bo
->sysmem
;
228 userbo
->map
= bo
->map
;
233 nouveau_bo_unmap(struct nouveau_bo
*userbo
)
239 nouveau_bo_upload(struct nouveau_bo_priv
*bo
)
242 nouveau_fence_wait(&bo
->fence
);
243 memcpy(bo
->map
, bo
->sysmem
, bo
->drm
.size
);
248 nouveau_bo_validate(struct nouveau_channel
*chan
, struct nouveau_bo
*bo
,
249 struct nouveau_fence
*fence
, uint32_t flags
)
251 struct nouveau_bo_priv
*nvbo
= nouveau_bo(bo
);
253 if (!nvbo
->drm
.size
) {
254 nouveau_bo_realloc_gpu(nvbo
, flags
, nvbo
->base
.size
);
255 nouveau_bo_upload(nvbo
);
258 nouveau_bo_upload(nvbo
);
260 if (nvbo
->base
.map
) {
261 nouveau_bo_upload(nvbo
);
265 if (!nvbo
->user
&& !nvbo
->base
.map
) {
271 nouveau_fence_del(&nvbo
->fence
);
272 nouveau_fence_ref(fence
, &nvbo
->fence
);
274 nvbo
->base
.offset
= nvbo
->drm
.offset
;
275 if (nvbo
->drm
.flags
& NOUVEAU_MEM_AGP
)
276 nvbo
->base
.flags
= NOUVEAU_BO_GART
;
278 nvbo
->base
.flags
= NOUVEAU_BO_VRAM
;