Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2006 VMware, Inc., Bismarck, ND., USA
4
 * All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
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 NON-INFRINGEMENT. IN NO EVENT SHALL
17
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21
 *
22
 * The above copyright notice and this permission notice (including the
23
 * next paragraph) shall be included in all copies or substantial portions
24
 * of the Software.
25
 *
26
 *
27
 **************************************************************************/
28
 
29
/**
30
 * \file
31
 * Batch buffer pool management.
32
 *
33
 * \author Jose Fonseca 
34
 * \author Thomas Hellström 
35
 */
36
 
37
 
38
#include "pipe/p_compiler.h"
39
#include "util/u_debug.h"
40
#include "os/os_thread.h"
41
#include "pipe/p_defines.h"
42
#include "util/u_memory.h"
43
#include "util/list.h"
44
 
45
#include "pb_buffer.h"
46
#include "pb_bufmgr.h"
47
 
48
 
49
/**
50
 * Convenience macro (type safe).
51
 */
52
#define SUPER(__derived) (&(__derived)->base)
53
 
54
 
55
struct pool_pb_manager
56
{
57
   struct pb_manager base;
58
 
59
   pipe_mutex mutex;
60
 
61
   pb_size bufSize;
62
   pb_size bufAlign;
63
 
64
   pb_size numFree;
65
   pb_size numTot;
66
 
67
   struct list_head free;
68
 
69
   struct pb_buffer *buffer;
70
   void *map;
71
 
72
   struct pool_buffer *bufs;
73
};
74
 
75
 
76
static INLINE struct pool_pb_manager *
77
pool_pb_manager(struct pb_manager *mgr)
78
{
79
   assert(mgr);
80
   return (struct pool_pb_manager *)mgr;
81
}
82
 
83
 
84
struct pool_buffer
85
{
86
   struct pb_buffer base;
87
 
88
   struct pool_pb_manager *mgr;
89
 
90
   struct list_head head;
91
 
92
   pb_size start;
93
};
94
 
95
 
96
static INLINE struct pool_buffer *
97
pool_buffer(struct pb_buffer *buf)
98
{
99
   assert(buf);
100
   return (struct pool_buffer *)buf;
101
}
102
 
103
 
104
 
105
static void
106
pool_buffer_destroy(struct pb_buffer *buf)
107
{
108
   struct pool_buffer *pool_buf = pool_buffer(buf);
109
   struct pool_pb_manager *pool = pool_buf->mgr;
110
 
111
   assert(!pipe_is_referenced(&pool_buf->base.reference));
112
 
113
   pipe_mutex_lock(pool->mutex);
114
   LIST_ADD(&pool_buf->head, &pool->free);
115
   pool->numFree++;
116
   pipe_mutex_unlock(pool->mutex);
117
}
118
 
119
 
120
static void *
121
pool_buffer_map(struct pb_buffer *buf, unsigned flags, void *flush_ctx)
122
{
123
   struct pool_buffer *pool_buf = pool_buffer(buf);
124
   struct pool_pb_manager *pool = pool_buf->mgr;
125
   void *map;
126
 
127
   /* XXX: it will be necessary to remap here to propagate flush_ctx */
128
 
129
   pipe_mutex_lock(pool->mutex);
130
   map = (unsigned char *) pool->map + pool_buf->start;
131
   pipe_mutex_unlock(pool->mutex);
132
   return map;
133
}
134
 
135
 
136
static void
137
pool_buffer_unmap(struct pb_buffer *buf)
138
{
139
   /* No-op */
140
}
141
 
142
 
143
static enum pipe_error
144
pool_buffer_validate(struct pb_buffer *buf,
145
                     struct pb_validate *vl,
146
                     unsigned flags)
147
{
148
   struct pool_buffer *pool_buf = pool_buffer(buf);
149
   struct pool_pb_manager *pool = pool_buf->mgr;
150
   return pb_validate(pool->buffer, vl, flags);
151
}
152
 
153
 
154
static void
155
pool_buffer_fence(struct pb_buffer *buf,
156
                  struct pipe_fence_handle *fence)
157
{
158
   struct pool_buffer *pool_buf = pool_buffer(buf);
159
   struct pool_pb_manager *pool = pool_buf->mgr;
160
   pb_fence(pool->buffer, fence);
161
}
162
 
163
 
164
static void
165
pool_buffer_get_base_buffer(struct pb_buffer *buf,
166
                            struct pb_buffer **base_buf,
167
                            pb_size *offset)
168
{
169
   struct pool_buffer *pool_buf = pool_buffer(buf);
170
   struct pool_pb_manager *pool = pool_buf->mgr;
171
   pb_get_base_buffer(pool->buffer, base_buf, offset);
172
   *offset += pool_buf->start;
173
}
174
 
175
 
