1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 
29 /**
30  * Functions for pixel buffer objects and vertex/element buffer objects.
31  */
32 
33 
34 #include <inttypes.h>  /* for PRId64 macro */
35 
36 #include "main/imports.h"
37 #include "main/mtypes.h"
38 #include "main/arrayobj.h"
39 #include "main/bufferobj.h"
40 
41 #include "st_context.h"
42 #include "st_cb_bufferobjects.h"
43 #include "st_cb_memoryobjects.h"
44 #include "st_debug.h"
45 
46 #include "pipe/p_context.h"
47 #include "pipe/p_defines.h"
48 #include "util/u_inlines.h"
49 
50 
51 /**
52  * There is some duplication between mesa's bufferobjects and our
53  * bufmgr buffers.  Both have an integer handle and a hashtable to
54  * lookup an opaque structure.  It would be nice if the handles and
55  * internal structure where somehow shared.
56  */
57 static struct gl_buffer_object *
st_bufferobj_alloc(struct gl_context * ctx,GLuint name)58 st_bufferobj_alloc(struct gl_context *ctx, GLuint name)
59 {
60    struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
61 
62    if (!st_obj)
63       return NULL;
64 
65    _mesa_initialize_buffer_object(ctx, &st_obj->Base, name);
66 
67    return &st_obj->Base;
68 }
69 
70 
71 
72 /**
73  * Deallocate/free a vertex/pixel buffer object.
74  * Called via glDeleteBuffersARB().
75  */
76 static void
st_bufferobj_free(struct gl_context * ctx,struct gl_buffer_object * obj)77 st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj)
78 {
79    struct st_buffer_object *st_obj = st_buffer_object(obj);
80 
81    assert(obj->RefCount == 0);
82    _mesa_buffer_unmap_all_mappings(ctx, obj);
83 
84    if (st_obj->buffer)
85       pipe_resource_reference(&st_obj->buffer, NULL);
86 
87    _mesa_delete_buffer_object(ctx, obj);
88 }
89 
90 
91 
92 /**
93  * Replace data in a subrange of buffer object.  If the data range
94  * specified by size + offset extends beyond the end of the buffer or
95  * if data is NULL, no copy is performed.
96  * Called via glBufferSubDataARB().
97  */
98 static void
st_bufferobj_subdata(struct gl_context * ctx,GLintptrARB offset,GLsizeiptrARB size,const void * data,struct gl_buffer_object * obj)99 st_bufferobj_subdata(struct gl_context *ctx,
100                      GLintptrARB offset,
101                      GLsizeiptrARB size,
102                      const void * data, struct gl_buffer_object *obj)
103 {
104    struct st_buffer_object *st_obj = st_buffer_object(obj);
105 
106    /* we may be called from VBO code, so double-check params here */
107    assert(offset >= 0);
108    assert(size >= 0);
109    assert(offset + size <= obj->Size);
110 
111    if (!size)
112       return;
113 
114    /*
115     * According to ARB_vertex_buffer_object specification, if data is null,
116     * then the contents of the buffer object's data store is undefined. We just
117     * ignore, and leave it unchanged.
118     */
119    if (!data)
120       return;
121 
122    if (!st_obj->buffer) {
123       /* we probably ran out of memory during buffer allocation */
124       return;
125    }
126 
127    /* Now that transfers are per-context, we don't have to figure out
128     * flushing here.  Usually drivers won't need to flush in this case
129     * even if the buffer is currently referenced by hardware - they
130     * just queue the upload as dma rather than mapping the underlying
131     * buffer directly.
132     */
133    pipe_buffer_write(st_context(ctx)->pipe,
134                      st_obj->buffer,
135                      offset, size, data);
136 }
137 
138 
139 /**
140  * Called via glGetBufferSubDataARB().
141  */
142 static void
st_bufferobj_get_subdata(struct gl_context * ctx,GLintptrARB offset,GLsizeiptrARB size,void * data,struct gl_buffer_object * obj)143 st_bufferobj_get_subdata(struct gl_context *ctx,
144                          GLintptrARB offset,
145                          GLsizeiptrARB size,
146                          void * data, struct gl_buffer_object *obj)
147 {
148    struct st_buffer_object *st_obj = st_buffer_object(obj);
149 
150    /* we may be called from VBO code, so double-check params here */
151    assert(offset >= 0);
152    assert(size >= 0);
153    assert(offset + size <= obj->Size);
154 
155    if (!size)
156       return;
157 
158    if (!st_obj->buffer) {
159       /* we probably ran out of memory during buffer allocation */
160       return;
161    }
162 
163    pipe_buffer_read(st_context(ctx)->pipe, st_obj->buffer,
164                     offset, size, data);
165 }
166 
167 static ALWAYS_INLINE GLboolean
bufferobj_data(struct gl_context * ctx,GLenum target,GLsizeiptrARB size,const void * data,struct gl_memory_object * memObj,GLuint64 offset,GLenum usage,GLbitfield storageFlags,struct gl_buffer_object * obj)168 bufferobj_data(struct gl_context *ctx,
169                GLenum target,
170                GLsizeiptrARB size,
171                const void *data,
172                struct gl_memory_object *memObj,
173                GLuint64 offset,
174                GLenum usage,
175                GLbitfield storageFlags,
176                struct gl_buffer_object *obj)
177 {
178    struct st_context *st = st_context(ctx);
179    struct pipe_context *pipe = st->pipe;
180    struct pipe_screen *screen = pipe->screen;
181    struct st_buffer_object *st_obj = st_buffer_object(obj);
182    struct st_memory_object *st_mem_obj = st_memory_object(memObj);
183    unsigned bind, pipe_usage, pipe_flags = 0;
184 
185    if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
186        size && st_obj->buffer &&
187        st_obj->Base.Size == size &&
188        st_obj->Base.Usage == usage &&
189        st_obj->Base.StorageFlags == storageFlags) {
190       if (data) {
191          /* Just discard the old contents and write new data.
192           * This should be the same as creating a new buffer, but we avoid
193           * a lot of validation in Mesa.
194           */
195          pipe->buffer_subdata(pipe, st_obj->buffer,
196                               PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
197                               0, size, data);
198          return GL_TRUE;
199       } else if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER)) {
200          pipe->invalidate_resource(pipe, st_obj->buffer);
201          return GL_TRUE;
202       }
203    }
204 
205    st_obj->Base.Size = size;
206    st_obj->Base.Usage = usage;
207    st_obj->Base.StorageFlags = storageFlags;
208 
209    switch (target) {
210    case GL_PIXEL_PACK_BUFFER_ARB:
211    case GL_PIXEL_UNPACK_BUFFER_ARB:
212       bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
213       break;
214    case GL_ARRAY_BUFFER_ARB:
215       bind = PIPE_BIND_VERTEX_BUFFER;
216       break;
217    case GL_ELEMENT_ARRAY_BUFFER_ARB:
218       bind = PIPE_BIND_INDEX_BUFFER;
219       break;
220    case GL_TEXTURE_BUFFER:
221       bind = PIPE_BIND_SAMPLER_VIEW;
222       break;
223    case GL_TRANSFORM_FEEDBACK_BUFFER:
224       bind = PIPE_BIND_STREAM_OUTPUT;
225       break;
226    case GL_UNIFORM_BUFFER:
227       bind = PIPE_BIND_CONSTANT_BUFFER;
228       break;
229    case GL_DRAW_INDIRECT_BUFFER:
230    case GL_PARAMETER_BUFFER_ARB:
231       bind = PIPE_BIND_COMMAND_ARGS_BUFFER;
232       break;
233    case GL_ATOMIC_COUNTER_BUFFER:
234    case GL_SHADER_STORAGE_BUFFER:
235       bind = PIPE_BIND_SHADER_BUFFER;
236       break;
237    case GL_QUERY_BUFFER:
238       bind = PIPE_BIND_QUERY_BUFFER;
239       break;
240    default:
241       bind = 0;
242    }
243 
244    /* Set usage. */
245    if (st_obj->Base.Immutable) {
246       /* BufferStorage */
247       if (storageFlags & GL_CLIENT_STORAGE_BIT) {
248          if (storageFlags & GL_MAP_READ_BIT)
249             pipe_usage = PIPE_USAGE_STAGING;
250          else
251             pipe_usage = PIPE_USAGE_STREAM;
252       } else {
253          pipe_usage = PIPE_USAGE_DEFAULT;
254       }
255    }
256    else {
257       /* BufferData */
258       switch (usage) {
259       case GL_STATIC_DRAW:
260       case GL_STATIC_COPY:
261       default:
262          pipe_usage = PIPE_USAGE_DEFAULT;
263          break;
264       case GL_DYNAMIC_DRAW:
265       case GL_DYNAMIC_COPY:
266          pipe_usage = PIPE_USAGE_DYNAMIC;
267          break;
268       case GL_STREAM_DRAW:
269       case GL_STREAM_COPY:
270          /* XXX: Remove this test and fall-through when we have PBO unpacking
271           * acceleration. Right now, PBO unpacking is done by the CPU, so we
272           * have to make sure CPU reads are fast.
273           */
274          if (target != GL_PIXEL_UNPACK_BUFFER_ARB) {
275             pipe_usage = PIPE_USAGE_STREAM;
276             break;
277          }
278          /* fall through */
279       case GL_STATIC_READ:
280       case GL_DYNAMIC_READ:
281       case GL_STREAM_READ:
282          pipe_usage = PIPE_USAGE_STAGING;
283          break;
284       }
285    }
286 
287    /* Set flags. */
288    if (storageFlags & GL_MAP_PERSISTENT_BIT)
289       pipe_flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT;
290    if (storageFlags & GL_MAP_COHERENT_BIT)
291       pipe_flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT;
292    if (storageFlags & GL_SPARSE_STORAGE_BIT_ARB)
293       pipe_flags |= PIPE_RESOURCE_FLAG_SPARSE;
294 
295    pipe_resource_reference( &st_obj->buffer, NULL );
296 
297    if (ST_DEBUG & DEBUG_BUFFER) {
298       debug_printf("Create buffer size %" PRId64 " bind 0x%x\n",
299                    (int64_t) size, bind);
300    }
301 
302    if (size != 0) {
303       struct pipe_resource buffer;
304 
305       memset(&buffer, 0, sizeof buffer);
306       buffer.target = PIPE_BUFFER;
307       buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
308       buffer.bind = bind;
309       buffer.usage = pipe_usage;
310       buffer.flags = pipe_flags;
311       buffer.width0 = size;
312       buffer.height0 = 1;
313       buffer.depth0 = 1;
314       buffer.array_size = 1;
315 
316       if (st_mem_obj) {
317          st_obj->buffer = screen->resource_from_memobj(screen, &buffer,
318                                                        st_mem_obj->memory,
319                                                        offset);
320       }
321       else if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
322          st_obj->buffer =
323             screen->resource_from_user_memory(screen, &buffer, (void*)data);
324       }
325       else {
326          st_obj->buffer = screen->resource_create(screen, &buffer);
327 
328          if (st_obj->buffer && data)
329             pipe_buffer_write(pipe, st_obj->buffer, 0, size, data);
330       }
331 
332       if (!st_obj->buffer) {
333          /* out of memory */
334          st_obj->Base.Size = 0;
335          return GL_FALSE;
336       }
337    }
338 
339    /* The current buffer may be bound, so we have to revalidate all atoms that
340     * might be using it.
341     */
342    /* TODO: Add arrays to usage history */
343    ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS;
344    if (st_obj->Base.UsageHistory & USAGE_UNIFORM_BUFFER)
345       ctx->NewDriverState |= ST_NEW_UNIFORM_BUFFER;
346    if (st_obj->Base.UsageHistory & USAGE_SHADER_STORAGE_BUFFER)
347       ctx->NewDriverState |= ST_NEW_STORAGE_BUFFER;
348    if (st_obj->Base.UsageHistory & USAGE_TEXTURE_BUFFER)
349       ctx->NewDriverState |= ST_NEW_SAMPLER_VIEWS | ST_NEW_IMAGE_UNITS;
350    if (st_obj->Base.UsageHistory & USAGE_ATOMIC_COUNTER_BUFFER)
351       ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
352 
353    return GL_TRUE;
354 }
355 
356 /**
357  * Allocate space for and store data in a buffer object.  Any data that was
358  * previously stored in the buffer object is lost.  If data is NULL,
359  * memory will be allocated, but no copy will occur.
360  * Called via ctx->Driver.BufferData().
361  * \return GL_TRUE for success, GL_FALSE if out of memory
362  */
363 static GLboolean
st_bufferobj_data(struct gl_context * ctx,GLenum target,GLsizeiptrARB size,const void * data,GLenum usage,GLbitfield storageFlags,struct gl_buffer_object * obj)364 st_bufferobj_data(struct gl_context *ctx,
365                   GLenum target,
366                   GLsizeiptrARB size,
367                   const void *data,
368                   GLenum usage,
369                   GLbitfield storageFlags,
370                   struct gl_buffer_object *obj)
371 {
372    return bufferobj_data(ctx, target, size, data, NULL, 0, usage, storageFlags, obj);
373 }
374 
375 static GLboolean
st_bufferobj_data_mem(struct gl_context * ctx,GLenum target,GLsizeiptrARB size,struct gl_memory_object * memObj,GLuint64 offset,GLenum usage,struct gl_buffer_object * bufObj)376 st_bufferobj_data_mem(struct gl_context *ctx,
377                       GLenum target,
378                       GLsizeiptrARB size,
379                       struct gl_memory_object *memObj,
380                       GLuint64 offset,
381                       GLenum usage,
382                       struct gl_buffer_object *bufObj)
383 {
384    return bufferobj_data(ctx, target, size, NULL, memObj, offset, usage, 0, bufObj);
385 }
386 
387 /**
388  * Called via glInvalidateBuffer(Sub)Data.
389  */
390 static void
st_bufferobj_invalidate(struct gl_context * ctx,struct gl_buffer_object * obj,GLintptr offset,GLsizeiptr size)391 st_bufferobj_invalidate(struct gl_context *ctx,
392                         struct gl_buffer_object *obj,
393                         GLintptr offset,
394                         GLsizeiptr size)
395 {
396    struct st_context *st = st_context(ctx);
397    struct pipe_context *pipe = st->pipe;
398    struct st_buffer_object *st_obj = st_buffer_object(obj);
399 
400    /* We ignore partial invalidates. */
401    if (offset != 0 || size != obj->Size)
402       return;
403 
404    /* Nothing to invalidate. */
405    if (!st_obj->buffer)
406       return;
407 
408    pipe->invalidate_resource(pipe, st_obj->buffer);
409 }
410 
411 
412 /**
413  * Called via glMapBufferRange().
414  */
415 static void *
st_bufferobj_map_range(struct gl_context * ctx,GLintptr offset,GLsizeiptr length,GLbitfield access,struct gl_buffer_object * obj,gl_map_buffer_index index)416 st_bufferobj_map_range(struct gl_context *ctx,
417                        GLintptr offset, GLsizeiptr length, GLbitfield access,
418                        struct gl_buffer_object *obj,
419                        gl_map_buffer_index index)
420 {
421    struct pipe_context *pipe = st_context(ctx)->pipe;
422    struct st_buffer_object *st_obj = st_buffer_object(obj);
423    enum pipe_transfer_usage flags = 0x0;
424 
425    if (access & GL_MAP_WRITE_BIT)
426       flags |= PIPE_TRANSFER_WRITE;
427 
428    if (access & GL_MAP_READ_BIT)
429       flags |= PIPE_TRANSFER_READ;
430 
431    if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
432       flags |= PIPE_TRANSFER_FLUSH_EXPLICIT;
433 
434    if (access & GL_MAP_INVALIDATE_BUFFER_BIT) {
435       flags |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
436    }
437    else if (access & GL_MAP_INVALIDATE_RANGE_BIT) {
438       if (offset == 0 && length == obj->Size)
439          flags |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
440       else
441          flags |= PIPE_TRANSFER_DISCARD_RANGE;
442    }
443 
444    if (access & GL_MAP_UNSYNCHRONIZED_BIT)
445       flags |= PIPE_TRANSFER_UNSYNCHRONIZED;
446 
447    if (access & GL_MAP_PERSISTENT_BIT)
448       flags |= PIPE_TRANSFER_PERSISTENT;
449 
450    if (access & GL_MAP_COHERENT_BIT)
451       flags |= PIPE_TRANSFER_COHERENT;
452 
453    /* ... other flags ...
454    */
455 
456    if (access & MESA_MAP_NOWAIT_BIT)
457       flags |= PIPE_TRANSFER_DONTBLOCK;
458 
459    assert(offset >= 0);
460    assert(length >= 0);
461    assert(offset < obj->Size);
462    assert(offset + length <= obj->Size);
463 
464    obj->Mappings[index].Pointer = pipe_buffer_map_range(pipe,
465                                                         st_obj->buffer,
466                                                         offset, length,
467                                                         flags,
468                                                         &st_obj->transfer[index]);
469    if (obj->Mappings[index].Pointer) {
470       obj->Mappings[index].Offset = offset;
471       obj->Mappings[index].Length = length;
472       obj->Mappings[index].AccessFlags = access;
473    }
474    else {
475       st_obj->transfer[index] = NULL;
476    }
477 
478    return obj->Mappings[index].Pointer;
479 }
480 
481 
482 static void
st_bufferobj_flush_mapped_range(struct gl_context * ctx,GLintptr offset,GLsizeiptr length,struct gl_buffer_object * obj,gl_map_buffer_index index)483 st_bufferobj_flush_mapped_range(struct gl_context *ctx,
484                                 GLintptr offset, GLsizeiptr length,
485                                 struct gl_buffer_object *obj,
486                                 gl_map_buffer_index index)
487 {
488    struct pipe_context *pipe = st_context(ctx)->pipe;
489    struct st_buffer_object *st_obj = st_buffer_object(obj);
490 
491    /* Subrange is relative to mapped range */
492    assert(offset >= 0);
493    assert(length >= 0);
494    assert(offset + length <= obj->Mappings[index].Length);
495    assert(obj->Mappings[index].Pointer);
496 
497    if (!length)
498       return;
499 
500    pipe_buffer_flush_mapped_range(pipe, st_obj->transfer[index],
501                                   obj->Mappings[index].Offset + offset,
502                                   length);
503 }
504 
505 
506 /**
507  * Called via glUnmapBufferARB().
508  */
509 static GLboolean
st_bufferobj_unmap(struct gl_context * ctx,struct gl_buffer_object * obj,gl_map_buffer_index index)510 st_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj,
511                    gl_map_buffer_index index)
512 {
513    struct pipe_context *pipe = st_context(ctx)->pipe;
514    struct st_buffer_object *st_obj = st_buffer_object(obj);
515 
516    if (obj->Mappings[index].Length)
517       pipe_buffer_unmap(pipe, st_obj->transfer[index]);
518 
519    st_obj->transfer[index] = NULL;
520    obj->Mappings[index].Pointer = NULL;
521    obj->Mappings[index].Offset = 0;
522    obj->Mappings[index].Length = 0;
523    return GL_TRUE;
524 }
525 
526 
527 /**
528  * Called via glCopyBufferSubData().
529  */
530 static void
st_copy_buffer_subdata(struct gl_context * ctx,struct gl_buffer_object * src,struct gl_buffer_object * dst,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)531 st_copy_buffer_subdata(struct gl_context *ctx,
532                        struct gl_buffer_object *src,
533                        struct gl_buffer_object *dst,
534                        GLintptr readOffset, GLintptr writeOffset,
535                        GLsizeiptr size)
536 {
537    struct pipe_context *pipe = st_context(ctx)->pipe;
538    struct st_buffer_object *srcObj = st_buffer_object(src);
539    struct st_buffer_object *dstObj = st_buffer_object(dst);
540    struct pipe_box box;
541 
542    if (!size)
543       return;
544 
545    /* buffer should not already be mapped */
546    assert(!_mesa_check_disallowed_mapping(src));
547    assert(!_mesa_check_disallowed_mapping(dst));
548 
549    u_box_1d(readOffset, size, &box);
550 
551    pipe->resource_copy_region(pipe, dstObj->buffer, 0, writeOffset, 0, 0,
552                               srcObj->buffer, 0, &box);
553 }
554 
555 /**
556  * Called via glClearBufferSubData().
557  */
558 static void
st_clear_buffer_subdata(struct gl_context * ctx,GLintptr offset,GLsizeiptr size,const void * clearValue,GLsizeiptr clearValueSize,struct gl_buffer_object * bufObj)559 st_clear_buffer_subdata(struct gl_context *ctx,
560                         GLintptr offset, GLsizeiptr size,
561                         const void *clearValue,
562                         GLsizeiptr clearValueSize,
563                         struct gl_buffer_object *bufObj)
564 {
565    struct pipe_context *pipe = st_context(ctx)->pipe;
566    struct st_buffer_object *buf = st_buffer_object(bufObj);
567    static const char zeros[16] = {0};
568 
569    if (!pipe->clear_buffer) {
570       _mesa_ClearBufferSubData_sw(ctx, offset, size,
571                                   clearValue, clearValueSize, bufObj);
572       return;
573    }
574 
575    if (!clearValue)
576       clearValue = zeros;
577 
578    pipe->clear_buffer(pipe, buf->buffer, offset, size,
579                       clearValue, clearValueSize);
580 }
581 
582 static void
st_bufferobj_page_commitment(struct gl_context * ctx,struct gl_buffer_object * bufferObj,GLintptr offset,GLsizeiptr size,GLboolean commit)583 st_bufferobj_page_commitment(struct gl_context *ctx,
584                              struct gl_buffer_object *bufferObj,
585                              GLintptr offset, GLsizeiptr size,
586                              GLboolean commit)
587 {
588    struct pipe_context *pipe = st_context(ctx)->pipe;
589    struct st_buffer_object *buf = st_buffer_object(bufferObj);
590    struct pipe_box box;
591 
592    u_box_1d(offset, size, &box);
593 
594    if (!pipe->resource_commit(pipe, buf->buffer, 0, &box, commit)) {
595       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferPageCommitmentARB(out of memory)");
596       return;
597    }
598 }
599 
600 void
st_init_bufferobject_functions(struct pipe_screen * screen,struct dd_function_table * functions)601 st_init_bufferobject_functions(struct pipe_screen *screen,
602                                struct dd_function_table *functions)
603 {
604    functions->NewBufferObject = st_bufferobj_alloc;
605    functions->DeleteBuffer = st_bufferobj_free;
606    functions->BufferData = st_bufferobj_data;
607    functions->BufferDataMem = st_bufferobj_data_mem;
608    functions->BufferSubData = st_bufferobj_subdata;
609    functions->GetBufferSubData = st_bufferobj_get_subdata;
610    functions->MapBufferRange = st_bufferobj_map_range;
611    functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
612    functions->UnmapBuffer = st_bufferobj_unmap;
613    functions->CopyBufferSubData = st_copy_buffer_subdata;
614    functions->ClearBufferSubData = st_clear_buffer_subdata;
615    functions->BufferPageCommitment = st_bufferobj_page_commitment;
616 
617    if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER))
618       functions->InvalidateBufferSubData = st_bufferobj_invalidate;
619 }
620