1 /**********************************************************
2 * Copyright 2009-2015 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26
27 #include "vmw_screen.h"
28
29 #include "vmw_buffer.h"
30 #include "vmw_fence.h"
31
32 #include "pipebuffer/pb_buffer.h"
33 #include "pipebuffer/pb_bufmgr.h"
34
35 /**
36 * vmw_pools_cleanup - Destroy the buffer pools.
37 *
38 * @vws: pointer to a struct vmw_winsys_screen.
39 */
40 void
vmw_pools_cleanup(struct vmw_winsys_screen * vws)41 vmw_pools_cleanup(struct vmw_winsys_screen *vws)
42 {
43 if (vws->pools.mob_shader_slab_fenced)
44 vws->pools.mob_shader_slab_fenced->destroy
45 (vws->pools.mob_shader_slab_fenced);
46 if (vws->pools.mob_shader_slab)
47 vws->pools.mob_shader_slab->destroy(vws->pools.mob_shader_slab);
48 if (vws->pools.mob_fenced)
49 vws->pools.mob_fenced->destroy(vws->pools.mob_fenced);
50 if (vws->pools.mob_cache)
51 vws->pools.mob_cache->destroy(vws->pools.mob_cache);
52
53 if (vws->pools.query_fenced)
54 vws->pools.query_fenced->destroy(vws->pools.query_fenced);
55 if (vws->pools.query_mm)
56 vws->pools.query_mm->destroy(vws->pools.query_mm);
57
58 if(vws->pools.gmr_fenced)
59 vws->pools.gmr_fenced->destroy(vws->pools.gmr_fenced);
60 if (vws->pools.gmr_mm)
61 vws->pools.gmr_mm->destroy(vws->pools.gmr_mm);
62 if (vws->pools.gmr_slab_fenced)
63 vws->pools.gmr_slab_fenced->destroy(vws->pools.gmr_slab_fenced);
64 if (vws->pools.gmr_slab)
65 vws->pools.gmr_slab->destroy(vws->pools.gmr_slab);
66
67 if(vws->pools.gmr)
68 vws->pools.gmr->destroy(vws->pools.gmr);
69 }
70
71
72 /**
73 * vmw_query_pools_init - Create a pool of query buffers.
74 *
75 * @vws: Pointer to a struct vmw_winsys_screen.
76 *
77 * Typically this pool should be created on demand when we
78 * detect that the app will be using queries. There's nothing
79 * special with this pool other than the backing kernel buffer sizes,
80 * which are limited to 8192.
81 * If there is a performance issue with allocation and freeing of the
82 * query slabs, it should be easily fixable by allocating them out
83 * of a buffer cache.
84 */
85 boolean
vmw_query_pools_init(struct vmw_winsys_screen * vws)86 vmw_query_pools_init(struct vmw_winsys_screen *vws)
87 {
88 struct pb_desc desc;
89
90 desc.alignment = 16;
91 desc.usage = ~(VMW_BUFFER_USAGE_SHARED | VMW_BUFFER_USAGE_SYNC);
92
93 vws->pools.query_mm = pb_slab_range_manager_create(vws->pools.gmr, 16, 128,
94 VMW_QUERY_POOL_SIZE,
95 &desc);
96 if (!vws->pools.query_mm)
97 return FALSE;
98
99 vws->pools.query_fenced = simple_fenced_bufmgr_create(
100 vws->pools.query_mm, vws->fence_ops);
101
102 if(!vws->pools.query_fenced)
103 goto out_no_query_fenced;
104
105 return TRUE;
106
107 out_no_query_fenced:
108 vws->pools.query_mm->destroy(vws->pools.query_mm);
109 return FALSE;
110 }
111
112 /**
113 * vmw_mob_pool_init - Create a pool of fenced kernel buffers.
114 *
115 * @vws: Pointer to a struct vmw_winsys_screen.
116 *
117 * Typically this pool should be created on demand when we
118 * detect that the app will be using MOB buffers.
119 */
120 boolean
vmw_mob_pools_init(struct vmw_winsys_screen * vws)121 vmw_mob_pools_init(struct vmw_winsys_screen *vws)
122 {
123 struct pb_desc desc;
124
125 vws->pools.mob_cache =
126 pb_cache_manager_create(vws->pools.gmr, 100000, 2.0f,
127 VMW_BUFFER_USAGE_SHARED,
128 64 * 1024 * 1024);
129 if (!vws->pools.mob_cache)
130 return FALSE;
131
132 vws->pools.mob_fenced =
133 simple_fenced_bufmgr_create(vws->pools.mob_cache,
134 vws->fence_ops);
135 if(!vws->pools.mob_fenced)
136 goto out_no_mob_fenced;
137
138 desc.alignment = 64;
139 desc.usage = ~(SVGA_BUFFER_USAGE_PINNED | VMW_BUFFER_USAGE_SHARED |
140 VMW_BUFFER_USAGE_SYNC);
141 vws->pools.mob_shader_slab =
142 pb_slab_range_manager_create(vws->pools.mob_cache,
143 64,
144 8192,
145 16384,
146 &desc);
147 if(!vws->pools.mob_shader_slab)
148 goto out_no_mob_shader_slab;
149
150 vws->pools.mob_shader_slab_fenced =
151 simple_fenced_bufmgr_create(vws->pools.mob_shader_slab,
152 vws->fence_ops);
153 if(!vws->pools.mob_fenced)
154 goto out_no_mob_shader_slab_fenced;
155
156 return TRUE;
157
158 out_no_mob_shader_slab_fenced:
159 vws->pools.mob_shader_slab->destroy(vws->pools.mob_shader_slab);
160 out_no_mob_shader_slab:
161 vws->pools.mob_fenced->destroy(vws->pools.mob_fenced);
162 out_no_mob_fenced:
163 vws->pools.mob_cache->destroy(vws->pools.mob_cache);
164 return FALSE;
165 }
166
167 /**
168 * vmw_pools_init - Create a pool of GMR buffers.
169 *
170 * @vws: Pointer to a struct vmw_winsys_screen.
171 */
172 boolean
vmw_pools_init(struct vmw_winsys_screen * vws)173 vmw_pools_init(struct vmw_winsys_screen *vws)
174 {
175 struct pb_desc desc;
176
177 vws->pools.gmr = vmw_gmr_bufmgr_create(vws);
178 if(!vws->pools.gmr)
179 goto error;
180
181 if ((vws->base.have_gb_objects && vws->base.have_gb_dma) ||
182 !vws->base.have_gb_objects) {
183 /*
184 * A managed pool for DMA buffers.
185 */
186 vws->pools.gmr_mm = mm_bufmgr_create(vws->pools.gmr,
187 VMW_GMR_POOL_SIZE,
188 12 /* 4096 alignment */);
189 if(!vws->pools.gmr_mm)
190 goto error;
191
192 vws->pools.gmr_fenced = simple_fenced_bufmgr_create
193 (vws->pools.gmr_mm, vws->fence_ops);
194
195 #ifdef DEBUG
196 vws->pools.gmr_fenced = pb_debug_manager_create(vws->pools.gmr_fenced,
197 4096,
198 4096);
199 #endif
200 if(!vws->pools.gmr_fenced)
201 goto error;
202
203 /*
204 * The slab pool allocates buffers directly from the kernel except
205 * for very small buffers which are allocated from a slab in order
206 * not to waste memory, since a kernel buffer is a minimum 4096 bytes.
207 *
208 * Here we use it only for emergency in the case our pre-allocated
209 * managed buffer pool runs out of memory.
210 */
211
212 desc.alignment = 64;
213 desc.usage = ~(SVGA_BUFFER_USAGE_PINNED | SVGA_BUFFER_USAGE_SHADER |
214 VMW_BUFFER_USAGE_SHARED | VMW_BUFFER_USAGE_SYNC);
215 vws->pools.gmr_slab = pb_slab_range_manager_create(vws->pools.gmr,
216 64,
217 8192,
218 16384,
219 &desc);
220 if (!vws->pools.gmr_slab)
221 goto error;
222
223 vws->pools.gmr_slab_fenced =
224 simple_fenced_bufmgr_create(vws->pools.gmr_slab, vws->fence_ops);
225
226 if (!vws->pools.gmr_slab_fenced)
227 goto error;
228 }
229
230 vws->pools.query_fenced = NULL;
231 vws->pools.query_mm = NULL;
232 vws->pools.mob_cache = NULL;
233
234 if (vws->base.have_gb_objects && !vmw_mob_pools_init(vws))
235 goto error;
236
237 return TRUE;
238
239 error:
240 vmw_pools_cleanup(vws);
241 return FALSE;
242 }
243