Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 "main/imports.h"
35
#include "main/mtypes.h"
36
#include "main/arrayobj.h"
37
#include "main/bufferobj.h"
38
 
39
#include "st_context.h"
40
#include "st_cb_bufferobjects.h"
41
 
42
#include "pipe/p_context.h"
43
#include "pipe/p_defines.h"
44
#include "util/u_inlines.h"
45
 
46
 
47
/**
48
 * There is some duplication between mesa's bufferobjects and our
49
 * bufmgr buffers.  Both have an integer handle and a hashtable to
50
 * lookup an opaque structure.  It would be nice if the handles and
51
 * internal structure where somehow shared.
52
 */
53
static struct gl_buffer_object *
54
st_bufferobj_alloc(struct gl_context *ctx, GLuint name, GLenum target)
55
{
56
   struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
57
 
58
   if (!st_obj)
59
      return NULL;
60
 
61
   _mesa_initialize_buffer_object(&st_obj->Base, name, target);
62
 
63
   return &st_obj->Base;
64
}
65
 
66
 
67
 
68
/**
69
 * Deallocate/free a vertex/pixel buffer object.
70
 * Called via glDeleteBuffersARB().
71
 */
72
static void
73
st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj)
74
{
75
   struct st_buffer_object *st_obj = st_buffer_object(obj);
76
 
77
   assert(obj->RefCount == 0);
78
   assert(st_obj->transfer == NULL);
79
 
80
   if (st_obj->buffer)
81
      pipe_resource_reference(&st_obj->buffer, NULL);
82
 
83
   free(st_obj);
84
}
85
 
86
 
87
 
88
/**
89
 * Replace data in a subrange of buffer object.  If the data range
90
 * specified by size + offset extends beyond the end of the buffer or
91
 * if data is NULL, no copy is performed.
92
 * Called via glBufferSubDataARB().
93
 */
94
static void
95
st_bufferobj_subdata(struct gl_context *ctx,
96
		     GLenum target,
97
		     GLintptrARB offset,
98
		     GLsizeiptrARB size,
99
		     const GLvoid * data, struct gl_buffer_object *obj)
100
{
101
   struct st_buffer_object *st_obj = st_buffer_object(obj);
102
 
103
   /* we may be called from VBO code, so double-check params here */
104
   ASSERT(offset >= 0);
105
   ASSERT(size >= 0);
106
   ASSERT(offset + size <= obj->Size);
107
 
108
   if (!size)
109
      return;
110
 
111
   /*
112
    * According to ARB_vertex_buffer_object specification, if data is null,
113
    * then the contents of the buffer object's data store is undefined. We just
114
    * ignore, and leave it unchanged.
115
    */
116
   if (!data)
117
      return;
118
 
119
   /* Now that transfers are per-context, we don't have to figure out
120
    * flushing here.  Usually drivers won't need to flush in this case
121
    * even if the buffer is currently referenced by hardware - they
122
    * just queue the upload as dma rather than mapping the underlying
123
    * buffer directly.
124
    */
125
   pipe_buffer_write(st_context(ctx)->pipe,
126
		     st_obj->buffer,
127
		     offset, size, data);
128
}
129
 
130
 
131
/**
132
 * Called via glGetBufferSubDataARB().
133
 */
134
static void
135
st_bufferobj_get_subdata(struct gl_context *ctx,
136
                         GLenum target,
137
                         GLintptrARB offset,
138
                         GLsizeiptrARB size,
139
                         GLvoid * data, struct gl_buffer_object *obj)
140
{
141
   struct st_buffer_object *st_obj = st_buffer_object(obj);
142
 
143
   /* we may be called from VBO code, so double-check params here */
144
   ASSERT(offset >= 0);
145
   ASSERT(size >= 0);
146
   ASSERT(offset + size <= obj->Size);
147
 
148
   if (!size)
149
      return;
150
 
151
   pipe_buffer_read(st_context(ctx)->pipe, st_obj->buffer,
152
                    offset, size, data);
153
}
154
 
155
 
156
/**
157
 * Allocate space for and store data in a buffer object.  Any data that was
158
 * previously stored in the buffer object is lost.  If data is NULL,
159
 * memory will be allocated, but no copy will occur.
160
 * Called via ctx->Driver.BufferData().
161
 * \return GL_TRUE for success, GL_FALSE if out of memory
162
 */
163
static GLboolean
164
st_bufferobj_data(struct gl_context *ctx,
165
		  GLenum target,
166
		  GLsizeiptrARB size,
167
		  const GLvoid * data,
168
		  GLenum usage,
169
		  struct gl_buffer_object *obj)
