gallium: Reusable pipe buffer library.
This is an optional library that winsys drivers can use to simplify memory management, and help meet the winsys interface requirements.
This commit is contained in:
parent
708582f6d5
commit
b478362251
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
TOP = ../../..
|
TOP = ../../..
|
||||||
include $(TOP)/configs/current
|
include $(TOP)/configs/current
|
||||||
|
|
||||||
|
@ -7,7 +6,7 @@ ifeq ($(CONFIG_NAME), linux-cell)
|
||||||
CELL_DIR = cell
|
CELL_DIR = cell
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUBDIRS = softpipe i915simple failover $(CELL_DIR)
|
SUBDIRS = softpipe i915simple failover pipebuffer $(CELL_DIR)
|
||||||
|
|
||||||
|
|
||||||
default: subdirs
|
default: subdirs
|
||||||
|
@ -22,4 +21,4 @@ subdirs:
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f `find . -name \*.[oa]`
|
rm -f `find . -name \*.[oa]`
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
TOP = ../../../..
|
||||||
|
include $(TOP)/configs/current
|
||||||
|
|
||||||
|
LIBNAME = pipebuffer
|
||||||
|
|
||||||
|
|
||||||
|
DRIVER_SOURCES = \
|
||||||
|
pb_buffer.c \
|
||||||
|
pb_buffer_client.c \
|
||||||
|
pb_buffer_handle.c \
|
||||||
|
pb_buffer_fenced.c \
|
||||||
|
pb_buffer_malloc.c \
|
||||||
|
pb_buffer_null.c \
|
||||||
|
pb_bufmgr_fenced.c \
|
||||||
|
pb_bufmgr_mm.c \
|
||||||
|
pb_bufmgr_pool.c
|
||||||
|
|
||||||
|
C_SOURCES = \
|
||||||
|
$(DRIVER_SOURCES)
|
||||||
|
|
||||||
|
ASM_SOURCES =
|
||||||
|
|
||||||
|
include ../Makefile.template
|
||||||
|
|
||||||
|
symlinks:
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* List macros heavily inspired by the Linux kernel
|
||||||
|
* list handling. No list looping yet.
|
||||||
|
*
|
||||||
|
* Is not threadsafe, so common operations need to
|
||||||
|
* be protected using an external mutex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LINKED_LIST_H_
|
||||||
|
#define LINKED_LIST_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct list_head
|
||||||
|
{
|
||||||
|
struct list_head *prev;
|
||||||
|
struct list_head *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define LIST_INITHEAD(__item) \
|
||||||
|
do { \
|
||||||
|
(__item)->prev = (__item); \
|
||||||
|
(__item)->next = (__item); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LIST_ADD(__item, __list) \
|
||||||
|
do { \
|
||||||
|
(__item)->prev = (__list); \
|
||||||
|
(__item)->next = (__list)->next; \
|
||||||
|
(__list)->next->prev = (__item); \
|
||||||
|
(__list)->next = (__item); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LIST_ADDTAIL(__item, __list) \
|
||||||
|
do { \
|
||||||
|
(__item)->next = (__list); \
|
||||||
|
(__item)->prev = (__list)->prev; \
|
||||||
|
(__list)->prev->next = (__item); \
|
||||||
|
(__list)->prev = (__item); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define LIST_DEL(__item) \
|
||||||
|
do { \
|
||||||
|
(__item)->prev->next = (__item)->next; \
|
||||||
|
(__item)->next->prev = (__item)->prev; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define LIST_DELINIT(__item) \
|
||||||
|
do { \
|
||||||
|
(__item)->prev->next = (__item)->next; \
|
||||||
|
(__item)->next->prev = (__item)->prev; \
|
||||||
|
(__item)->next = (__item); \
|
||||||
|
(__item)->prev = (__item); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define LIST_ENTRY(__type, __item, __field) \
|
||||||
|
((__type *)(((char *)(__item)) - offsetof(__type, __field)))
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LINKED_LIST_H_*/
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Buffer implementation.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_reference(struct pipe_buffer **dst,
|
||||||
|
struct pipe_buffer *src)
|
||||||
|
{
|
||||||
|
if(*dst != src) {
|
||||||
|
if (src)
|
||||||
|
src->vtbl->reference(src);
|
||||||
|
|
||||||
|
if (*dst)
|
||||||
|
(*dst)->vtbl->release(*dst);
|
||||||
|
|
||||||
|
*dst = src;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Generic code for buffers.
|
||||||
|
*
|
||||||
|
* Behind a pipe buffle handle there can be DMA buffers, client (or user)
|
||||||
|
* buffers, regular malloced buffers, etc. This file provides an abstract base
|
||||||
|
* buffer handle that allows the driver to cope with all those kinds of buffers
|
||||||
|
* in a more flexible way.
|
||||||
|
*
|
||||||
|
* There is no obligation of a winsys driver to use this library. And a pipe
|
||||||
|
* driver should be completly agnostic about it.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PB_BUFFER_H_
|
||||||
|
#define PB_BUFFER_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_buffer_vtbl;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all pipe buffers.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Pointer to the virtual function table.
|
||||||
|
*
|
||||||
|
* Avoid accessing this table directly. Use the inline functions below
|
||||||
|
* instead to avoid mistakes.
|
||||||
|
*/
|
||||||
|
const struct pipe_buffer_vtbl *vtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual function table for the buffer storage operations.
|
||||||
|
*
|
||||||
|
* Note that creation is not done through this table.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer_vtbl
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add a reference to the buffer.
|
||||||
|
*
|
||||||
|
* This method can be a no-op for buffers that don't need reference
|
||||||
|
* counting.
|
||||||
|
*/
|
||||||
|
void (*reference)( struct pipe_buffer *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a reference to this buffer and destroy it.
|
||||||
|
*/
|
||||||
|
void (*release)( struct pipe_buffer *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the entire data store of a buffer object into the client's address.
|
||||||
|
* flags is bitmask of PIPE_BUFFER_FLAG_READ/WRITE.
|
||||||
|
*/
|
||||||
|
void *(*map)( struct pipe_buffer *buf,
|
||||||
|
unsigned flags );
|
||||||
|
|
||||||
|
void (*unmap)( struct pipe_buffer *buf );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the base buffer and the offset.
|
||||||
|
*
|
||||||
|
* A buffer can be subdivided in smaller buffers. This method should return
|
||||||
|
* the underlaying buffer, and the relative offset.
|
||||||
|
*
|
||||||
|
* Buffers without an underlaying base buffer should return themselves, with
|
||||||
|
* a zero offset.
|
||||||
|
*
|
||||||
|
* Note that this will increase the reference count of the base buffer.
|
||||||
|
*/
|
||||||
|
void (*get_base_buffer)( struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** *dst = src with reference counting */
|
||||||
|
void
|
||||||
|
buffer_reference(struct pipe_buffer **dst,
|
||||||
|
struct pipe_buffer *src);
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
buf->vtbl->release(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
buffer_map(struct pipe_buffer *buf,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
return buf->vtbl->map(buf, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
buf->vtbl->unmap(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
buffer_get_base_buffer( struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset )
|
||||||
|
{
|
||||||
|
buf->vtbl->get_base_buffer(buf, base_buf, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Placeholder for empty buffers. */
|
||||||
|
extern struct pipe_buffer null_buffer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client buffers (also designated as user buffers) are just for convenience
|
||||||
|
* of the state tracker, so that it can masquerade its own data as a buffer.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer *
|
||||||
|
client_buffer_create(void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Malloc-based buffer to store data that can't be used by the graphics
|
||||||
|
* hardware.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer *
|
||||||
|
malloc_buffer_create(unsigned size);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*PB_BUFFER_H_*/
|
|
@ -0,0 +1,123 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Implementation of client buffer (also designated as "user buffers"), which
|
||||||
|
* are just state-tracker owned data masqueraded as buffers.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct client_buffer
|
||||||
|
{
|
||||||
|
struct pipe_buffer base;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern const struct pipe_buffer_vtbl client_buffer_vtbl;
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct client_buffer *
|
||||||
|
client_buffer(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
assert(buf->vtbl == &client_buffer_vtbl);
|
||||||
|
return (struct client_buffer *)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_buffer_reference(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
client_buffer_map(struct pipe_buffer *buf,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
return client_buffer(buf)->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_buffer_get_base_buffer(struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset)
|
||||||
|
{
|
||||||
|
*base_buf = buf;
|
||||||
|
*offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct pipe_buffer_vtbl
|
||||||
|
client_buffer_vtbl = {
|
||||||
|
client_buffer_reference,
|
||||||
|
client_buffer_release,
|
||||||
|
client_buffer_map,
|
||||||
|
client_buffer_unmap,
|
||||||
|
client_buffer_get_base_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_buffer *
|
||||||
|
client_buffer_create(void *data)
|
||||||
|
{
|
||||||
|
struct client_buffer *buf;
|
||||||
|
|
||||||
|
buf = (struct client_buffer *)malloc(sizeof(struct client_buffer));
|
||||||
|
if(!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf->base.vtbl = &client_buffer_vtbl;
|
||||||
|
|
||||||
|
buf->data = data;
|
||||||
|
|
||||||
|
return &buf->base;
|
||||||
|
}
|
|
@ -0,0 +1,340 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Implementation of fenced buffers.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com>
|
||||||
|
* \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "main/imports.h"
|
||||||
|
#include "glapi/glthread.h"
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
#include "p_winsys.h"
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
#include "pb_buffer_fenced.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience macro (type safe).
|
||||||
|
*/
|
||||||
|
#define SUPER(__derived) (&(__derived)->base)
|
||||||
|
|
||||||
|
|
||||||
|
struct fenced_buffer_list
|
||||||
|
{
|
||||||
|
_glthread_Mutex mutex;
|
||||||
|
|
||||||
|
struct pipe_winsys *winsys;
|
||||||
|
|
||||||
|
size_t numDelayed;
|
||||||
|
size_t checkDelayed;
|
||||||
|
|
||||||
|
struct list_head delayed;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around a pipe buffer which adds fencing and reference counting.
|
||||||
|
*/
|
||||||
|
struct fenced_buffer
|
||||||
|
{
|
||||||
|
struct pipe_buffer base;
|
||||||
|
|
||||||
|
struct pipe_buffer *buffer;
|
||||||
|
|
||||||
|
unsigned refcount;
|
||||||
|
struct pipe_fence_handle *fence;
|
||||||
|
|
||||||
|
struct list_head head;
|
||||||
|
struct fenced_buffer_list *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct fenced_buffer *
|
||||||
|
fenced_buffer(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
assert(buf->vtbl == &fenced_buffer_vtbl);
|
||||||
|
return (struct fenced_buffer *)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_fenced_buffer_destroy(struct fenced_buffer *fenced_buf)
|
||||||
|
{
|
||||||
|
buffer_release(fenced_buf->buffer);
|
||||||
|
free(fenced_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
|
||||||
|
int wait)
|
||||||
|
{
|
||||||
|
struct pipe_winsys *winsys = fenced_list->winsys;
|
||||||
|
struct fenced_buffer *fenced_buf;
|
||||||
|
struct list_head *list, *prev;
|
||||||
|
int signaled = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
list = fenced_list->delayed.next;
|
||||||
|
|
||||||
|
if (fenced_list->numDelayed > 3) {
|
||||||
|
for (i = 0; i < fenced_list->numDelayed; i += 3) {
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = list->prev;
|
||||||
|
for (; list != &fenced_list->delayed; list = prev, prev = list->prev) {
|
||||||
|
|
||||||
|
fenced_buf = LIST_ENTRY(struct fenced_buffer, list, head);
|
||||||
|
|
||||||
|
if (signaled != 0) {
|
||||||
|
if (wait) {
|
||||||
|
signaled = winsys->fence_finish(winsys, fenced_buf->fence, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
signaled = winsys->fence_signalled(winsys, fenced_buf->fence, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signaled != 0)
|
||||||
|
/* XXX: we are assuming that buffers are freed in the same order they
|
||||||
|
* are fenced which may not always be true...
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
winsys->fence_reference(winsys, &fenced_buf->fence, NULL);
|
||||||
|
|
||||||
|
LIST_DEL(list);
|
||||||
|
fenced_list->numDelayed--;
|
||||||
|
|
||||||
|
_fenced_buffer_destroy(fenced_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fenced_buffer_reference(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
struct fenced_buffer_list *fenced_list = fenced_buf->list;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(fenced_list->mutex);
|
||||||
|
fenced_buf->refcount++;
|
||||||
|
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fenced_buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
struct fenced_buffer_list *fenced_list = fenced_buf->list;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(fenced_list->mutex);
|
||||||
|
|
||||||
|
fenced_buf->refcount--;
|
||||||
|
if(!fenced_buf->refcount) {
|
||||||
|
if (fenced_buf->fence) {
|
||||||
|
LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed);
|
||||||
|
fenced_list->numDelayed++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_fenced_buffer_destroy(fenced_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fenced_list->numDelayed % fenced_list->checkDelayed) == 0)
|
||||||
|
_fenced_buffer_list_check_free(fenced_list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
fenced_buffer_map(struct pipe_buffer *buf,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
return buffer_map(fenced_buf->buffer, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fenced_buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
buffer_unmap(fenced_buf->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fenced_buffer_get_base_buffer(struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset)
|
||||||
|
{
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
buffer_get_base_buffer(fenced_buf->buffer, base_buf, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct pipe_buffer_vtbl
|
||||||
|
fenced_buffer_vtbl = {
|
||||||
|
fenced_buffer_reference,
|
||||||
|
fenced_buffer_release,
|
||||||
|
fenced_buffer_map,
|
||||||
|
fenced_buffer_unmap,
|
||||||
|
fenced_buffer_get_base_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_buffer *
|
||||||
|
fenced_buffer_create(struct fenced_buffer_list *fenced_list,
|
||||||
|
struct pipe_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct fenced_buffer *buf;
|
||||||
|
|
||||||
|
buf = (struct fenced_buffer *)calloc(1, sizeof(struct fenced_buffer));
|
||||||
|
if(!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf->base.vtbl = &fenced_buffer_vtbl;
|
||||||
|
buf->buffer = buffer;
|
||||||
|
buf->refcount = 1;
|
||||||
|
buf->list = fenced_list;
|
||||||
|
|
||||||
|
return &buf->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_fence(struct pipe_buffer *buf,
|
||||||
|
struct pipe_fence_handle *fence)
|
||||||
|
{
|
||||||
|
if(buf->vtbl == &fenced_buffer_vtbl) {
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
struct fenced_buffer_list *fenced_list = fenced_buf->list;
|
||||||
|
struct pipe_winsys *winsys = fenced_list->winsys;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(fenced_list->mutex);
|
||||||
|
winsys->fence_reference(winsys, &fenced_buf->fence, fence);
|
||||||
|
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_unfence(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
buffer_fence(buf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
buffer_finish(struct pipe_buffer *buf,
|
||||||
|
unsigned flag)
|
||||||
|
{
|
||||||
|
if(buf->vtbl == &fenced_buffer_vtbl) {
|
||||||
|
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
|
||||||
|
if(fenced_buf->fence) {
|
||||||
|
struct fenced_buffer_list *fenced_list = fenced_buf->list;
|
||||||
|
struct pipe_winsys *winsys = fenced_list->winsys;
|
||||||
|
return winsys->fence_finish(winsys, fenced_buf->fence, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct fenced_buffer_list *
|
||||||
|
fenced_buffer_list_create(struct pipe_winsys *winsys)
|
||||||
|
{
|
||||||
|
struct fenced_buffer_list *fenced_list;
|
||||||
|
|
||||||
|
fenced_list = (struct fenced_buffer_list *)calloc(1, sizeof(*fenced_list));
|
||||||
|
if (!fenced_list)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fenced_list->winsys = winsys;
|
||||||
|
|
||||||
|
LIST_INITHEAD(&fenced_list->delayed);
|
||||||
|
|
||||||
|
fenced_list->numDelayed = 0;
|
||||||
|
|
||||||
|
/* TODO: don't hard code this */
|
||||||
|
fenced_list->checkDelayed = 5;
|
||||||
|
|
||||||
|
_glthread_INIT_MUTEX(fenced_list->mutex);
|
||||||
|
|
||||||
|
return fenced_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
|
||||||
|
int wait)
|
||||||
|
{
|
||||||
|
_glthread_LOCK_MUTEX(fenced_list->mutex);
|
||||||
|
_fenced_buffer_list_check_free(fenced_list, wait);
|
||||||
|
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list)
|
||||||
|
{
|
||||||
|
_glthread_LOCK_MUTEX(fenced_list->mutex);
|
||||||
|
|
||||||
|
/* Wait on outstanding fences */
|
||||||
|
while (fenced_list->numDelayed) {
|
||||||
|
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
|
||||||
|
sched_yield();
|
||||||
|
_fenced_buffer_list_check_free(fenced_list, GL_TRUE);
|
||||||
|
_glthread_LOCK_MUTEX(fenced_list->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
|
||||||
|
|
||||||
|
free(fenced_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Buffer fencing.
|
||||||
|
*
|
||||||
|
* "Fenced buffers" is actually a misnomer. They should be referred as
|
||||||
|
* "fenceable buffers", i.e, buffers that can be fenced, but I couldn't find
|
||||||
|
* the word "fenceable" in the dictionary.
|
||||||
|
*
|
||||||
|
* A "fenced buffer" is a decorator around a normal buffer, which adds two
|
||||||
|
* special properties:
|
||||||
|
* - the ability for the destruction to be delayed by a fence;
|
||||||
|
* - reference counting.
|
||||||
|
*
|
||||||
|
* Usually DMA buffers have a life-time that will extend the life-time of its
|
||||||
|
* handle. The end-of-life is dictated by the fence signalling.
|
||||||
|
*
|
||||||
|
* Between the handle's destruction, and the fence signalling, the buffer is
|
||||||
|
* stored in a fenced buffer list.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PB_BUFFER_FENCED_H_
|
||||||
|
#define PB_BUFFER_FENCED_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_winsys;
|
||||||
|
struct pipe_buffer;
|
||||||
|
struct pipe_fence_handle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of buffers which are awaiting fence signalling.
|
||||||
|
*/
|
||||||
|
struct fenced_buffer_list;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fenced buffer's virtual function table.
|
||||||
|
*
|
||||||
|
* NOTE: Made public for debugging purposes.
|
||||||
|
*/
|
||||||
|
extern const struct pipe_buffer_vtbl fenced_buffer_vtbl;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a fenced buffer list.
|
||||||
|
*
|
||||||
|
* See also fenced_bufmgr_create for a more convenient way to use this.
|
||||||
|
*/
|
||||||
|
struct fenced_buffer_list *
|
||||||
|
fenced_buffer_list_create(struct pipe_winsys *winsys);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walk the fenced buffer list to check and free signalled buffers.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
|
||||||
|
int wait);
|
||||||
|
|
||||||
|
void
|
||||||
|
fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a buffer in a fenced buffer.
|
||||||
|
*
|
||||||
|
* NOTE: this will not increase the buffer reference count.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer *
|
||||||
|
fenced_buffer_create(struct fenced_buffer_list *fenced,
|
||||||
|
struct pipe_buffer *buffer);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a buffer's fence.
|
||||||
|
*
|
||||||
|
* NOTE: Although it takes a generic pipe buffer argument, it will fail
|
||||||
|
* on everything but buffers returned by fenced_buffer_create.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
buffer_fence(struct pipe_buffer *buf,
|
||||||
|
struct pipe_fence_handle *fence);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the buffer's fence.
|
||||||
|
*
|
||||||
|
* NOTE: Although it takes a generic pipe buffer argument, it will fail
|
||||||
|
* on everything but buffers returned by fenced_buffer_create.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
buffer_unfence(struct pipe_buffer *buf);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the buffer fence to signal.
|
||||||
|
*
|
||||||
|
* See also pipe_winsys::fence_finish().
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
buffer_finish(struct pipe_buffer *buf,
|
||||||
|
unsigned flag);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*PB_BUFFER_FENCED_H_*/
|
|
@ -0,0 +1,182 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Drop-in implementation of the winsys driver functions for buffer handles.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "pipe/p_winsys.h"
|
||||||
|
#include "pipe/p_defines.h"
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
#include "pb_buffer_handle.h"
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_buffer_handle *
|
||||||
|
buffer_handle_create(struct pipe_winsys *winsys,
|
||||||
|
unsigned alignment,
|
||||||
|
unsigned flags,
|
||||||
|
unsigned hint)
|
||||||
|
{
|
||||||
|
struct pipe_buffer_handle *handle;
|
||||||
|
|
||||||
|
handle = (struct pipe_buffer_handle *)malloc(sizeof(struct pipe_buffer_handle));
|
||||||
|
if(!handle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
handle->refcount = 1;
|
||||||
|
handle->alignment = alignment;
|
||||||
|
handle->flags = flags;
|
||||||
|
handle->hint = hint;
|
||||||
|
|
||||||
|
handle->buf = &null_buffer;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_buffer_handle *
|
||||||
|
buffer_handle_create_user(struct pipe_winsys *winsys,
|
||||||
|
void *data, unsigned size)
|
||||||
|
{
|
||||||
|
struct pipe_buffer_handle *handle;
|
||||||
|
struct pipe_buffer *buf;
|
||||||
|
|
||||||
|
handle = buffer_handle_create(winsys, 1, 0, 0);
|
||||||
|
if(!handle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf = client_buffer_create(data);
|
||||||
|
if(!buf) {
|
||||||
|
free(handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_handle_data(handle, buf);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
buffer_handle_map(struct pipe_winsys *winsys,
|
||||||
|
struct pipe_buffer_handle *handle,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
return buffer_map(handle->buf, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_handle_unmap(struct pipe_winsys *winsys,
|
||||||
|
struct pipe_buffer_handle *handle)
|
||||||
|
{
|
||||||
|
buffer_unmap(handle->buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_handle_reference(struct pipe_winsys *winsys,
|
||||||
|
struct pipe_buffer_handle **dst,
|
||||||
|
struct pipe_buffer_handle *src)
|
||||||
|
{
|
||||||
|
/* XXX: should this be thread safe? */
|
||||||
|
|
||||||
|
if (src) {
|
||||||
|
src->refcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*dst) {
|
||||||
|
(*dst)->refcount--;
|
||||||
|
if ((*dst)->refcount == 0) {
|
||||||
|
buffer_release((*dst)->buf);
|
||||||
|
free(*dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
buffer_handle_subdata(struct pipe_winsys *winsys,
|
||||||
|
struct pipe_buffer_handle *handle,
|
||||||
|
unsigned long offset,
|
||||||
|
unsigned long size,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
void *map;
|
||||||
|
assert(handle);
|
||||||
|
assert(data);
|
||||||
|
map = buffer_handle_map(winsys, handle, PIPE_BUFFER_FLAG_WRITE);
|
||||||
|
if(map) {
|
||||||
|
memcpy((char *)map + offset, data, size);
|
||||||
|
buffer_handle_unmap(winsys, handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
buffer_handle_get_subdata(struct pipe_winsys *winsys,
|
||||||
|
struct pipe_buffer_handle *handle,
|
||||||
|
unsigned long offset,
|
||||||
|
unsigned long size,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
void *map;
|
||||||
|
assert(handle);
|
||||||
|
assert(data);
|
||||||
|
map = buffer_handle_map(winsys, handle, PIPE_BUFFER_FLAG_READ);
|
||||||
|
if(map) {
|
||||||
|
memcpy(data, (char *)map + offset, size);
|
||||||
|
buffer_handle_unmap(winsys, handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_handle_init_winsys(struct pipe_winsys *winsys)
|
||||||
|
{
|
||||||
|
winsys->buffer_create = buffer_handle_create;
|
||||||
|
winsys->user_buffer_create = buffer_handle_create_user;
|
||||||
|
winsys->buffer_map = buffer_handle_map;
|
||||||
|
winsys->buffer_unmap = buffer_handle_unmap;
|
||||||
|
winsys->buffer_reference = buffer_handle_reference;
|
||||||
|
winsys->buffer_subdata = buffer_handle_subdata;
|
||||||
|
winsys->buffer_get_subdata = buffer_handle_get_subdata;
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Buffer handle interface.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PB_BUFFER_HANDLE_H_
|
||||||
|
#define PB_BUFFER_HANDLE_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer handle.
|
||||||
|
*
|
||||||
|
* The buffer handle and the buffer data storage are separate entities. This
|
||||||
|
* is modelled after ARB_vertex_buffer_object, which is the interface that
|
||||||
|
* Gallium requires. See p_winsys.h for more information.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer_handle
|
||||||
|
{
|
||||||
|
/** Reference count */
|
||||||
|
unsigned refcount;
|
||||||
|
|
||||||
|
/** Allocation characteristics */
|
||||||
|
unsigned alignment;
|
||||||
|
unsigned flags;
|
||||||
|
unsigned hint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual buffer.
|
||||||
|
*
|
||||||
|
* It should never be NULL. Use null_buffer instead.
|
||||||
|
*/
|
||||||
|
struct pipe_buffer *buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set buffer storage.
|
||||||
|
*
|
||||||
|
* NOTE: this will not increase the buffer reference count.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
buffer_handle_data(struct pipe_buffer_handle *handle,
|
||||||
|
struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(handle);
|
||||||
|
assert(handle->buf);
|
||||||
|
buffer_release(handle->buf);
|
||||||
|
assert(buf);
|
||||||
|
handle->buf = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
buffer_handle_clear(struct pipe_buffer_handle *handle)
|
||||||
|
{
|
||||||
|
buffer_handle_data(handle, &null_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
buffer_handle_has_data(struct pipe_buffer_handle *handle) {
|
||||||
|
assert(handle);
|
||||||
|
assert(handle->buf);
|
||||||
|
return handle->buf != &null_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in the pipe_winsys' buffer-related callbacks.
|
||||||
|
*
|
||||||
|
* Specifically, the fullfilled functions are:
|
||||||
|
* - buffer_create
|
||||||
|
* - user_buffer_create
|
||||||
|
* - buffer_map
|
||||||
|
* - buffer_unmap
|
||||||
|
* - buffer_reference
|
||||||
|
* - buffer_subdata
|
||||||
|
* - buffer_get_subdata
|
||||||
|
*
|
||||||
|
* NOTE: buffer_data is left untouched.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
buffer_handle_init_winsys(struct pipe_winsys *winsys);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*PB_BUFFER_HANDLE_H_*/
|
|
@ -0,0 +1,132 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Implementation of malloc-based buffers to store data that can't be processed
|
||||||
|
* by the hardware.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct malloc_buffer
|
||||||
|
{
|
||||||
|
struct pipe_buffer base;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern const struct pipe_buffer_vtbl malloc_buffer_vtbl;
|
||||||
|
|
||||||
|
static inline struct malloc_buffer *
|
||||||
|
malloc_buffer(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
assert(buf->vtbl == &malloc_buffer_vtbl);
|
||||||
|
return (struct malloc_buffer *)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
malloc_buffer_reference(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* no-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
malloc_buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
free(malloc_buffer(buf)->data);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
malloc_buffer_map(struct pipe_buffer *buf,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
return malloc_buffer(buf)->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
malloc_buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
malloc_buffer_get_base_buffer(struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset)
|
||||||
|
{
|
||||||
|
*base_buf = buf;
|
||||||
|
*offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct pipe_buffer_vtbl
|
||||||
|
malloc_buffer_vtbl = {
|
||||||
|
malloc_buffer_reference,
|
||||||
|
malloc_buffer_release,
|
||||||
|
malloc_buffer_map,
|
||||||
|
malloc_buffer_unmap,
|
||||||
|
malloc_buffer_get_base_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_buffer *
|
||||||
|
malloc_buffer_create(unsigned size)
|
||||||
|
{
|
||||||
|
struct malloc_buffer *buf;
|
||||||
|
|
||||||
|
/* TODO: accept an alignment parameter */
|
||||||
|
/* TODO: do a single allocation */
|
||||||
|
|
||||||
|
buf = (struct malloc_buffer *)malloc(sizeof(struct malloc_buffer));
|
||||||
|
if(!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf->base.vtbl = &malloc_buffer_vtbl;
|
||||||
|
|
||||||
|
buf->data = malloc(size);
|
||||||
|
if(!buf->data) {
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &buf->base;
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Null buffer implementation.
|
||||||
|
*
|
||||||
|
* We have a special null buffer object so that we can safely call buffer
|
||||||
|
* operations without having to check whether the buffer pointer is null or not.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "pipe/p_winsys.h"
|
||||||
|
#include "pipe/p_defines.h"
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
null_buffer_reference(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
null_buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
null_buffer_map(struct pipe_buffer *buf,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
null_buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
null_buffer_get_base_buffer(struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset)
|
||||||
|
{
|
||||||
|
*base_buf = buf;
|
||||||
|
*offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct pipe_buffer_vtbl
|
||||||
|
pipe_buffer_vtbl = {
|
||||||
|
null_buffer_reference,
|
||||||
|
null_buffer_release,
|
||||||
|
null_buffer_map,
|
||||||
|
null_buffer_unmap,
|
||||||
|
null_buffer_get_base_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_buffer
|
||||||
|
null_buffer = {
|
||||||
|
&pipe_buffer_vtbl
|
||||||
|
};
|
|
@ -0,0 +1,114 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Buffer management.
|
||||||
|
*
|
||||||
|
* A buffer manager does only one basic thing: it creates buffers. Actually,
|
||||||
|
* "buffer factory" would probably a more accurate description.
|
||||||
|
*
|
||||||
|
* You can chain buffer managers so that you can have a finer grained memory
|
||||||
|
* management and pooling.
|
||||||
|
*
|
||||||
|
* For example, for a simple batch buffer manager you would chain:
|
||||||
|
* - the native buffer manager, which provides DMA memory from the graphics
|
||||||
|
* memory space;
|
||||||
|
* - the pool buffer manager, which keep around a pool of equally sized buffers
|
||||||
|
* to avoid latency associated with the native buffer manager;
|
||||||
|
* - the fenced buffer manager, which will delay buffer destruction until the
|
||||||
|
* the moment the card finishing processing it.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PB_BUFMGR_H_
|
||||||
|
#define PB_BUFMGR_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct pipe_buffer;
|
||||||
|
struct pipe_winsys;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base class for all buffer managers.
|
||||||
|
*/
|
||||||
|
struct buffer_manager
|
||||||
|
{
|
||||||
|
/* XXX: we will likely need more allocation flags */
|
||||||
|
struct pipe_buffer *
|
||||||
|
(*create_buffer)( struct buffer_manager *mgr,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
void
|
||||||
|
(*destroy)( struct buffer_manager *mgr );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static buffer pool manager.
|
||||||
|
*
|
||||||
|
* Manages the allocation of equally sized buffers. It does so by allocating
|
||||||
|
* a single big buffer and divide it equally sized buffers.
|
||||||
|
*
|
||||||
|
* It is meant to manage the allocation of batch buffer pools.
|
||||||
|
*/
|
||||||
|
struct buffer_manager *
|
||||||
|
pool_bufmgr_create(struct buffer_manager *provider,
|
||||||
|
size_t n, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraper around the old memory manager.
|
||||||
|
*
|
||||||
|
* It managers buffers of different sizes. It does so by allocating a buffer
|
||||||
|
* with the size of the heap, and then using the old mm memory manager to manage
|
||||||
|
* that heap.
|
||||||
|
*/
|
||||||
|
struct buffer_manager *
|
||||||
|
mm_bufmgr_create(struct buffer_manager *provider,
|
||||||
|
size_t size, size_t align2);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fenced buffer manager.
|
||||||
|
*
|
||||||
|
* This manager is just meant for convenience. It wraps the buffers returned
|
||||||
|
* by another manager in fenced buffers, so that
|
||||||
|
*
|
||||||
|
* NOTE: the buffer manager that provides the buffers will be destroyed
|
||||||
|
* at the same time.
|
||||||
|
*/
|
||||||
|
struct buffer_manager *
|
||||||
|
fenced_bufmgr_create(struct buffer_manager *provider,
|
||||||
|
struct pipe_winsys *winsys);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*PB_BUFMGR_H_*/
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* A buffer manager that wraps buffers in fenced buffers.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.dot.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
#include "pb_buffer_fenced.h"
|
||||||
|
#include "pb_bufmgr.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct fenced_buffer_manager
|
||||||
|
{
|
||||||
|
struct buffer_manager base;
|
||||||
|
|
||||||
|
struct buffer_manager *provider;
|
||||||
|
|
||||||
|
struct fenced_buffer_list *fenced_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct fenced_buffer_manager *
|
||||||
|
fenced_buffer_manager(struct buffer_manager *mgr)
|
||||||
|
{
|
||||||
|
assert(mgr);
|
||||||
|
return (struct fenced_buffer_manager *)mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_buffer *
|
||||||
|
fenced_bufmgr_create_buffer(struct buffer_manager *mgr, size_t size)
|
||||||
|
{
|
||||||
|
struct fenced_buffer_manager *fenced_mgr = fenced_buffer_manager(mgr);
|
||||||
|
struct pipe_buffer *buf;
|
||||||
|
struct pipe_buffer *fenced_buf;
|
||||||
|
|
||||||
|
/* check for free buffers before allocating new ones */
|
||||||
|
fenced_buffer_list_check_free(fenced_mgr->fenced_list, 0);
|
||||||
|
|
||||||
|
buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size);
|
||||||
|
if(!buf) {
|
||||||
|
/* try harder to get a buffer */
|
||||||
|
fenced_buffer_list_check_free(fenced_mgr->fenced_list, 1);
|
||||||
|
|
||||||
|
buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size);
|
||||||
|
if(!buf) {
|
||||||
|
/* give up */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fenced_buf = fenced_buffer_create(fenced_mgr->fenced_list, buf);
|
||||||
|
if(!fenced_buf) {
|
||||||
|
buffer_release(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fenced_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fenced_bufmgr_destroy(struct buffer_manager *mgr)
|
||||||
|
{
|
||||||
|
struct fenced_buffer_manager *fenced_mgr = fenced_buffer_manager(mgr);
|
||||||
|
|
||||||
|
fenced_buffer_list_destroy(fenced_mgr->fenced_list);
|
||||||
|
|
||||||
|
fenced_mgr->provider->destroy(fenced_mgr->provider);
|
||||||
|
|
||||||
|
free(fenced_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct buffer_manager *
|
||||||
|
fenced_bufmgr_create(struct buffer_manager *provider,
|
||||||
|
struct pipe_winsys *winsys)
|
||||||
|
{
|
||||||
|
struct fenced_buffer_manager *fenced_mgr;
|
||||||
|
|
||||||
|
fenced_mgr = (struct fenced_buffer_manager *)calloc(1, sizeof(*fenced_mgr));
|
||||||
|
if (!fenced_mgr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fenced_mgr->base.destroy = fenced_bufmgr_destroy;
|
||||||
|
fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer;
|
||||||
|
|
||||||
|
fenced_mgr->provider = provider;
|
||||||
|
fenced_mgr->fenced_list = fenced_buffer_list_create(winsys);
|
||||||
|
if(!fenced_mgr->fenced_list) {
|
||||||
|
free(fenced_mgr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &fenced_mgr->base;
|
||||||
|
}
|
|
@ -0,0 +1,265 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Buffer manager using the old texture memory manager.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca@tungstengraphics.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "main/imports.h"
|
||||||
|
#include "glapi/glthread.h"
|
||||||
|
#include "main/mm.h"
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
#include "p_defines.h"
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
#include "pb_bufmgr.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience macro (type safe).
|
||||||
|
*/
|
||||||
|
#define SUPER(__derived) (&(__derived)->base)
|
||||||
|
|
||||||
|
|
||||||
|
struct mm_buffer_manager
|
||||||
|
{
|
||||||
|
struct buffer_manager base;
|
||||||
|
|
||||||
|
_glthread_Mutex mutex;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
struct mem_block *heap;
|
||||||
|
|
||||||
|
size_t align2;
|
||||||
|
|
||||||
|
struct pipe_buffer *buffer;
|
||||||
|
void *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct mm_buffer_manager *
|
||||||
|
mm_buffer_manager(struct buffer_manager *mgr)
|
||||||
|
{
|
||||||
|
assert(mgr);
|
||||||
|
return (struct mm_buffer_manager *)mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct mm_buffer
|
||||||
|
{
|
||||||
|
struct pipe_buffer base;
|
||||||
|
|
||||||
|
struct mm_buffer_manager *mgr;
|
||||||
|
|
||||||
|
struct mem_block *block;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct mm_buffer *
|
||||||
|
mm_buffer(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
return (struct mm_buffer *)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
mm_buffer_reference(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
mm_buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
struct mm_buffer *mm_buf = mm_buffer(buf);
|
||||||
|
struct mm_buffer_manager *mm = mm_buf->mgr;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(mm->mutex);
|
||||||
|
mmFreeMem(mm_buf->block);
|
||||||
|
free(buf);
|
||||||
|
_glthread_UNLOCK_MUTEX(mm->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
mm_buffer_map(struct pipe_buffer *buf,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
struct mm_buffer *mm_buf = mm_buffer(buf);
|
||||||
|
struct mm_buffer_manager *mm = mm_buf->mgr;
|
||||||
|
|
||||||
|
return (unsigned char *) mm->map + mm_buf->block->ofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
mm_buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
mm_buffer_get_base_buffer(struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset)
|
||||||
|
{
|
||||||
|
struct mm_buffer *mm_buf = mm_buffer(buf);
|
||||||
|
struct mm_buffer_manager *mm = mm_buf->mgr;
|
||||||
|
buffer_get_base_buffer(mm->buffer, base_buf, offset);
|
||||||
|
*offset += mm_buf->block->ofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct pipe_buffer_vtbl
|
||||||
|
mm_buffer_vtbl = {
|
||||||
|
mm_buffer_reference,
|
||||||
|
mm_buffer_release,
|
||||||
|
mm_buffer_map,
|
||||||
|
mm_buffer_unmap,
|
||||||
|
mm_buffer_get_base_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_buffer *
|
||||||
|
mm_bufmgr_create_buffer(struct buffer_manager *mgr,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
struct mm_buffer_manager *mm = mm_buffer_manager(mgr);
|
||||||
|
struct mm_buffer *mm_buf;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(mm->mutex);
|
||||||
|
|
||||||
|
mm_buf = (struct mm_buffer *)malloc(sizeof(*mm_buf));
|
||||||
|
if (!mm_buf) {
|
||||||
|
_glthread_UNLOCK_MUTEX(mm->mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm_buf->base.vtbl = &mm_buffer_vtbl;
|
||||||
|
|
||||||
|
mm_buf->mgr = mm;
|
||||||
|
|
||||||
|
mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0);
|
||||||
|
if(!mm_buf->block) {
|
||||||
|
fprintf(stderr, "warning: heap full\n");
|
||||||
|
#if 0
|
||||||
|
mmDumpMemInfo(mm->heap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0);
|
||||||
|
if(!mm_buf->block) {
|
||||||
|
assert(0);
|
||||||
|
free(mm_buf);
|
||||||
|
_glthread_UNLOCK_MUTEX(mm->mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some sanity checks */
|
||||||
|
assert(0 <= mm_buf->block->ofs && mm_buf->block->ofs < mm->size);
|
||||||
|
assert(size <= mm_buf->block->size && mm_buf->block->ofs + mm_buf->block->size <= mm->size);
|
||||||
|
|
||||||
|
_glthread_UNLOCK_MUTEX(mm->mutex);
|
||||||
|
return SUPER(mm_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
mm_bufmgr_destroy(struct buffer_manager *mgr)
|
||||||
|
{
|
||||||
|
struct mm_buffer_manager *mm = mm_buffer_manager(mgr);
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(mm->mutex);
|
||||||
|
|
||||||
|
mmDestroy(mm->heap);
|
||||||
|
|
||||||
|
buffer_unmap(mm->buffer);
|
||||||
|
buffer_release(mm->buffer);
|
||||||
|
|
||||||
|
_glthread_UNLOCK_MUTEX(mm->mutex);
|
||||||
|
|
||||||
|
free(mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct buffer_manager *
|
||||||
|
mm_bufmgr_create(struct buffer_manager *provider,
|
||||||
|
size_t size, size_t align2)
|
||||||
|
{
|
||||||
|
struct mm_buffer_manager *mm;
|
||||||
|
|
||||||
|
mm = (struct mm_buffer_manager *)calloc(1, sizeof(*mm));
|
||||||
|
if (!mm)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
assert(provider);
|
||||||
|
assert(provider->create_buffer);
|
||||||
|
mm->base.create_buffer = mm_bufmgr_create_buffer;
|
||||||
|
mm->base.destroy = mm_bufmgr_destroy;
|
||||||
|
|
||||||
|
mm->size = size;
|
||||||
|
mm->align2 = align2; /* 64-byte alignment */
|
||||||
|
|
||||||
|
_glthread_INIT_MUTEX(mm->mutex);
|
||||||
|
|
||||||
|
mm->buffer = provider->create_buffer(provider, size);
|
||||||
|
if (!mm->buffer)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
mm->map = buffer_map(mm->buffer,
|
||||||
|
PIPE_BUFFER_FLAG_READ | PIPE_BUFFER_FLAG_WRITE );
|
||||||
|
if(!mm->map)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
mm->heap = mmInit(0, size);
|
||||||
|
if (!mm->heap)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
return SUPER(mm);
|
||||||
|
|
||||||
|
failure:
|
||||||
|
if(mm->heap)
|
||||||
|
mmDestroy(mm->heap);
|
||||||
|
if(mm->map)
|
||||||
|
buffer_unmap(mm->buffer);
|
||||||
|
if(mm->buffer)
|
||||||
|
buffer_release(mm->buffer);
|
||||||
|
if(mm)
|
||||||
|
free(mm);
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Batch buffer pool management.
|
||||||
|
*
|
||||||
|
* \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com>
|
||||||
|
* \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "main/imports.h"
|
||||||
|
#include "glapi/glthread.h"
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
#include "p_defines.h"
|
||||||
|
|
||||||
|
#include "pb_buffer.h"
|
||||||
|
#include "pb_bufmgr.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience macro (type safe).
|
||||||
|
*/
|
||||||
|
#define SUPER(__derived) (&(__derived)->base)
|
||||||
|
|
||||||
|
|
||||||
|
struct pool_buffer_manager
|
||||||
|
{
|
||||||
|
struct buffer_manager base;
|
||||||
|
|
||||||
|
_glthread_Mutex mutex;
|
||||||
|
|
||||||
|
size_t bufSize;
|
||||||
|
|
||||||
|
size_t numFree;
|
||||||
|
size_t numTot;
|
||||||
|
|
||||||
|
struct list_head free;
|
||||||
|
|
||||||
|
struct pipe_buffer *buffer;
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
struct pool_buffer *bufs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct pool_buffer_manager *
|
||||||
|
pool_buffer_manager(struct buffer_manager *mgr)
|
||||||
|
{
|
||||||
|
assert(mgr);
|
||||||
|
return (struct pool_buffer_manager *)mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct pool_buffer
|
||||||
|
{
|
||||||
|
struct pipe_buffer base;
|
||||||
|
|
||||||
|
struct pool_buffer_manager *mgr;
|
||||||
|
|
||||||
|
struct list_head head;
|
||||||
|
|
||||||
|
size_t start;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct pool_buffer *
|
||||||
|
pool_buffer(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
assert(buf);
|
||||||
|
return (struct pool_buffer *)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pool_buffer_reference(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pool_buffer_release(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
struct pool_buffer *pool_buf = pool_buffer(buf);
|
||||||
|
struct pool_buffer_manager *pool = pool_buf->mgr;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(pool->mutex);
|
||||||
|
LIST_ADD(&pool_buf->head, &pool->free);
|
||||||
|
pool->numFree++;
|
||||||
|
_glthread_UNLOCK_MUTEX(pool->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
pool_buffer_map(struct pipe_buffer *buf, unsigned flags)
|
||||||
|
{
|
||||||
|
struct pool_buffer *pool_buf = pool_buffer(buf);
|
||||||
|
struct pool_buffer_manager *pool = pool_buf->mgr;
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(pool->mutex);
|
||||||
|
map = (unsigned char *) pool->map + pool_buf->start;
|
||||||
|
_glthread_UNLOCK_MUTEX(pool->mutex);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pool_buffer_unmap(struct pipe_buffer *buf)
|
||||||
|
{
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pool_buffer_get_base_buffer(struct pipe_buffer *buf,
|
||||||
|
struct pipe_buffer **base_buf,
|
||||||
|
unsigned *offset)
|
||||||
|
{
|
||||||
|
struct pool_buffer *pool_buf = pool_buffer(buf);
|
||||||
|
struct pool_buffer_manager *pool = pool_buf->mgr;
|
||||||
|
buffer_get_base_buffer(pool->buffer, base_buf, offset);
|
||||||
|
*offset += pool_buf->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct pipe_buffer_vtbl
|
||||||
|
pool_buffer_vtbl = {
|
||||||
|
pool_buffer_reference,
|
||||||
|
pool_buffer_release,
|
||||||
|
pool_buffer_map,
|
||||||
|
pool_buffer_unmap,
|
||||||
|
pool_buffer_get_base_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct pipe_buffer *
|
||||||
|
pool_bufmgr_create_buffer(struct buffer_manager *mgr, size_t size)
|
||||||
|
{
|
||||||
|
struct pool_buffer_manager *pool = pool_buffer_manager(mgr);
|
||||||
|
struct pool_buffer *pool_buf;
|
||||||
|
struct list_head *item;
|
||||||
|
|
||||||
|
assert(size == pool->bufSize);
|
||||||
|
|
||||||
|
_glthread_LOCK_MUTEX(pool->mutex);
|
||||||
|
|
||||||
|
if (pool->numFree == 0) {
|
||||||
|
_glthread_UNLOCK_MUTEX(pool->mutex);
|
||||||
|
fprintf(stderr, "warning: out of fixed size buffer objects\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = pool->free.next;
|
||||||
|
|
||||||
|
if (item == &pool->free) {
|
||||||
|
_glthread_UNLOCK_MUTEX(pool->mutex);
|
||||||
|
fprintf(stderr, "error: fixed size buffer pool corruption\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_DEL(item);
|
||||||
|
--pool->numFree;
|
||||||
|
|
||||||
|
_glthread_UNLOCK_MUTEX(pool->mutex);
|
||||||
|
pool_buf = LIST_ENTRY(struct pool_buffer, item, head);
|
||||||
|
return SUPER(pool_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pool_bufmgr_destroy(struct buffer_manager *mgr)
|
||||||
|
{
|
||||||
|
struct pool_buffer_manager *pool = pool_buffer_manager(mgr);
|
||||||
|
_glthread_LOCK_MUTEX(pool->mutex);
|
||||||
|
|
||||||
|
free(pool->bufs);
|
||||||
|
|
||||||
|
buffer_unmap(pool->buffer);
|
||||||
|
buffer_release(pool->buffer);
|
||||||
|
|
||||||
|
_glthread_UNLOCK_MUTEX(pool->mutex);
|
||||||
|
|
||||||
|
free(mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct buffer_manager *
|
||||||
|
pool_bufmgr_create(struct buffer_manager *provider,
|
||||||
|
size_t numBufs,
|
||||||
|
size_t bufSize)
|
||||||
|
{
|
||||||
|
struct pool_buffer_manager *pool;
|
||||||
|
struct pool_buffer *pool_buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pool = (struct pool_buffer_manager *)calloc(1, sizeof(*pool));
|
||||||
|
if (!pool)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pool->base.destroy = pool_bufmgr_destroy;
|
||||||
|
pool->base.create_buffer = pool_bufmgr_create_buffer;
|
||||||
|
|
||||||
|
LIST_INITHEAD(&pool->free);
|
||||||
|
|
||||||
|
pool->numTot = numBufs;
|
||||||
|
pool->numFree = numBufs;
|
||||||
|
pool->bufSize = bufSize;
|
||||||
|
|
||||||
|
_glthread_INIT_MUTEX(pool->mutex);
|
||||||
|
|
||||||
|
pool->buffer = provider->create_buffer(provider, numBufs*bufSize);
|
||||||
|
if (!pool->buffer)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
pool->map = buffer_map(pool->buffer,
|
||||||
|
PIPE_BUFFER_FLAG_READ |
|
||||||
|
PIPE_BUFFER_FLAG_WRITE );
|
||||||
|
if(!pool->map)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
pool->bufs = (struct pool_buffer *) malloc(numBufs * sizeof(*pool->bufs));
|
||||||
|
if (!pool->bufs)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
pool_buf = pool->bufs;
|
||||||
|
for (i = 0; i < numBufs; ++i) {
|
||||||
|
pool_buf->base.vtbl = &pool_buffer_vtbl;
|
||||||
|
pool_buf->mgr = pool;
|
||||||
|
pool_buf->start = i * bufSize;
|
||||||
|
LIST_ADDTAIL(&pool_buf->head, &pool->free);
|
||||||
|
pool_buf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUPER(pool);
|
||||||
|
|
||||||
|
failure:
|
||||||
|
if(pool->bufs)
|
||||||
|
free(pool->bufs);
|
||||||
|
if(pool->map)
|
||||||
|
buffer_unmap(pool->buffer);
|
||||||
|
if(pool->buffer)
|
||||||
|
buffer_release(pool->buffer);
|
||||||
|
if(pool)
|
||||||
|
free(pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
Loading…
Reference in New Issue