1/********************************************************** 2 * Copyright 2009 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 * TODO: Have the query pool always ask the fence manager for 37 * SVGA_FENCE_FLAG_QUERY signaled. Unfortunately, pb_fenced doesn't 38 * support that currently, so we'd have to create a separate 39 * pb_fence_ops wrapper that does this implicitly. 40 */ 41 42/** 43 * vmw_pools_cleanup - Destroy the buffer pools. 44 * 45 * @vws: pointer to a struct vmw_winsys_screen. 46 */ 47void 48vmw_pools_cleanup(struct vmw_winsys_screen *vws) 49{ 50 if(vws->pools.gmr_fenced) 51 vws->pools.gmr_fenced->destroy(vws->pools.gmr_fenced); 52 if (vws->pools.query_fenced) 53 vws->pools.query_fenced->destroy(vws->pools.query_fenced); 54 55 /* gmr_mm pool is already destroyed above */ 56 57 if (vws->pools.gmr_slab_fenced) 58 vws->pools.gmr_slab_fenced->destroy(vws->pools.gmr_slab_fenced); 59 60 if(vws->pools.gmr) 61 vws->pools.gmr->destroy(vws->pools.gmr); 62 if(vws->pools.query) 63 vws->pools.query->destroy(vws->pools.query); 64} 65 66 67/** 68 * vmw_query_pools_init - Create a pool of query buffers. 69 * 70 * @vws: Pointer to a struct vmw_winsys_screen. 71 * 72 * Typically this pool should be created on demand when we 73 * detect that the app will be using queries. There's nothing 74 * special with this pool other than the backing kernel buffer size, 75 * which is limited to 8192. 76 */ 77boolean 78vmw_query_pools_init(struct vmw_winsys_screen *vws) 79{ 80 vws->pools.query = vmw_gmr_bufmgr_create(vws); 81 if(!vws->pools.query) 82 return FALSE; 83 84 vws->pools.query_mm = mm_bufmgr_create(vws->pools.query, 85 VMW_QUERY_POOL_SIZE, 86 3 /* 8 alignment */); 87 if(!vws->pools.query_mm) 88 goto out_no_query_mm; 89 90 vws->pools.query_fenced = fenced_bufmgr_create( 91 vws->pools.query_mm, 92 vmw_fence_ops_create(vws), 93 VMW_QUERY_POOL_SIZE, 94 ~0); 95 96 if(!vws->pools.query_fenced) 97 goto out_no_query_fenced; 98 99 return TRUE; 100 101 out_no_query_fenced: 102 vws->pools.query_mm->destroy(vws->pools.query_mm); 103 out_no_query_mm: 104 vws->pools.query->destroy(vws->pools.query); 105 return FALSE; 106} 107 108/** 109 * vmw_pools_init - Create a pool of GMR buffers. 110 * 111 * @vws: Pointer to a struct vmw_winsys_screen. 112 */ 113boolean 114vmw_pools_init(struct vmw_winsys_screen *vws) 115{ 116 struct pb_desc desc; 117 118 vws->pools.gmr = vmw_gmr_bufmgr_create(vws); 119 if(!vws->pools.gmr) 120 goto error; 121 122 vws->pools.gmr_mm = mm_bufmgr_create(vws->pools.gmr, 123 VMW_GMR_POOL_SIZE, 124 12 /* 4096 alignment */); 125 if(!vws->pools.gmr_mm) 126 goto error; 127 128 /* 129 * We disallow "CPU" buffers to be created by the fenced_bufmgr_create, 130 * because that defers "GPU" buffer creation to buffer validation, 131 * and at buffer validation we have no means of handling failures 132 * due to pools space shortage or fragmentation. Effectively this 133 * makes sure all failures are reported immediately on buffer allocation, 134 * and we can revert to allocating directly from the kernel. 135 */ 136 vws->pools.gmr_fenced = fenced_bufmgr_create( 137 vws->pools.gmr_mm, 138 vmw_fence_ops_create(vws), 139 VMW_GMR_POOL_SIZE, 140 0); 141 142#ifdef DEBUG 143 vws->pools.gmr_fenced = pb_debug_manager_create(vws->pools.gmr_fenced, 144 4096, 145 4096); 146#endif 147 if(!vws->pools.gmr_fenced) 148 goto error; 149 150 /* 151 * The slab pool allocates buffers directly from the kernel except 152 * for very small buffers which are allocated from a slab in order 153 * not to waste memory, since a kernel buffer is a minimum 4096 bytes. 154 * 155 * Here we use it only for emergency in the case our pre-allocated 156 * buffer pool runs out of memory. 157 */ 158 desc.alignment = 64; 159 desc.usage = ~0; 160 vws->pools.gmr_slab = pb_slab_range_manager_create(vws->pools.gmr, 161 64, 162 8192, 163 16384, 164 &desc); 165 if (!vws->pools.gmr_slab) 166 goto error; 167 168 vws->pools.gmr_slab_fenced = 169 fenced_bufmgr_create(vws->pools.gmr_slab, 170 vmw_fence_ops_create(vws), 171 VMW_MAX_BUFFER_SIZE, 172 0); 173 174 if (!vws->pools.gmr_slab_fenced) 175 goto error; 176 177 vws->pools.query_fenced = NULL; 178 vws->pools.query_mm = NULL; 179 vws->pools.query = NULL; 180 181 return TRUE; 182 183error: 184 vmw_pools_cleanup(vws); 185 return FALSE; 186} 187 188