170
{
171
   struct st_context *st = st_context(ctx);
172
   struct pipe_context *pipe = st->pipe;
173
   struct st_buffer_object *st_obj = st_buffer_object(obj);
174
   unsigned buffer_usage;
175
 
176
   st_obj->Base.Size = size;
177
   st_obj->Base.Usage = usage;
178
 
179
   switch(target) {
180
   case GL_PIXEL_PACK_BUFFER_ARB:
181
   case GL_PIXEL_UNPACK_BUFFER_ARB:
182
      buffer_usage = PIPE_BIND_RENDER_TARGET;
183
      break;
184
   case GL_ARRAY_BUFFER_ARB:
185
      buffer_usage = PIPE_BIND_VERTEX_BUFFER;
186
      break;
187
   case GL_ELEMENT_ARRAY_BUFFER_ARB:
188
      buffer_usage = PIPE_BIND_INDEX_BUFFER;
189
      break;
190
   default:
191
      buffer_usage = 0;
192
   }
193
 
194
   pipe_resource_reference( &st_obj->buffer, NULL );
195
 
196
   if (size != 0) {
197
      st_obj->buffer = pipe_buffer_create(pipe->screen, buffer_usage, size);
198
 
199
      if (!st_obj->buffer) {
200
         return GL_FALSE;
201
      }
202
 
203
      if (data)
204
         pipe_buffer_write(st_context(ctx)->pipe, st_obj->buffer, 0,
205
				       size, data);
206
      return GL_TRUE;
207
   }
208
 
209
   return GL_TRUE;
210
}
211
 
212
 
213
/**
214
 * Dummy data whose's pointer is used for zero size buffers or ranges.
215
 */
216
static long st_bufferobj_zero_length = 0;
217
 
218
 
219
 
220
/**
221
 * Called via glMapBufferARB().
222
 */
223
static void *
224
st_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access,
225
                 struct gl_buffer_object *obj)
226
{
227
   struct st_buffer_object *st_obj = st_buffer_object(obj);
228
   uint flags;
229
 
230
   switch (access) {
231
   case GL_WRITE_ONLY:
232
      flags = PIPE_TRANSFER_WRITE;
233
      break;
234
   case GL_READ_ONLY:
235
      flags = PIPE_TRANSFER_READ;
236
      break;
237
   case GL_READ_WRITE:
238
   default:
239
      flags = PIPE_TRANSFER_READ_WRITE;
240
      break;
241
   }
242
 
243
   /* Handle zero-size buffers here rather than in drivers */
244
   if (obj->Size == 0) {
245
      obj->Pointer = &st_bufferobj_zero_length;
246
   }
247
   else {
248
      obj->Pointer = pipe_buffer_map(st_context(ctx)->pipe,
249
                                     st_obj->buffer,
250
                                     flags,
251
                                     &st_obj->transfer);
252
   }
253
 
254
   if (obj->Pointer) {
255
      obj->Offset = 0;
256
      obj->Length = obj->Size;
257
   }
258
   return obj->Pointer;
259
}
260
 
261
 
262
/**
263
 * Called via glMapBufferRange().
264
 */
265
static void *
266
st_bufferobj_map_range(struct gl_context *ctx, GLenum target,
267
                       GLintptr offset, GLsizeiptr length, GLbitfield access,
268
                       struct gl_buffer_object *obj)
269
{
270
   struct pipe_context *pipe = st_context(ctx)->pipe;
271
   struct st_buffer_object *st_obj = st_buffer_object(obj);
272
   enum pipe_transfer_usage flags = 0x0;
273
 
274
   if (access & GL_MAP_WRITE_BIT)
275
      flags |= PIPE_TRANSFER_WRITE;
276
 
277
   if (access & GL_MAP_READ_BIT)
278
      flags |= PIPE_TRANSFER_READ;
279
 
280
   if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
281
      flags |= PIPE_TRANSFER_FLUSH_EXPLICIT;
282
 
283
   if (access & GL_MAP_INVALIDATE_RANGE_BIT)
284
      flags |= PIPE_TRANSFER_DISCARD;
285
 
286
   if (access & GL_MAP_INVALIDATE_BUFFER_BIT)
287
      flags |= PIPE_TRANSFER_DISCARD;
288
 
289
   if (access & GL_MAP_UNSYNCHRONIZED_BIT)
290
      flags |= PIPE_TRANSFER_UNSYNCHRONIZED;
291
 
292
   /* ... other flags ...
293
    */
294
 
295
   if (access & MESA_MAP_NOWAIT_BIT)
296
      flags |= PIPE_TRANSFER_DONTBLOCK;
297
 
298
   assert(offset >= 0);
299
   assert(length >= 0);
300
   assert(offset < obj->Size);
301
   assert(offset + length <= obj->Size);
302
 
303
   /*
304
    * We go out of way here to hide the degenerate yet valid case of zero
305
    * length range from the pipe driver.
306
    */
307
   if (!length) {
308
      obj->Pointer = &st_bufferobj_zero_length;
309
   }
310
   else {
311
      obj->Pointer = pipe_buffer_map_range(pipe,
312
                                           st_obj->buffer,
313
                                           offset, length,
314
                                           flags,
315
                                           &st_obj->transfer);
316
      if (obj->Pointer) {
317
         obj->Pointer = (ubyte *) obj->Pointer + offset;
318
      }
319
   }
320
 
321
   if (obj->Pointer) {
322
      obj->Offset = offset;
323
      obj->Length = length;
324
      obj->AccessFlags = access;
325
   }
326
 
327
   return obj->Pointer;
328
}
329
 
