1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2006 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/**
29bf215546Sopenharmony_ci * \file
30bf215546Sopenharmony_ci * Buffer manager using the old texture memory manager.
31bf215546Sopenharmony_ci *
32bf215546Sopenharmony_ci * \author Jose Fonseca <jfonseca@vmware.com>
33bf215546Sopenharmony_ci */
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "pipe/p_defines.h"
37bf215546Sopenharmony_ci#include "util/u_debug.h"
38bf215546Sopenharmony_ci#include "os/os_thread.h"
39bf215546Sopenharmony_ci#include "util/u_memory.h"
40bf215546Sopenharmony_ci#include "util/list.h"
41bf215546Sopenharmony_ci#include "util/u_mm.h"
42bf215546Sopenharmony_ci#include "pb_buffer.h"
43bf215546Sopenharmony_ci#include "pb_bufmgr.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci/**
47bf215546Sopenharmony_ci * Convenience macro (type safe).
48bf215546Sopenharmony_ci */
49bf215546Sopenharmony_ci#define SUPER(__derived) (&(__derived)->base)
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_cistruct mm_pb_manager
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci   struct pb_manager base;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   mtx_t mutex;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   pb_size size;
59bf215546Sopenharmony_ci   struct mem_block *heap;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   pb_size align2;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   struct pb_buffer *buffer;
64bf215546Sopenharmony_ci   void *map;
65bf215546Sopenharmony_ci};
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_cistatic inline struct mm_pb_manager *
69bf215546Sopenharmony_cimm_pb_manager(struct pb_manager *mgr)
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci   assert(mgr);
72bf215546Sopenharmony_ci   return (struct mm_pb_manager *)mgr;
73bf215546Sopenharmony_ci}
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_cistruct mm_buffer
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci   struct pb_buffer base;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   struct mm_pb_manager *mgr;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   struct mem_block *block;
83bf215546Sopenharmony_ci};
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_cistatic inline struct mm_buffer *
87bf215546Sopenharmony_cimm_buffer(struct pb_buffer *buf)
88bf215546Sopenharmony_ci{
89bf215546Sopenharmony_ci   assert(buf);
90bf215546Sopenharmony_ci   return (struct mm_buffer *)buf;
91bf215546Sopenharmony_ci}
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_cistatic void
95bf215546Sopenharmony_cimm_buffer_destroy(void *winsys, struct pb_buffer *buf)
96bf215546Sopenharmony_ci{
97bf215546Sopenharmony_ci   struct mm_buffer *mm_buf = mm_buffer(buf);
98bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_buf->mgr;
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   assert(!pipe_is_referenced(&mm_buf->base.reference));
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   mtx_lock(&mm->mutex);
103bf215546Sopenharmony_ci   u_mmFreeMem(mm_buf->block);
104bf215546Sopenharmony_ci   FREE(mm_buf);
105bf215546Sopenharmony_ci   mtx_unlock(&mm->mutex);
106bf215546Sopenharmony_ci}
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_cistatic void *
110bf215546Sopenharmony_cimm_buffer_map(struct pb_buffer *buf,
111bf215546Sopenharmony_ci              enum pb_usage_flags flags,
112bf215546Sopenharmony_ci              void *flush_ctx)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   struct mm_buffer *mm_buf = mm_buffer(buf);
115bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_buf->mgr;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   /* XXX: it will be necessary to remap here to propagate flush_ctx */
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   return (unsigned char *) mm->map + mm_buf->block->ofs;
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_cistatic void
124bf215546Sopenharmony_cimm_buffer_unmap(struct pb_buffer *buf)
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci   /* No-op */
127bf215546Sopenharmony_ci}
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_cistatic enum pipe_error
131bf215546Sopenharmony_cimm_buffer_validate(struct pb_buffer *buf,
132bf215546Sopenharmony_ci                   struct pb_validate *vl,
133bf215546Sopenharmony_ci                   enum pb_usage_flags flags)
134bf215546Sopenharmony_ci{
135bf215546Sopenharmony_ci   struct mm_buffer *mm_buf = mm_buffer(buf);
136bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_buf->mgr;
137bf215546Sopenharmony_ci   return pb_validate(mm->buffer, vl, flags);
138bf215546Sopenharmony_ci}
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_cistatic void
142bf215546Sopenharmony_cimm_buffer_fence(struct pb_buffer *buf,
143bf215546Sopenharmony_ci                struct pipe_fence_handle *fence)
144bf215546Sopenharmony_ci{
145bf215546Sopenharmony_ci   struct mm_buffer *mm_buf = mm_buffer(buf);
146bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_buf->mgr;
147bf215546Sopenharmony_ci   pb_fence(mm->buffer, fence);
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_cistatic void
152bf215546Sopenharmony_cimm_buffer_get_base_buffer(struct pb_buffer *buf,
153bf215546Sopenharmony_ci                          struct pb_buffer **base_buf,
154bf215546Sopenharmony_ci                          pb_size *offset)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   struct mm_buffer *mm_buf = mm_buffer(buf);
157bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_buf->mgr;
158bf215546Sopenharmony_ci   pb_get_base_buffer(mm->buffer, base_buf, offset);
159bf215546Sopenharmony_ci   *offset += mm_buf->block->ofs;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic const struct pb_vtbl
164bf215546Sopenharmony_cimm_buffer_vtbl = {
165bf215546Sopenharmony_ci      mm_buffer_destroy,
166bf215546Sopenharmony_ci      mm_buffer_map,
167bf215546Sopenharmony_ci      mm_buffer_unmap,
168bf215546Sopenharmony_ci      mm_buffer_validate,
169bf215546Sopenharmony_ci      mm_buffer_fence,
170bf215546Sopenharmony_ci      mm_buffer_get_base_buffer
171bf215546Sopenharmony_ci};
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_cistatic struct pb_buffer *
175bf215546Sopenharmony_cimm_bufmgr_create_buffer(struct pb_manager *mgr,
176bf215546Sopenharmony_ci                        pb_size size,
177bf215546Sopenharmony_ci                        const struct pb_desc *desc)
178bf215546Sopenharmony_ci{
179bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_pb_manager(mgr);
180bf215546Sopenharmony_ci   struct mm_buffer *mm_buf;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   /* We don't handle alignments larger then the one initially setup */
183bf215546Sopenharmony_ci   assert(pb_check_alignment(desc->alignment, 1u << mm->align2));
184bf215546Sopenharmony_ci   if(!pb_check_alignment(desc->alignment, 1u << mm->align2))
185bf215546Sopenharmony_ci      return NULL;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   mtx_lock(&mm->mutex);
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   mm_buf = CALLOC_STRUCT(mm_buffer);
190bf215546Sopenharmony_ci   if (!mm_buf) {
191bf215546Sopenharmony_ci      mtx_unlock(&mm->mutex);
192bf215546Sopenharmony_ci      return NULL;
193bf215546Sopenharmony_ci   }
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   pipe_reference_init(&mm_buf->base.reference, 1);
196bf215546Sopenharmony_ci   mm_buf->base.alignment_log2 = util_logbase2(desc->alignment);
197bf215546Sopenharmony_ci   mm_buf->base.usage = desc->usage;
198bf215546Sopenharmony_ci   mm_buf->base.size = size;
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   mm_buf->base.vtbl = &mm_buffer_vtbl;
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   mm_buf->mgr = mm;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   mm_buf->block = u_mmAllocMem(mm->heap, (int)size, (int)mm->align2, 0);
205bf215546Sopenharmony_ci   if(!mm_buf->block) {
206bf215546Sopenharmony_ci#if 0
207bf215546Sopenharmony_ci      debug_printf("warning: heap full\n");
208bf215546Sopenharmony_ci      mmDumpMemInfo(mm->heap);
209bf215546Sopenharmony_ci#endif
210bf215546Sopenharmony_ci      FREE(mm_buf);
211bf215546Sopenharmony_ci      mtx_unlock(&mm->mutex);
212bf215546Sopenharmony_ci      return NULL;
213bf215546Sopenharmony_ci   }
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   /* Some sanity checks */
216bf215546Sopenharmony_ci   assert(0 <= (pb_size)mm_buf->block->ofs && (pb_size)mm_buf->block->ofs < mm->size);
217bf215546Sopenharmony_ci   assert(size <= (pb_size)mm_buf->block->size && (pb_size)mm_buf->block->ofs + (pb_size)mm_buf->block->size <= mm->size);
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   mtx_unlock(&mm->mutex);
220bf215546Sopenharmony_ci   return SUPER(mm_buf);
221bf215546Sopenharmony_ci}
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_cistatic void
225bf215546Sopenharmony_cimm_bufmgr_flush(struct pb_manager *mgr)
226bf215546Sopenharmony_ci{
227bf215546Sopenharmony_ci   /* No-op */
228bf215546Sopenharmony_ci}
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_cistatic void
232bf215546Sopenharmony_cimm_bufmgr_destroy(struct pb_manager *mgr)
233bf215546Sopenharmony_ci{
234bf215546Sopenharmony_ci   struct mm_pb_manager *mm = mm_pb_manager(mgr);
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci   mtx_lock(&mm->mutex);
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   u_mmDestroy(mm->heap);
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci   pb_unmap(mm->buffer);
241bf215546Sopenharmony_ci   pb_reference(&mm->buffer, NULL);
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   mtx_unlock(&mm->mutex);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   FREE(mgr);
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_cistruct pb_manager *
250bf215546Sopenharmony_cimm_bufmgr_create_from_buffer(struct pb_buffer *buffer,
251bf215546Sopenharmony_ci                             pb_size size, pb_size align2)
252bf215546Sopenharmony_ci{
253bf215546Sopenharmony_ci   struct mm_pb_manager *mm;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   if (!buffer)
256bf215546Sopenharmony_ci      return NULL;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   mm = CALLOC_STRUCT(mm_pb_manager);
259bf215546Sopenharmony_ci   if (!mm)
260bf215546Sopenharmony_ci      return NULL;
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci   mm->base.destroy = mm_bufmgr_destroy;
263bf215546Sopenharmony_ci   mm->base.create_buffer = mm_bufmgr_create_buffer;
264bf215546Sopenharmony_ci   mm->base.flush = mm_bufmgr_flush;
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   mm->size = size;
267bf215546Sopenharmony_ci   mm->align2 = align2; /* 64-byte alignment */
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   (void) mtx_init(&mm->mutex, mtx_plain);
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   mm->buffer = buffer;
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   mm->map = pb_map(mm->buffer,
274bf215546Sopenharmony_ci		    PB_USAGE_CPU_READ |
275bf215546Sopenharmony_ci		    PB_USAGE_CPU_WRITE, NULL);
276bf215546Sopenharmony_ci   if(!mm->map)
277bf215546Sopenharmony_ci      goto failure;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   mm->heap = u_mmInit(0, (int)size);
280bf215546Sopenharmony_ci   if (!mm->heap)
281bf215546Sopenharmony_ci      goto failure;
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   return SUPER(mm);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_cifailure:
286bf215546Sopenharmony_ci   if(mm->heap)
287bf215546Sopenharmony_ci      u_mmDestroy(mm->heap);
288bf215546Sopenharmony_ci   if(mm->map)
289bf215546Sopenharmony_ci      pb_unmap(mm->buffer);
290bf215546Sopenharmony_ci   FREE(mm);
291bf215546Sopenharmony_ci   return NULL;
292bf215546Sopenharmony_ci}
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_cistruct pb_manager *
296bf215546Sopenharmony_cimm_bufmgr_create(struct pb_manager *provider,
297bf215546Sopenharmony_ci                 pb_size size, pb_size align2)
298bf215546Sopenharmony_ci{
299bf215546Sopenharmony_ci   struct pb_buffer *buffer;
300bf215546Sopenharmony_ci   struct pb_manager *mgr;
301bf215546Sopenharmony_ci   struct pb_desc desc;
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   if (!provider)
304bf215546Sopenharmony_ci      return NULL;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   memset(&desc, 0, sizeof(desc));
307bf215546Sopenharmony_ci   desc.alignment = 1 << align2;
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   buffer = provider->create_buffer(provider, size, &desc);
310bf215546Sopenharmony_ci   if (!buffer)
311bf215546Sopenharmony_ci      return NULL;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   mgr = mm_bufmgr_create_from_buffer(buffer, size, align2);
314bf215546Sopenharmony_ci   if (!mgr) {
315bf215546Sopenharmony_ci      pb_reference(&buffer, NULL);
316bf215546Sopenharmony_ci      return NULL;
317bf215546Sopenharmony_ci   }
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci  return mgr;
320bf215546Sopenharmony_ci}
321