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