330
 
331
static void
332
st_bufferobj_flush_mapped_range(struct gl_context *ctx, GLenum target,
333
                                GLintptr offset, GLsizeiptr length,
334
                                struct gl_buffer_object *obj)
335
{
336
   struct pipe_context *pipe = st_context(ctx)->pipe;
337
   struct st_buffer_object *st_obj = st_buffer_object(obj);
338
 
339
   /* Subrange is relative to mapped range */
340
   assert(offset >= 0);
341
   assert(length >= 0);
342
   assert(offset + length <= obj->Length);
343
   assert(obj->Pointer);
344
 
345
   if (!length)
346
      return;
347
 
348
   pipe_buffer_flush_mapped_range(pipe, st_obj->transfer,
349
                                  obj->Offset + offset, length);
350
}
351
 
352
 
353
/**
354
 * Called via glUnmapBufferARB().
355
 */
356
static GLboolean
357
st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_object *obj)
358
{
359
   struct pipe_context *pipe = st_context(ctx)->pipe;
360
   struct st_buffer_object *st_obj = st_buffer_object(obj);
361
 
362
   if (obj->Length)
363
      pipe_buffer_unmap(pipe, st_obj->buffer, st_obj->transfer);
364
 
365
   st_obj->transfer = NULL;
366
   obj->Pointer = NULL;
367
   obj->Offset = 0;
368
   obj->Length = 0;
369
   return GL_TRUE;
370
}
371
 
372
 
373
/**
374
 * Called via glCopyBufferSubData().
375
 */
376
static void
377
st_copy_buffer_subdata(struct gl_context *ctx,
378
                       struct gl_buffer_object *src,
379
                       struct gl_buffer_object *dst,
380
                       GLintptr readOffset, GLintptr writeOffset,
381
                       GLsizeiptr size)
382
{
383
   struct pipe_context *pipe = st_context(ctx)->pipe;
384
   struct st_buffer_object *srcObj = st_buffer_object(src);
385
   struct st_buffer_object *dstObj = st_buffer_object(dst);
386
   struct pipe_transfer *src_transfer;
387
   struct pipe_transfer *dst_transfer;
388
   ubyte *srcPtr, *dstPtr;
389
 
390
   if(!size)
391
      return;
392
 
393
   /* buffer should not already be mapped */
394
   assert(!src->Pointer);
395
   assert(!dst->Pointer);
396
 
397
   srcPtr = (ubyte *) pipe_buffer_map_range(pipe,
398
                                            srcObj->buffer,
399
                                            readOffset, size,
400
                                            PIPE_TRANSFER_READ,
401
					    &src_transfer);
402
 
403
   dstPtr = (ubyte *) pipe_buffer_map_range(pipe,
404
                                            dstObj->buffer,
405
                                            writeOffset, size,
406
                                            PIPE_TRANSFER_WRITE,
407
					    &dst_transfer);
408
 
409
   if (srcPtr && dstPtr)
410
      memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
411
 
412
   pipe_buffer_unmap(pipe, srcObj->buffer, src_transfer);
413
   pipe_buffer_unmap(pipe, dstObj->buffer, dst_transfer);
414
}
415
 
416
 
417
/* TODO: if buffer wasn't created with appropriate usage flags, need
418
 * to recreate it now and copy contents -- or possibly create a
419
 * gallium entrypoint to extend the usage flags and let the driver
420
 * decide if a copy is necessary.
421
 */
422
void
423
st_bufferobj_validate_usage(struct st_context *st,
424
			    struct st_buffer_object *obj,
425
			    unsigned usage)
426
{
427
}
428
 
429
 
430
void
431
st_init_bufferobject_functions(struct dd_function_table *functions)
432
{
433
   functions->NewBufferObject = st_bufferobj_alloc;
434
   functions->DeleteBuffer = st_bufferobj_free;
435
   functions->BufferData = st_bufferobj_data;
436
   functions->BufferSubData = st_bufferobj_subdata;
437
   functions->GetBufferSubData = st_bufferobj_get_subdata;
438
   functions->MapBuffer = st_bufferobj_map;
439
   functions->MapBufferRange = st_bufferobj_map_range;
440
   functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
441
   functions->UnmapBuffer = st_bufferobj_unmap;
442
   functions->CopyBufferSubData = st_copy_buffer_subdata;
443
 
444
   /* For GL_APPLE_vertex_array_object */
445
   functions->NewArrayObject = _mesa_new_array_object;
446
   functions->DeleteArrayObject = _mesa_delete_array_object;
447
}