OSDN Git Service

0ab426dc0fb63dac204e941547b5a55b31464478
[android-x86/external-libdrm.git] / libdrm / nouveau / nouveau_bo.c
1 /*
2  * Copyright 2007 Nouveau Project
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
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
20  * SOFTWARE.
21  */
22
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include <sys/mman.h>
29 #include <sys/ioctl.h>
30
31 #include "nouveau_private.h"
32
33 int
34 nouveau_bo_init(struct nouveau_device *dev)
35 {
36         return 0;
37 }
38
39 void
40 nouveau_bo_takedown(struct nouveau_device *dev)
41 {
42 }
43
44 static int
45 nouveau_bo_allocated(struct nouveau_bo_priv *nvbo)
46 {
47         if (nvbo->sysmem || nvbo->handle || (nvbo->flags & NOUVEAU_BO_PIN))
48                 return 1;
49         return 0;
50 }
51
52 static int
53 nouveau_bo_ualloc(struct nouveau_bo_priv *nvbo)
54 {
55         if (nvbo->user || nvbo->sysmem) {
56                 assert(nvbo->sysmem);
57                 return 0;
58         }
59
60         nvbo->sysmem = malloc(nvbo->size);
61         if (!nvbo->sysmem)
62                 return -ENOMEM;
63
64         return 0;
65 }
66
67 static void
68 nouveau_bo_ufree(struct nouveau_bo_priv *nvbo)
69 {
70         if (nvbo->sysmem) {
71                 if (!nvbo->user)
72                         free(nvbo->sysmem);
73                 nvbo->sysmem = NULL;
74         }
75 }
76
77 static void
78 nouveau_bo_kfree_nomm(struct nouveau_bo_priv *nvbo)
79 {
80         struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
81         struct drm_nouveau_mem_free req;
82
83         if (nvbo->map) {
84                 drmUnmap(nvbo->map, nvbo->size);
85                 nvbo->map = NULL;
86         }
87
88         req.offset = nvbo->offset;
89         if (nvbo->domain & NOUVEAU_BO_GART)
90                 req.flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI;
91         else
92         if (nvbo->domain & NOUVEAU_BO_VRAM)
93                 req.flags = NOUVEAU_MEM_FB;
94         drmCommandWrite(nvdev->fd, DRM_NOUVEAU_MEM_FREE, &req, sizeof(req));
95
96         nvbo->handle = 0;
97 }
98
99 static void
100 nouveau_bo_kfree(struct nouveau_bo_priv *nvbo)
101 {
102         struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
103         struct drm_gem_close req;
104
105         if (!nvbo->handle)
106                 return;
107
108         if (!nvdev->mm_enabled) {
109                 nouveau_bo_kfree_nomm(nvbo);
110                 return;
111         }
112
113         if (nvbo->map) {
114                 munmap(nvbo->map, nvbo->size);
115                 nvbo->map = NULL;
116         }
117
118         req.handle = nvbo->handle;
119         nvbo->handle = 0;
120         ioctl(nvdev->fd, DRM_IOCTL_GEM_CLOSE, &req);
121 }
122
123 static int
124 nouveau_bo_kalloc_nomm(struct nouveau_bo_priv *nvbo)
125 {
126         struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
127         struct drm_nouveau_mem_alloc req;
128         int ret;
129
130         if (nvbo->handle)
131                 return 0;
132
133         if (!(nvbo->flags & (NOUVEAU_BO_VRAM|NOUVEAU_BO_GART)))
134                 nvbo->flags |= (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM);
135
136         req.size = nvbo->size;
137         req.alignment = nvbo->align;
138         req.flags = 0;
139         if (nvbo->flags & NOUVEAU_BO_VRAM)
140                 req.flags |= NOUVEAU_MEM_FB;
141         if (nvbo->flags & NOUVEAU_BO_GART)
142                 req.flags |= (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI);
143         if (nvbo->flags & NOUVEAU_BO_TILED) {
144                 req.flags |= NOUVEAU_MEM_TILE;
145                 if (nvbo->flags & NOUVEAU_BO_ZTILE)
146                         req.flags |= NOUVEAU_MEM_TILE_ZETA;
147         }
148         req.flags |= NOUVEAU_MEM_MAPPED;
149
150         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_MEM_ALLOC,
151                                   &req, sizeof(req));
152         if (ret)
153                 return ret;
154
155         nvbo->handle = req.map_handle;
156         nvbo->size = req.size;
157         nvbo->offset = req.offset;
158         if (req.flags & (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI))
159                 nvbo->domain = NOUVEAU_BO_GART;
160         else
161         if (req.flags & NOUVEAU_MEM_FB)
162                 nvbo->domain = NOUVEAU_BO_VRAM;
163
164         return 0;
165 }
166
167 static int
168 nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan)
169 {
170         struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
171         struct drm_nouveau_gem_new req;
172         int ret;
173
174         if (nvbo->handle || (nvbo->flags & NOUVEAU_BO_PIN))
175                 return 0;
176
177         if (!nvdev->mm_enabled)
178                 return nouveau_bo_kalloc_nomm(nvbo);
179
180         req.channel_hint = chan ? chan->id : 0;
181
182         req.size = nvbo->size;
183         req.align = nvbo->align;
184
185         req.domain = 0;
186
187         if (nvbo->flags & NOUVEAU_BO_VRAM)
188                 req.domain |= NOUVEAU_GEM_DOMAIN_VRAM;
189
190         if (nvbo->flags & NOUVEAU_BO_GART)
191                 req.domain |= NOUVEAU_GEM_DOMAIN_GART;
192
193         if (nvbo->flags & NOUVEAU_BO_TILED) {
194                 req.domain |= NOUVEAU_GEM_DOMAIN_TILE;
195                 if (nvbo->flags & NOUVEAU_BO_ZTILE)
196                         req.domain |= NOUVEAU_GEM_DOMAIN_TILE_ZETA;
197         }
198
199         if (!req.domain) {
200                 req.domain |= (NOUVEAU_GEM_DOMAIN_VRAM |
201                                NOUVEAU_GEM_DOMAIN_GART);
202         }
203
204         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW,
205                                   &req, sizeof(req));
206         if (ret)
207                 return ret;
208         nvbo->handle = nvbo->base.handle = req.handle;
209         nvbo->size = req.size;
210         nvbo->domain = req.domain;
211         nvbo->offset = req.offset;
212
213         return 0;
214 }
215
216 static int
217 nouveau_bo_kmap_nomm(struct nouveau_bo_priv *nvbo)
218 {
219         struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
220         int ret;
221
222         ret = drmMap(nvdev->fd, nvbo->handle, nvbo->size, &nvbo->map);
223         if (ret) {
224                 nvbo->map = NULL;
225                 return ret;
226         }
227
228         return 0;
229 }
230
231 static int
232 nouveau_bo_kmap(struct nouveau_bo_priv *nvbo)
233 {
234         struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
235         struct drm_nouveau_gem_mmap req;
236         int ret;
237
238         if (nvbo->map)
239                 return 0;
240
241         if (!nvbo->handle)
242                 return -EINVAL;
243
244         if (!nvdev->mm_enabled)
245                 return nouveau_bo_kmap_nomm(nvbo);
246
247         req.handle = nvbo->handle;
248         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_MMAP,
249                                   &req, sizeof(req));
250         if (ret)
251                 return ret;
252
253         nvbo->map = (void *)(unsigned long)req.vaddr;
254         return 0;
255 }
256
257 int
258 nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
259                int size, struct nouveau_bo **bo)
260 {
261         struct nouveau_bo_priv *nvbo;
262         int ret;
263
264         if (!dev || !bo || *bo)
265                 return -EINVAL;
266
267         nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
268         if (!nvbo)
269                 return -ENOMEM;
270         nvbo->base.device = dev;
271         nvbo->base.size = size;
272
273         nvbo->refcount = 1;
274         /* Don't set NOUVEAU_BO_PIN here, or nouveau_bo_allocated() will
275          * decided the buffer's already allocated when it's not.  The
276          * call to nouveau_bo_pin() later will set this flag.
277          */
278         nvbo->flags = (flags & ~NOUVEAU_BO_PIN);
279         nvbo->size = size;
280         nvbo->align = align;
281
282         /*XXX: murder me violently */
283         if (flags & NOUVEAU_BO_TILED) {
284                 nvbo->base.tiled = 1;
285                 if (flags & NOUVEAU_BO_ZTILE)
286                         nvbo->base.tiled |= 2;
287         }
288
289         if (flags & NOUVEAU_BO_PIN) {
290                 ret = nouveau_bo_pin((void *)nvbo, nvbo->flags);
291                 if (ret) {
292                         nouveau_bo_ref(NULL, (void *)nvbo);
293                         return ret;
294                 }
295         }
296
297         *bo = &nvbo->base;
298         return 0;
299 }
300
301 int
302 nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
303                 struct nouveau_bo **bo)
304 {
305         struct nouveau_bo_priv *nvbo;
306         int ret;
307
308         ret = nouveau_bo_new(dev, 0, 0, size, bo);
309         if (ret)
310                 return ret;
311         nvbo = nouveau_bo(*bo);
312
313         nvbo->sysmem = ptr;
314         nvbo->user = 1;
315         return 0;
316 }
317
318 int
319 nouveau_bo_fake(struct nouveau_device *dev, uint64_t offset, uint32_t flags,
320                 uint32_t size, void *map, struct nouveau_bo **bo)
321 {
322         struct nouveau_bo_priv *nvbo;
323         int ret;
324
325         ret = nouveau_bo_new(dev, flags & ~NOUVEAU_BO_PIN, 0, size, bo);
326         if (ret)
327                 return ret;
328         nvbo = nouveau_bo(*bo);
329
330         nvbo->flags = flags | NOUVEAU_BO_PIN;
331         nvbo->domain = (flags & (NOUVEAU_BO_VRAM|NOUVEAU_BO_GART));
332         nvbo->offset = offset;
333         nvbo->size = nvbo->base.size = size;
334         nvbo->map = map;
335         nvbo->base.flags = nvbo->flags;
336         nvbo->base.offset = nvbo->offset;
337         return 0;
338 }
339
340 int
341 nouveau_bo_handle_get(struct nouveau_bo *bo, uint32_t *handle)
342 {
343         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
344         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
345         int ret;
346  
347         if (!bo || !handle)
348                 return -EINVAL;
349
350         if (!nvdev->mm_enabled)
351                 return -ENODEV;
352
353         if (!nvbo->global_handle) {
354                 struct drm_gem_flink req;
355  
356                 ret = nouveau_bo_kalloc(nvbo, NULL);
357                 if (ret)
358                         return ret;
359  
360                 req.handle = nvbo->handle;
361                 ret = ioctl(nvdev->fd, DRM_IOCTL_GEM_FLINK, &req);
362                 if (ret) {
363                         nouveau_bo_kfree(nvbo);
364                         return ret;
365                 }
366  
367                 nvbo->global_handle = req.name;
368         }
369  
370         *handle = nvbo->global_handle;
371         return 0;
372 }
373  
374 int
375 nouveau_bo_handle_ref(struct nouveau_device *dev, uint32_t handle,
376                       struct nouveau_bo **bo)
377 {
378         struct nouveau_device_priv *nvdev = nouveau_device(dev);
379         struct nouveau_bo_priv *nvbo;
380         struct drm_gem_open req;
381         int ret;
382
383         ret = nouveau_bo_new(dev, 0, 0, 0, bo);
384         if (ret)
385                 return ret;
386         nvbo = nouveau_bo(*bo);
387
388         if (!nvdev->mm_enabled) {
389                 nvbo->handle = 0;
390                 nvbo->offset =  handle;
391                 nvbo->domain = NOUVEAU_BO_VRAM;
392                 nvbo->flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN;
393                 nvbo->base.offset = nvbo->offset;
394                 nvbo->base.flags = nvbo->flags;
395         } else {
396                 req.name = handle;
397                 ret = ioctl(nvdev->fd, DRM_IOCTL_GEM_OPEN, &req);
398                 if (ret) {
399                         nouveau_bo_ref(NULL, bo);
400                         return ret;
401                 }
402
403                 nvbo->size = req.size;
404                 nvbo->handle = req.handle;
405         }
406  
407         return 0;
408
409
410 static void
411 nouveau_bo_del_cb(void *priv)
412 {
413         struct nouveau_bo_priv *nvbo = priv;
414
415         nouveau_bo_kfree(nvbo);
416         free(nvbo);
417 }
418
419 static void
420 nouveau_bo_del(struct nouveau_bo **bo)
421 {
422         struct nouveau_bo_priv *nvbo;
423
424         if (!bo || !*bo)
425                 return;
426         nvbo = nouveau_bo(*bo);
427         *bo = NULL;
428
429         if (--nvbo->refcount)
430                 return;
431
432         if (nvbo->pending) {
433                 nvbo->pending = NULL;
434                 nouveau_pushbuf_flush(nvbo->pending_channel, 0);
435         }
436
437         nouveau_bo_ufree(nvbo);
438         if (!nouveau_device(nvbo->base.device)->mm_enabled && nvbo->fence)
439                 nouveau_fence_signal_cb(nvbo->fence, nouveau_bo_del_cb, nvbo);
440         else
441                 nouveau_bo_del_cb(nvbo);
442 }
443
444 int
445 nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pbo)
446 {
447         if (!pbo)
448                 return -EINVAL;
449
450         if (ref)
451                 nouveau_bo(ref)->refcount++;
452
453         if (*pbo)
454                 nouveau_bo_del(pbo);
455
456         *pbo = ref;
457         return 0;
458 }
459
460 static int
461 nouveau_bo_wait_nomm(struct nouveau_bo *bo, int cpu_write)
462 {
463         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
464         int ret = 0;
465
466         if (cpu_write)
467                 ret = nouveau_fence_wait(&nvbo->fence);
468         else
469                 ret = nouveau_fence_wait(&nvbo->wr_fence);
470         if (ret)
471                 return ret;
472
473         nvbo->write_marker = 0;
474         return 0;
475 }
476
477 static int
478 nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write)
479 {
480         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
481         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
482         struct drm_nouveau_gem_cpu_prep req;
483         int ret;
484
485         if (!nvbo->global_handle && !nvbo->write_marker && !cpu_write)
486                 return 0;
487
488         if (nvbo->pending &&
489             (nvbo->pending->write_domains || cpu_write)) {
490                 nvbo->pending = NULL;
491                 nouveau_pushbuf_flush(nvbo->pending_channel, 0);
492         }
493
494         if (!nvdev->mm_enabled)
495                 return nouveau_bo_wait_nomm(bo, cpu_write);
496
497         req.handle = nvbo->handle;
498         ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_PREP,
499                               &req, sizeof(req));
500         if (ret)
501                 return ret;
502
503         nvbo->write_marker = 0;
504         return 0;
505 }
506
507 int
508 nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
509 {
510         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
511         int ret;
512
513         if (!nvbo || bo->map)
514                 return -EINVAL;
515
516         if (!nouveau_bo_allocated(nvbo)) {
517                 if (nvbo->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
518                         ret = nouveau_bo_kalloc(nvbo, NULL);
519                         if (ret)
520                                 return ret;
521                 }
522
523                 if (!nouveau_bo_allocated(nvbo)) {
524                         ret = nouveau_bo_ualloc(nvbo);
525                         if (ret)
526                                 return ret;
527                 }
528         }
529
530         if (nvbo->sysmem) {
531                 bo->map = nvbo->sysmem;
532         } else {
533                 ret = nouveau_bo_kmap(nvbo);
534                 if (ret)
535                         return ret;
536
537                 ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR));
538                 if (ret)
539                         return ret;
540
541                 bo->map = nvbo->map;
542         }
543
544         return 0;
545 }
546
547 void
548 nouveau_bo_unmap(struct nouveau_bo *bo)
549 {
550         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
551         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
552
553         if (nvdev->mm_enabled && bo->map && !nvbo->sysmem) {
554                 struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
555                 struct drm_nouveau_gem_cpu_fini req;
556
557                 req.handle = nvbo->handle;
558                 drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_FINI,
559                                 &req, sizeof(req));
560         }
561
562         bo->map = NULL;
563 }
564
565 int
566 nouveau_bo_validate_nomm(struct nouveau_bo_priv *nvbo, uint32_t flags)
567 {
568         struct nouveau_bo *new = NULL;
569         uint32_t t_handle, t_domain, t_offset, t_size;
570         void *t_map;
571         int ret;
572
573         if ((flags & NOUVEAU_BO_VRAM) && nvbo->domain == NOUVEAU_BO_VRAM)
574                 return 0;
575         if ((flags & NOUVEAU_BO_GART) && nvbo->domain == NOUVEAU_BO_GART)
576                 return 0;
577         assert(flags & (NOUVEAU_BO_VRAM|NOUVEAU_BO_GART));
578
579         /* Keep tiling info */
580         flags |= (nvbo->flags & (NOUVEAU_BO_TILED|NOUVEAU_BO_ZTILE));
581
582         ret = nouveau_bo_new(nvbo->base.device, flags, 0, nvbo->size, &new);
583         if (ret)
584                 return ret;
585
586         ret = nouveau_bo_kalloc(nouveau_bo(new), NULL);
587         if (ret) {
588                 nouveau_bo_ref(NULL, &new);
589                 return ret;
590         }
591
592         if (nvbo->handle || nvbo->sysmem) {
593         nouveau_bo_kmap(nouveau_bo(new));
594
595         if (!nvbo->base.map) {
596                 nouveau_bo_map(&nvbo->base, NOUVEAU_BO_RD);
597                 memcpy(nouveau_bo(new)->map, nvbo->base.map, nvbo->base.size);
598                 nouveau_bo_unmap(&nvbo->base);
599         } else {
600                 memcpy(nouveau_bo(new)->map, nvbo->base.map, nvbo->base.size);
601         }
602         }
603
604         t_handle = nvbo->handle;
605         t_domain = nvbo->domain;
606         t_offset = nvbo->offset;
607         t_size = nvbo->size;
608         t_map = nvbo->map;
609
610         nvbo->handle = nouveau_bo(new)->handle;
611         nvbo->domain = nouveau_bo(new)->domain;
612         nvbo->offset = nouveau_bo(new)->offset;
613         nvbo->size = nouveau_bo(new)->size;
614         nvbo->map = nouveau_bo(new)->map;
615
616         nouveau_bo(new)->handle = t_handle;
617         nouveau_bo(new)->domain = t_domain;
618         nouveau_bo(new)->offset = t_offset;
619         nouveau_bo(new)->size = t_size;
620         nouveau_bo(new)->map = t_map;
621
622         nouveau_bo_ref(NULL, &new);
623
624         return 0;
625 }
626
627 static int
628 nouveau_bo_pin_nomm(struct nouveau_bo *bo, uint32_t flags)
629 {
630         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
631         int ret;
632
633         if (!nvbo->handle) {
634                 if (!(flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)))
635                         return -EINVAL;
636
637                 ret = nouveau_bo_validate_nomm(nvbo, flags & ~NOUVEAU_BO_PIN);
638                 if (ret)
639                         return ret;
640         }
641
642         nvbo->pinned = 1;
643
644         /* Fill in public nouveau_bo members */
645         bo->flags = nvbo->domain;
646         bo->offset = nvbo->offset;
647
648         return 0;
649 }
650
651 int
652 nouveau_bo_pin(struct nouveau_bo *bo, uint32_t flags)
653 {
654         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
655         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
656         struct drm_nouveau_gem_pin req;
657         int ret;
658
659         if (nvbo->pinned)
660                 return 0;
661
662         if (!nvdev->mm_enabled)
663                 return nouveau_bo_pin_nomm(bo, flags);
664
665         /* Ensure we have a kernel object... */
666         if (!nvbo->handle) {
667                 if (!(flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)))
668                         return -EINVAL;
669                 nvbo->flags = flags;
670
671                 ret = nouveau_bo_kalloc(nvbo, NULL);
672                 if (ret)
673                         return ret;
674         }
675
676         /* Now force it to stay put :) */
677         req.handle = nvbo->handle;
678         req.domain = 0;
679         if (nvbo->flags & NOUVEAU_BO_VRAM)
680                 req.domain |= NOUVEAU_GEM_DOMAIN_VRAM;
681         if (nvbo->flags & NOUVEAU_BO_GART)
682                 req.domain |= NOUVEAU_GEM_DOMAIN_GART;
683
684         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PIN, &req,
685                                   sizeof(struct drm_nouveau_gem_pin));
686         if (ret)
687                 return ret;
688         nvbo->offset = req.offset;
689         nvbo->domain = req.domain;
690         nvbo->pinned = 1;
691         nvbo->flags |= NOUVEAU_BO_PIN;
692
693         /* Fill in public nouveau_bo members */
694         if (nvbo->domain & NOUVEAU_GEM_DOMAIN_VRAM)
695                 bo->flags = NOUVEAU_BO_VRAM;
696         if (nvbo->domain & NOUVEAU_GEM_DOMAIN_GART)
697                 bo->flags = NOUVEAU_BO_GART;
698         bo->offset = nvbo->offset;
699
700         return 0;
701 }
702
703 void
704 nouveau_bo_unpin(struct nouveau_bo *bo)
705 {
706         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
707         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
708         struct drm_nouveau_gem_unpin req;
709
710         if (!nvbo->pinned)
711                 return;
712
713         if (nvdev->mm_enabled) {
714                 req.handle = nvbo->handle;
715                 drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_UNPIN,
716                                 &req, sizeof(req));
717         }
718
719         nvbo->pinned = bo->offset = bo->flags = 0;
720 }
721
722 int
723 nouveau_bo_tile(struct nouveau_bo *bo, uint32_t flags, uint32_t delta,
724                 uint32_t size)
725 {
726         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
727         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
728         uint32_t kern_flags = 0;
729         int ret = 0;
730
731         if (flags & NOUVEAU_BO_TILED) {
732                 kern_flags |= NOUVEAU_MEM_TILE;
733                 if (flags & NOUVEAU_BO_ZTILE)
734                         kern_flags |= NOUVEAU_MEM_TILE_ZETA;
735         }
736
737         if (nvdev->mm_enabled) {
738                 struct drm_nouveau_gem_tile req;
739
740                 req.handle = nvbo->handle;
741                 req.delta = delta;
742                 req.size = size;
743                 req.flags = kern_flags;
744                 ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_TILE,
745                                       &req, sizeof(req));
746         } else {
747                 struct drm_nouveau_mem_tile req;
748
749                 req.offset = nvbo->offset;
750                 req.delta = delta;
751                 req.size = size;
752                 req.flags = kern_flags;
753
754                 if (flags & NOUVEAU_BO_VRAM)
755                         req.flags |= NOUVEAU_MEM_FB;
756                 if (flags & NOUVEAU_BO_GART)
757                         req.flags |= NOUVEAU_MEM_AGP;
758
759                 ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_MEM_TILE,
760                                       &req, sizeof(req));
761         }
762
763         return 0;
764 }
765
766 int
767 nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
768 {
769         struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
770         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
771
772         if (!nvdev->mm_enabled) {
773                 struct nouveau_fence *fence;
774
775                 if (nvbo->pending && (nvbo->pending->write_domains ||
776                                       (access & NOUVEAU_BO_WR)))
777                         return 1;
778
779                 if (access & NOUVEAU_BO_WR)
780                         fence = nvbo->fence;
781                 else
782                         fence = nvbo->wr_fence;
783                 return !nouveau_fence(fence)->signalled;
784         }
785
786         return 1;
787 }
788
789 #include <stdio.h>
790 struct drm_nouveau_gem_pushbuf_bo *
791 nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
792 {
793         struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
794         struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
795         struct drm_nouveau_gem_pushbuf_bo *pbbo;
796         struct nouveau_bo *ref = NULL;
797         int ret;
798
799         if (nvbo->pending)
800                 return nvbo->pending;
801
802         if (!nvbo->handle) {
803                 ret = nouveau_bo_kalloc(nvbo, chan);
804                 if (ret)
805                         return NULL;
806
807                 if (nvbo->sysmem) {
808                         void *sysmem_tmp = nvbo->sysmem;
809
810                         nvbo->sysmem = NULL;
811                         ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
812                         if (ret)
813                                 return NULL;
814                         nvbo->sysmem = sysmem_tmp;
815
816                         memcpy(bo->map, nvbo->sysmem, nvbo->base.size);
817                         nouveau_bo_unmap(bo);
818                         nouveau_bo_ufree(nvbo);
819                 }
820         }
821
822         if (nvpb->nr_buffers >= NOUVEAU_PUSHBUF_MAX_BUFFERS)
823                 return NULL;
824         pbbo = nvpb->buffers + nvpb->nr_buffers++;
825         nvbo->pending = pbbo;
826         nvbo->pending_channel = chan;
827
828         nouveau_bo_ref(bo, &ref);
829         pbbo->user_priv = (uint64_t)(unsigned long)ref;
830         pbbo->handle = nvbo->handle;
831         pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
832         pbbo->read_domains = 0;
833         pbbo->write_domains = 0;
834         pbbo->presumed_domain = nvbo->domain;
835         pbbo->presumed_offset = nvbo->offset;
836         pbbo->presumed_ok = 1;
837         return pbbo;
838 }