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_shader_slab_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