14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg/** 294a49301eSmrg * \file 304a49301eSmrg * Generic code for buffers. 31361fc4cbSmaya * 32361fc4cbSmaya * Behind a pipe buffle handle there can be DMA buffers, client (or user) 33361fc4cbSmaya * buffers, regular malloced buffers, etc. This file provides an abstract base 34361fc4cbSmaya * buffer handle that allows the driver to cope with all those kinds of buffers 354a49301eSmrg * in a more flexible way. 36361fc4cbSmaya * 374a49301eSmrg * There is no obligation of a winsys driver to use this library. And a pipe 384a49301eSmrg * driver should be completly agnostic about it. 39361fc4cbSmaya * 40af69d88dSmrg * \author Jose Fonseca <jfonseca@vmware.com> 414a49301eSmrg */ 424a49301eSmrg 434a49301eSmrg#ifndef PB_BUFFER_H_ 444a49301eSmrg#define PB_BUFFER_H_ 454a49301eSmrg 464a49301eSmrg 474a49301eSmrg#include "pipe/p_compiler.h" 484a49301eSmrg#include "util/u_debug.h" 49cdc920a0Smrg#include "util/u_inlines.h" 504a49301eSmrg#include "pipe/p_defines.h" 514a49301eSmrg 524a49301eSmrg 534a49301eSmrg#ifdef __cplusplus 544a49301eSmrgextern "C" { 554a49301eSmrg#endif 564a49301eSmrg 574a49301eSmrg 584a49301eSmrgstruct pb_vtbl; 594a49301eSmrgstruct pb_validate; 603464ebd5Sriastradhstruct pipe_fence_handle; 614a49301eSmrg 62361fc4cbSmayaenum pb_usage_flags { 63361fc4cbSmaya PB_USAGE_CPU_READ = (1 << 0), 64361fc4cbSmaya PB_USAGE_CPU_WRITE = (1 << 1), 65361fc4cbSmaya PB_USAGE_GPU_READ = (1 << 2), 66361fc4cbSmaya PB_USAGE_GPU_WRITE = (1 << 3), 677ec681f3Smrg PB_USAGE_DONTBLOCK = (1 << 4), 687ec681f3Smrg PB_USAGE_UNSYNCHRONIZED = (1 << 5), 697ec681f3Smrg /* Persistent mappings may remain across a flush. Note that contrary 707ec681f3Smrg * to OpenGL persistent maps, there is no requirement at the pipebuffer 717ec681f3Smrg * api level to explicitly enforce coherency by barriers or range flushes. 727ec681f3Smrg */ 737ec681f3Smrg PB_USAGE_PERSISTENT = (1 << 8) 74361fc4cbSmaya}; 75361fc4cbSmaya 76361fc4cbSmaya/* For error checking elsewhere */ 77361fc4cbSmaya#define PB_USAGE_ALL (PB_USAGE_CPU_READ | \ 78361fc4cbSmaya PB_USAGE_CPU_WRITE | \ 79361fc4cbSmaya PB_USAGE_GPU_READ | \ 80361fc4cbSmaya PB_USAGE_GPU_WRITE | \ 81361fc4cbSmaya PB_USAGE_DONTBLOCK | \ 827ec681f3Smrg PB_USAGE_UNSYNCHRONIZED | \ 837ec681f3Smrg PB_USAGE_PERSISTENT) 844a49301eSmrg 85361fc4cbSmaya#define PB_USAGE_CPU_READ_WRITE (PB_USAGE_CPU_READ | PB_USAGE_CPU_WRITE) 86361fc4cbSmaya#define PB_USAGE_GPU_READ_WRITE (PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE) 87361fc4cbSmaya#define PB_USAGE_WRITE (PB_USAGE_CPU_WRITE | PB_USAGE_GPU_WRITE) 883464ebd5Sriastradh 893464ebd5Sriastradh 904a49301eSmrg/** 914a49301eSmrg * Buffer description. 92361fc4cbSmaya * 934a49301eSmrg * Used when allocating the buffer. 944a49301eSmrg */ 954a49301eSmrgstruct pb_desc 964a49301eSmrg{ 974a49301eSmrg unsigned alignment; 98361fc4cbSmaya enum pb_usage_flags usage; 994a49301eSmrg}; 1004a49301eSmrg 1014a49301eSmrg 1024a49301eSmrg/** 10301e04c3fSmrg * 64-bit type for GPU buffer sizes and offsets. 1044a49301eSmrg */ 10501e04c3fSmrgtypedef uint64_t pb_size; 1064a49301eSmrg 1074a49301eSmrg 1084a49301eSmrg/** 1094a49301eSmrg * Base class for all pb_* buffers. 1104a49301eSmrg */ 111361fc4cbSmayastruct pb_buffer 1124a49301eSmrg{ 113af69d88dSmrg struct pipe_reference reference; 1147ec681f3Smrg 1157ec681f3Smrg /* For internal driver use. It's here so as not to waste space due to 1167ec681f3Smrg * type alignment. (pahole) 1177ec681f3Smrg */ 1187ec681f3Smrg uint8_t placement; 1197ec681f3Smrg 1207ec681f3Smrg /* Alignments are powers of two, so store only the bit position. 1217ec681f3Smrg * alignment_log2 = util_logbase2(alignment); 1227ec681f3Smrg * alignment = 1 << alignment_log2; 1237ec681f3Smrg */ 1247ec681f3Smrg uint8_t alignment_log2; 1257ec681f3Smrg 1267ec681f3Smrg /** 1277ec681f3Smrg * Used with pb_usage_flags or driver-specific flags, depending on drivers. 1287ec681f3Smrg */ 1297ec681f3Smrg uint16_t usage; 1307ec681f3Smrg 13101e04c3fSmrg pb_size size; 1324a49301eSmrg 1334a49301eSmrg /** 1344a49301eSmrg * Pointer to the virtual function table. 1354a49301eSmrg * 136361fc4cbSmaya * Avoid accessing this table directly. Use the inline functions below 137361fc4cbSmaya * instead to avoid mistakes. 1384a49301eSmrg */ 1394a49301eSmrg const struct pb_vtbl *vtbl; 1404a49301eSmrg}; 1414a49301eSmrg 1424a49301eSmrg 1434a49301eSmrg/** 1444a49301eSmrg * Virtual function table for the buffer storage operations. 145361fc4cbSmaya * 1464a49301eSmrg * Note that creation is not done through this table. 1474a49301eSmrg */ 1484a49301eSmrgstruct pb_vtbl 1494a49301eSmrg{ 1507ec681f3Smrg void (*destroy)(void *winsys, struct pb_buffer *buf); 1514a49301eSmrg 152361fc4cbSmaya /** 1534a49301eSmrg * Map the entire data store of a buffer object into the client's address. 154361fc4cbSmaya * flags is bitmask of PB_USAGE_CPU_READ/WRITE. 1554a49301eSmrg */ 156361fc4cbSmaya void *(*map)(struct pb_buffer *buf, 157361fc4cbSmaya enum pb_usage_flags flags, void *flush_ctx); 1584a49301eSmrg 159361fc4cbSmaya void (*unmap)(struct pb_buffer *buf); 1604a49301eSmrg 161361fc4cbSmaya enum pipe_error (*validate)(struct pb_buffer *buf, 162361fc4cbSmaya struct pb_validate *vl, 163361fc4cbSmaya enum pb_usage_flags flags); 164361fc4cbSmaya 165361fc4cbSmaya void (*fence)(struct pb_buffer *buf, 166361fc4cbSmaya struct pipe_fence_handle *fence); 1674a49301eSmrg 1684a49301eSmrg /** 1694a49301eSmrg * Get the base buffer and the offset. 170361fc4cbSmaya * 1714a49301eSmrg * A buffer can be subdivided in smaller buffers. This method should return 1724a49301eSmrg * the underlaying buffer, and the relative offset. 173361fc4cbSmaya * 174361fc4cbSmaya * Buffers without an underlaying base buffer should return themselves, with 1754a49301eSmrg * a zero offset. 176361fc4cbSmaya * 1774a49301eSmrg * Note that this will increase the reference count of the base buffer. 1784a49301eSmrg */ 179361fc4cbSmaya void (*get_base_buffer)(struct pb_buffer *buf, 180361fc4cbSmaya struct pb_buffer **base_buf, 181361fc4cbSmaya pb_size *offset); 1824a49301eSmrg}; 1834a49301eSmrg 1844a49301eSmrg 1854a49301eSmrg 1864a49301eSmrg/* Accessor functions for pb->vtbl: 1874a49301eSmrg */ 18801e04c3fSmrgstatic inline void * 189361fc4cbSmayapb_map(struct pb_buffer *buf, enum pb_usage_flags flags, void *flush_ctx) 1904a49301eSmrg{ 1914a49301eSmrg assert(buf); 19201e04c3fSmrg if (!buf) 1934a49301eSmrg return NULL; 194af69d88dSmrg assert(pipe_is_referenced(&buf->reference)); 1953464ebd5Sriastradh return buf->vtbl->map(buf, flags, flush_ctx); 1964a49301eSmrg} 1974a49301eSmrg 1984a49301eSmrg 199361fc4cbSmayastatic inline void 2004a49301eSmrgpb_unmap(struct pb_buffer *buf) 2014a49301eSmrg{ 2024a49301eSmrg assert(buf); 20301e04c3fSmrg if (!buf) 2044a49301eSmrg return; 205af69d88dSmrg assert(pipe_is_referenced(&buf->reference)); 2064a49301eSmrg buf->vtbl->unmap(buf); 2074a49301eSmrg} 2084a49301eSmrg 2094a49301eSmrg 21001e04c3fSmrgstatic inline void 211361fc4cbSmayapb_get_base_buffer(struct pb_buffer *buf, 212361fc4cbSmaya struct pb_buffer **base_buf, 213361fc4cbSmaya pb_size *offset) 2144a49301eSmrg{ 2154a49301eSmrg assert(buf); 21601e04c3fSmrg if (!buf) { 2174a49301eSmrg base_buf = NULL; 2184a49301eSmrg offset = 0; 2194a49301eSmrg return; 2204a49301eSmrg } 221af69d88dSmrg assert(pipe_is_referenced(&buf->reference)); 2224a49301eSmrg assert(buf->vtbl->get_base_buffer); 2234a49301eSmrg buf->vtbl->get_base_buffer(buf, base_buf, offset); 2244a49301eSmrg assert(*base_buf); 225af69d88dSmrg assert(*offset < (*base_buf)->size); 2264a49301eSmrg} 2274a49301eSmrg 2284a49301eSmrg 229361fc4cbSmayastatic inline enum pipe_error 230361fc4cbSmayapb_validate(struct pb_buffer *buf, struct pb_validate *vl, 231361fc4cbSmaya enum pb_usage_flags flags) 2324a49301eSmrg{ 2334a49301eSmrg assert(buf); 23401e04c3fSmrg if (!buf) 2354a49301eSmrg return PIPE_ERROR; 2364a49301eSmrg assert(buf->vtbl->validate); 2374a49301eSmrg return buf->vtbl->validate(buf, vl, flags); 2384a49301eSmrg} 2394a49301eSmrg 2404a49301eSmrg 241361fc4cbSmayastatic inline void 2424a49301eSmrgpb_fence(struct pb_buffer *buf, struct pipe_fence_handle *fence) 2434a49301eSmrg{ 2444a49301eSmrg assert(buf); 24501e04c3fSmrg if (!buf) 2464a49301eSmrg return; 2474a49301eSmrg assert(buf->vtbl->fence); 2484a49301eSmrg buf->vtbl->fence(buf, fence); 2494a49301eSmrg} 2504a49301eSmrg 2514a49301eSmrg 252361fc4cbSmayastatic inline void 2537ec681f3Smrgpb_destroy(void *winsys, struct pb_buffer *buf) 2544a49301eSmrg{ 2554a49301eSmrg assert(buf); 25601e04c3fSmrg if (!buf) 2574a49301eSmrg return; 258af69d88dSmrg assert(!pipe_is_referenced(&buf->reference)); 2597ec681f3Smrg buf->vtbl->destroy(winsys, buf); 2604a49301eSmrg} 2614a49301eSmrg 262361fc4cbSmaya 26301e04c3fSmrgstatic inline void 2644a49301eSmrgpb_reference(struct pb_buffer **dst, 2654a49301eSmrg struct pb_buffer *src) 2664a49301eSmrg{ 2674a49301eSmrg struct pb_buffer *old = *dst; 2684a49301eSmrg 269af69d88dSmrg if (pipe_reference(&(*dst)->reference, &src->reference)) 2707ec681f3Smrg pb_destroy(NULL, old); 271cdc920a0Smrg *dst = src; 2724a49301eSmrg} 2734a49301eSmrg 2747ec681f3Smrgstatic inline void 2757ec681f3Smrgpb_reference_with_winsys(void *winsys, 2767ec681f3Smrg struct pb_buffer **dst, 2777ec681f3Smrg struct pb_buffer *src) 2787ec681f3Smrg{ 2797ec681f3Smrg struct pb_buffer *old = *dst; 2807ec681f3Smrg 2817ec681f3Smrg if (pipe_reference(&(*dst)->reference, &src->reference)) 2827ec681f3Smrg pb_destroy(winsys, old); 2837ec681f3Smrg *dst = src; 2847ec681f3Smrg} 2854a49301eSmrg 2864a49301eSmrg/** 2874a49301eSmrg * Utility function to check whether the provided alignment is consistent with 2884a49301eSmrg * the requested or not. 2894a49301eSmrg */ 29001e04c3fSmrgstatic inline boolean 2917ec681f3Smrgpb_check_alignment(uint32_t requested, uint32_t provided) 2924a49301eSmrg{ 293361fc4cbSmaya if (!requested) 2944a49301eSmrg return TRUE; 295361fc4cbSmaya if (requested > provided) 2964a49301eSmrg return FALSE; 297361fc4cbSmaya if (provided % requested != 0) 2984a49301eSmrg return FALSE; 2994a49301eSmrg return TRUE; 3004a49301eSmrg} 3014a49301eSmrg 3024a49301eSmrg 3034a49301eSmrg/** 3044a49301eSmrg * Utility function to check whether the provided alignment is consistent with 3054a49301eSmrg * the requested or not. 3064a49301eSmrg */ 30701e04c3fSmrgstatic inline boolean 3084a49301eSmrgpb_check_usage(unsigned requested, unsigned provided) 3094a49301eSmrg{ 3104a49301eSmrg return (requested & provided) == requested ? TRUE : FALSE; 3114a49301eSmrg} 3124a49301eSmrg 3134a49301eSmrg#ifdef __cplusplus 3144a49301eSmrg} 3154a49301eSmrg#endif 3164a49301eSmrg 3174a49301eSmrg#endif /*PB_BUFFER_H_*/ 318