176
static const struct pb_vtbl
177
pool_buffer_vtbl = {
178
      pool_buffer_destroy,
179
      pool_buffer_map,
180
      pool_buffer_unmap,
181
      pool_buffer_validate,
182
      pool_buffer_fence,
183
      pool_buffer_get_base_buffer
184
};
185
 
186
 
187
static struct pb_buffer *
188
pool_bufmgr_create_buffer(struct pb_manager *mgr,
189
                          pb_size size,
190
                          const struct pb_desc *desc)
191
{
192
   struct pool_pb_manager *pool = pool_pb_manager(mgr);
193
   struct pool_buffer *pool_buf;
194
   struct list_head *item;
195
 
196
   assert(size == pool->bufSize);
197
   assert(pool->bufAlign % desc->alignment == 0);
198
 
199
   pipe_mutex_lock(pool->mutex);
200
 
201
   if (pool->numFree == 0) {
202
      pipe_mutex_unlock(pool->mutex);
203
      debug_printf("warning: out of fixed size buffer objects\n");
204
      return NULL;
205
   }
206
 
207
   item = pool->free.next;
208
 
209
   if (item == &pool->free) {
210
      pipe_mutex_unlock(pool->mutex);
211
      debug_printf("error: fixed size buffer pool corruption\n");
212
      return NULL;
213
   }
214
 
215
   LIST_DEL(item);
216
   --pool->numFree;
217
 
218
   pipe_mutex_unlock(pool->mutex);
219
 
220
   pool_buf = LIST_ENTRY(struct pool_buffer, item, head);
221
   assert(!pipe_is_referenced(&pool_buf->base.reference));
222
   pipe_reference_init(&pool_buf->base.reference, 1);
223
   pool_buf->base.alignment = desc->alignment;
224
   pool_buf->base.usage = desc->usage;
225
 
226
   return SUPER(pool_buf);
227
}
228
 
229
 
230
static void
231
pool_bufmgr_flush(struct pb_manager *mgr)
232
{
233
   /* No-op */
234
}
235
 
236
 
237
static void
238
pool_bufmgr_destroy(struct pb_manager *mgr)
239
{
240
   struct pool_pb_manager *pool = pool_pb_manager(mgr);
241
   pipe_mutex_lock(pool->mutex);
242
 
243
   FREE(pool->bufs);
244
 
245
   pb_unmap(pool->buffer);
246
   pb_reference(&pool->buffer, NULL);
247
 
248
   pipe_mutex_unlock(pool->mutex);
249
 
250
   FREE(mgr);
251
}
252
 
253
 
254
struct pb_manager *
255
pool_bufmgr_create(struct pb_manager *provider,
256
                   pb_size numBufs,
257
                   pb_size bufSize,
258
                   const struct pb_desc *desc)
259
{
260
   struct pool_pb_manager *pool;
261
   struct pool_buffer *pool_buf;
262
   pb_size i;
263
 
264
   if(!provider)
265
      return NULL;
266
 
267
   pool = CALLOC_STRUCT(pool_pb_manager);
268
   if (!pool)
269
      return NULL;
270
 
271
   pool->base.destroy = pool_bufmgr_destroy;
272
   pool->base.create_buffer = pool_bufmgr_create_buffer;
273
   pool->base.flush = pool_bufmgr_flush;
274
 
275
   LIST_INITHEAD(&pool->free);
276
 
277
   pool->numTot = numBufs;
278
   pool->numFree = numBufs;
279
   pool->bufSize = bufSize;
280
   pool->bufAlign = desc->alignment;
281
 
282
   pipe_mutex_init(pool->mutex);
283
 
284
   pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc);
285
   if (!pool->buffer)
286
      goto failure;
287
 
288
   pool->map = pb_map(pool->buffer,
289
                          PB_USAGE_CPU_READ |
290
                          PB_USAGE_CPU_WRITE, NULL);
291
   if(!pool->map)
292
      goto failure;
293
 
294
   pool->bufs = (struct pool_buffer *)CALLOC(numBufs, sizeof(*pool->bufs));
295
   if (!pool->bufs)
296
      goto failure;
297
 
298
   pool_buf = pool->bufs;
299
   for (i = 0; i < numBufs; ++i) {
300
      pipe_reference_init(&pool_buf->base.reference, 0);
301
      pool_buf->base.alignment = 0;
302
      pool_buf->base.usage = 0;
303
      pool_buf->base.size = bufSize;
304
      pool_buf->base.vtbl = &pool_buffer_vtbl;
305
      pool_buf->mgr = pool;
306
      pool_buf->start = i * bufSize;
307
      LIST_ADDTAIL(&pool_buf->head, &pool->free);
308
      pool_buf++;
309
   }
310
 
311
   return SUPER(pool);
312
 
313
failure:
314
   FREE(pool->bufs);
315
   if(pool->map)
316
      pb_unmap(pool->buffer);
317
   if(pool->buffer)
318
      pb_reference(&pool->buffer, NULL);
319
   FREE(pool);
320
   return NULL;
321
}