OSDN Git Service

freedreno/msm: get rid of ring_bo unref hack
[android-x86/external-libdrm.git] / freedreno / freedreno_ringbuffer.c
1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3 /*
4  * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Authors:
26  *    Rob Clark <robclark@freedesktop.org>
27  */
28
29 #include <assert.h>
30
31 #include "freedreno_drmif.h"
32 #include "freedreno_priv.h"
33 #include "freedreno_ringbuffer.h"
34
35 static struct fd_ringbuffer *
36 ringbuffer_new(struct fd_pipe *pipe, uint32_t size,
37                 enum fd_ringbuffer_flags flags)
38 {
39         struct fd_ringbuffer *ring;
40
41         ring = pipe->funcs->ringbuffer_new(pipe, size, flags);
42         if (!ring)
43                 return NULL;
44
45         ring->flags = flags;
46         ring->pipe = pipe;
47         ring->start = ring->funcs->hostptr(ring);
48         ring->end = &(ring->start[ring->size/4]);
49
50         ring->cur = ring->last_start = ring->start;
51
52         return ring;
53 }
54
55 drm_public struct fd_ringbuffer *
56 fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size)
57 {
58         return ringbuffer_new(pipe, size, 0);
59 }
60
61 drm_public struct fd_ringbuffer *
62 fd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size)
63 {
64         /* we can't really support "growable" rb's in general for
65          * stateobj's since we need a single gpu addr (ie. can't
66          * do the trick of a chain of IB packets):
67          */
68         assert(size);
69         return ringbuffer_new(pipe, size, FD_RINGBUFFER_OBJECT);
70 }
71
72 drm_public void fd_ringbuffer_del(struct fd_ringbuffer *ring)
73 {
74         if (!(ring->flags & FD_RINGBUFFER_OBJECT))
75                 fd_ringbuffer_reset(ring);
76         ring->funcs->destroy(ring);
77 }
78
79 /* ringbuffers which are IB targets should set the toplevel rb (ie.
80  * the IB source) as it's parent before emitting reloc's, to ensure
81  * the bookkeeping works out properly.
82  */
83 drm_public void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring,
84                                          struct fd_ringbuffer *parent)
85 {
86         /* state objects should not be parented! */
87         assert(!(ring->flags & FD_RINGBUFFER_OBJECT));
88         ring->parent = parent;
89 }
90
91 drm_public void fd_ringbuffer_reset(struct fd_ringbuffer *ring)
92 {
93         uint32_t *start = ring->start;
94         if (ring->pipe->id == FD_PIPE_2D)
95                 start = &ring->start[0x140];
96         ring->cur = ring->last_start = start;
97         if (ring->funcs->reset)
98                 ring->funcs->reset(ring);
99 }
100
101 drm_public int fd_ringbuffer_flush(struct fd_ringbuffer *ring)
102 {
103         return ring->funcs->flush(ring, ring->last_start, -1, NULL);
104 }
105
106 drm_public int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd,
107                 int *out_fence_fd)
108 {
109         return ring->funcs->flush(ring, ring->last_start, in_fence_fd, out_fence_fd);
110 }
111
112 drm_public void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords)
113 {
114         assert(ring->funcs->grow);     /* unsupported on kgsl */
115
116         /* there is an upper bound on IB size, which appears to be 0x100000 */
117         if (ring->size < 0x100000)
118                 ring->size *= 2;
119
120         ring->funcs->grow(ring, ring->size);
121
122         ring->start = ring->funcs->hostptr(ring);
123         ring->end = &(ring->start[ring->size/4]);
124
125         ring->cur = ring->last_start = ring->start;
126 }
127
128 drm_public uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring)
129 {
130         return ring->last_timestamp;
131 }
132
133 drm_public void fd_ringbuffer_reloc(struct fd_ringbuffer *ring,
134                                     const struct fd_reloc *reloc)
135 {
136         assert(ring->pipe->gpu_id < 500);
137         ring->funcs->emit_reloc(ring, reloc);
138 }
139
140 drm_public void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring,
141                                      const struct fd_reloc *reloc)
142 {
143         ring->funcs->emit_reloc(ring, reloc);
144 }
145
146 drm_public void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
147                 struct fd_ringmarker *target, struct fd_ringmarker *end)
148 {
149         uint32_t submit_offset, size;
150
151         /* This function is deprecated and not supported on 64b devices: */
152         assert(ring->pipe->gpu_id < 500);
153         assert(target->ring == end->ring);
154
155         submit_offset = offset_bytes(target->cur, target->ring->start);
156         size = offset_bytes(end->cur, target->cur);
157
158         ring->funcs->emit_reloc_ring(ring, target->ring, 0, submit_offset, size);
159 }
160
161 drm_public uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
162 {
163         if (!ring->funcs->cmd_count)
164                 return 1;
165         return ring->funcs->cmd_count(ring);
166 }
167
168 drm_public uint32_t
169 fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring,
170                 struct fd_ringbuffer *target, uint32_t cmd_idx)
171 {
172         uint32_t size = offset_bytes(target->cur, target->start);
173         return ring->funcs->emit_reloc_ring(ring, target, cmd_idx, 0, size);
174 }
175
176 drm_public uint32_t
177 fd_ringbuffer_size(struct fd_ringbuffer *ring)
178 {
179         /* only really needed for stateobj ringbuffers, and won't really
180          * do what you expect for growable rb's.. so lets just restrict
181          * this to stateobj's for now:
182          */
183         assert(ring->flags & FD_RINGBUFFER_OBJECT);
184         return offset_bytes(ring->cur, ring->start);
185 }
186
187 /*
188  * Deprecated ringmarker API:
189  */
190
191 drm_public struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring)
192 {
193         struct fd_ringmarker *marker = NULL;
194
195         marker = calloc(1, sizeof(*marker));
196         if (!marker) {
197                 ERROR_MSG("allocation failed");
198                 return NULL;
199         }
200
201         marker->ring = ring;
202
203         marker->cur = marker->ring->cur;
204
205         return marker;
206 }
207
208 drm_public void fd_ringmarker_del(struct fd_ringmarker *marker)
209 {
210         free(marker);
211 }
212
213 drm_public void fd_ringmarker_mark(struct fd_ringmarker *marker)
214 {
215         marker->cur = marker->ring->cur;
216 }
217
218 drm_public uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start,
219                                          struct fd_ringmarker *end)
220 {
221         return end->cur - start->cur;
222 }
223
224 drm_public int fd_ringmarker_flush(struct fd_ringmarker *marker)
225 {
226         struct fd_ringbuffer *ring = marker->ring;
227         return ring->funcs->flush(ring, marker->cur, -1, NULL);
228 }