1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 #include "main/imports.h"
30 #include "main/mfeatures.h"
31 #include "main/mtypes.h"
32 #include "main/macros.h"
33 #include "main/bufferobj.h"
35 #include "intel_blit.h"
36 #include "intel_buffer_objects.h"
37 #include "intel_batchbuffer.h"
38 #include "intel_context.h"
39 #include "intel_fbo.h"
40 #include "intel_mipmap_tree.h"
41 #include "intel_regions.h"
44 intel_bufferobj_unmap(struct gl_context
* ctx
, struct gl_buffer_object
*obj
);
46 /** Allocates a new drm_intel_bo to store the data for the buffer object. */
48 intel_bufferobj_alloc_buffer(struct intel_context
*intel
,
49 struct intel_buffer_object
*intel_obj
)
51 intel_obj
->buffer
= drm_intel_bo_alloc(intel
->bufmgr
, "bufferobj",
52 intel_obj
->Base
.Size
, 64);
56 release_buffer(struct intel_buffer_object
*intel_obj
)
58 drm_intel_bo_unreference(intel_obj
->buffer
);
59 intel_obj
->buffer
= NULL
;
60 intel_obj
->offset
= 0;
61 intel_obj
->source
= 0;
65 * There is some duplication between mesa's bufferobjects and our
66 * bufmgr buffers. Both have an integer handle and a hashtable to
67 * lookup an opaque structure. It would be nice if the handles and
68 * internal structure where somehow shared.
70 static struct gl_buffer_object
*
71 intel_bufferobj_alloc(struct gl_context
* ctx
, GLuint name
, GLenum target
)
73 struct intel_buffer_object
*obj
= CALLOC_STRUCT(intel_buffer_object
);
75 _mesa_initialize_buffer_object(&obj
->Base
, name
, target
);
82 /* Break the COW tie to the region. The region gets to keep the data.
85 intel_bufferobj_release_region(struct intel_buffer_object
*intel_obj
)
87 assert(intel_obj
->region
->buffer
== intel_obj
->buffer
);
88 intel_obj
->region
->pbo
= NULL
;
89 intel_obj
->region
= NULL
;
91 release_buffer(intel_obj
);
94 /* Break the COW tie to the region. Both the pbo and the region end
95 * up with a copy of the data.
98 intel_bufferobj_cow(struct intel_context
*intel
,
99 struct intel_buffer_object
*intel_obj
)
101 assert(intel_obj
->region
);
102 intel_region_cow(intel
, intel_obj
->region
);
107 * Deallocate/free a vertex/pixel buffer object.
108 * Called via glDeleteBuffersARB().
111 intel_bufferobj_free(struct gl_context
* ctx
, struct gl_buffer_object
*obj
)
113 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
117 /* Buffer objects are automatically unmapped when deleting according
118 * to the spec, but Mesa doesn't do UnmapBuffer for us at context destroy
119 * (though it does if you call glDeleteBuffers)
122 intel_bufferobj_unmap(ctx
, obj
);
124 free(intel_obj
->sys_buffer
);
125 if (intel_obj
->region
) {
126 intel_bufferobj_release_region(intel_obj
);
129 drm_intel_bo_unreference(intel_obj
->buffer
);
136 * Allocate space for and store data in a buffer object. Any data that was
137 * previously stored in the buffer object is lost. If data is NULL,
138 * memory will be allocated, but no copy will occur.
139 * Called via ctx->Driver.BufferData().
140 * \return GL_TRUE for success, GL_FALSE if out of memory
143 intel_bufferobj_data(struct gl_context
* ctx
,
147 GLenum usage
, struct gl_buffer_object
*obj
)
149 struct intel_context
*intel
= intel_context(ctx
);
150 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
152 /* Part of the ABI, but this function doesn't use it.
158 intel_obj
->Base
.Size
= size
;
159 intel_obj
->Base
.Usage
= usage
;
161 assert(!obj
->Pointer
); /* Mesa should have unmapped it */
163 if (intel_obj
->region
)
164 intel_bufferobj_release_region(intel_obj
);
166 if (intel_obj
->buffer
!= NULL
)
167 release_buffer(intel_obj
);
169 free(intel_obj
->sys_buffer
);
170 intel_obj
->sys_buffer
= NULL
;
173 if (usage
== GL_DYNAMIC_DRAW
175 /* On pre-965, stick VBOs in system memory, as we're always doing
176 * swtnl with their contents anyway.
178 || target
== GL_ARRAY_BUFFER
|| target
== GL_ELEMENT_ARRAY_BUFFER
182 intel_obj
->sys_buffer
= malloc(size
);
183 if (intel_obj
->sys_buffer
!= NULL
) {
185 memcpy(intel_obj
->sys_buffer
, data
, size
);
189 intel_bufferobj_alloc_buffer(intel
, intel_obj
);
190 if (!intel_obj
->buffer
)
194 drm_intel_bo_subdata(intel_obj
->buffer
, 0, size
, data
);
202 * Replace data in a subrange of buffer object. If the data range
203 * specified by size + offset extends beyond the end of the buffer or
204 * if data is NULL, no copy is performed.
205 * Called via glBufferSubDataARB().
208 intel_bufferobj_subdata(struct gl_context
* ctx
,
211 const GLvoid
* data
, struct gl_buffer_object
*obj
)
213 struct intel_context
*intel
= intel_context(ctx
);
214 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
222 if (intel_obj
->region
)
223 intel_bufferobj_cow(intel
, intel_obj
);
225 /* If we have a single copy in system memory, update that */
226 if (intel_obj
->sys_buffer
) {
227 if (intel_obj
->source
)
228 release_buffer(intel_obj
);
230 if (intel_obj
->buffer
== NULL
) {
231 memcpy((char *)intel_obj
->sys_buffer
+ offset
, data
, size
);
235 free(intel_obj
->sys_buffer
);
236 intel_obj
->sys_buffer
= NULL
;
239 /* Otherwise we need to update the copy in video memory. */
241 drm_intel_bo_busy(intel_obj
->buffer
) ||
242 drm_intel_bo_references(intel
->batch
.bo
, intel_obj
->buffer
);
244 /* replace the current busy bo with fresh data */
245 if (busy
&& size
== intel_obj
->Base
.Size
) {
246 drm_intel_bo_unreference(intel_obj
->buffer
);
247 intel_bufferobj_alloc_buffer(intel
, intel_obj
);
248 drm_intel_bo_subdata(intel_obj
->buffer
, 0, size
, data
);
249 } else if (intel
->gen
< 6) {
251 drm_intel_bo
*temp_bo
;
253 temp_bo
= drm_intel_bo_alloc(intel
->bufmgr
, "subdata temp", size
, 64);
255 drm_intel_bo_subdata(temp_bo
, 0, size
, data
);
257 intel_emit_linear_blit(intel
,
258 intel_obj
->buffer
, offset
,
262 drm_intel_bo_unreference(temp_bo
);
264 drm_intel_bo_subdata(intel_obj
->buffer
, offset
, size
, data
);
267 /* Can't use the blit to modify the buffer in the middle of batch. */
268 if (drm_intel_bo_references(intel
->batch
.bo
, intel_obj
->buffer
)) {
269 intel_batchbuffer_flush(intel
);
271 drm_intel_bo_subdata(intel_obj
->buffer
, offset
, size
, data
);
277 * Called via glGetBufferSubDataARB().
280 intel_bufferobj_get_subdata(struct gl_context
* ctx
,
283 GLvoid
* data
, struct gl_buffer_object
*obj
)
285 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
286 struct intel_context
*intel
= intel_context(ctx
);
289 if (intel_obj
->sys_buffer
)
290 memcpy(data
, (char *)intel_obj
->sys_buffer
+ offset
, size
);
292 if (drm_intel_bo_references(intel
->batch
.bo
, intel_obj
->buffer
)) {
293 intel_batchbuffer_flush(intel
);
295 drm_intel_bo_get_subdata(intel_obj
->buffer
, offset
, size
, data
);
302 * Called via glMapBufferRange and glMapBuffer
304 * The goal of this extension is to allow apps to accumulate their rendering
305 * at the same time as they accumulate their buffer object. Without it,
306 * you'd end up blocking on execution of rendering every time you mapped
307 * the buffer to put new data in.
309 * We support it in 3 ways: If unsynchronized, then don't bother
310 * flushing the batchbuffer before mapping the buffer, which can save blocking
311 * in many cases. If we would still block, and they allow the whole buffer
312 * to be invalidated, then just allocate a new buffer to replace the old one.
313 * If not, and we'd block, and they allow the subrange of the buffer to be
314 * invalidated, then we can make a new little BO, let them write into that,
315 * and blit it into the real BO at unmap time.
318 intel_bufferobj_map_range(struct gl_context
* ctx
,
319 GLintptr offset
, GLsizeiptr length
,
320 GLbitfield access
, struct gl_buffer_object
*obj
)
322 struct intel_context
*intel
= intel_context(ctx
);
323 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
327 /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also
328 * internally uses our functions directly.
330 obj
->Offset
= offset
;
331 obj
->Length
= length
;
332 obj
->AccessFlags
= access
;
334 if (intel_obj
->sys_buffer
) {
335 const bool read_only
=
336 (access
& (GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
)) == GL_MAP_READ_BIT
;
338 if (!read_only
&& intel_obj
->source
)
339 release_buffer(intel_obj
);
341 if (!intel_obj
->buffer
|| intel_obj
->source
) {
342 obj
->Pointer
= intel_obj
->sys_buffer
+ offset
;
346 free(intel_obj
->sys_buffer
);
347 intel_obj
->sys_buffer
= NULL
;
350 if (intel_obj
->region
)
351 intel_bufferobj_cow(intel
, intel_obj
);
353 /* If the mapping is synchronized with other GL operations, flush
354 * the batchbuffer so that GEM knows about the buffer access for later
357 if (!(access
& GL_MAP_UNSYNCHRONIZED_BIT
) &&
358 drm_intel_bo_references(intel
->batch
.bo
, intel_obj
->buffer
))
361 if (intel_obj
->buffer
== NULL
) {
366 /* If the user doesn't care about existing buffer contents and mapping
367 * would cause us to block, then throw out the old buffer.
369 if (!(access
& GL_MAP_UNSYNCHRONIZED_BIT
) &&
370 (access
& GL_MAP_INVALIDATE_BUFFER_BIT
) &&
371 drm_intel_bo_busy(intel_obj
->buffer
)) {
372 drm_intel_bo_unreference(intel_obj
->buffer
);
373 intel_bufferobj_alloc_buffer(intel
, intel_obj
);
376 /* If the user is mapping a range of an active buffer object but
377 * doesn't require the current contents of that range, make a new
378 * BO, and we'll copy what they put in there out at unmap or
381 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) &&
382 drm_intel_bo_busy(intel_obj
->buffer
)) {
383 if (access
& GL_MAP_FLUSH_EXPLICIT_BIT
) {
384 intel_obj
->range_map_buffer
= malloc(length
);
385 obj
->Pointer
= intel_obj
->range_map_buffer
;
387 intel_obj
->range_map_bo
= drm_intel_bo_alloc(intel
->bufmgr
,
390 if (!(access
& GL_MAP_READ_BIT
)) {
391 drm_intel_gem_bo_map_gtt(intel_obj
->range_map_bo
);
392 intel_obj
->mapped_gtt
= GL_TRUE
;
394 drm_intel_bo_map(intel_obj
->range_map_bo
,
395 (access
& GL_MAP_WRITE_BIT
) != 0);
396 intel_obj
->mapped_gtt
= GL_FALSE
;
398 obj
->Pointer
= intel_obj
->range_map_bo
->virtual;
403 if (!(access
& GL_MAP_READ_BIT
)) {
404 drm_intel_gem_bo_map_gtt(intel_obj
->buffer
);
405 intel_obj
->mapped_gtt
= GL_TRUE
;
407 drm_intel_bo_map(intel_obj
->buffer
, (access
& GL_MAP_WRITE_BIT
) != 0);
408 intel_obj
->mapped_gtt
= GL_FALSE
;
411 obj
->Pointer
= intel_obj
->buffer
->virtual + offset
;
415 /* Ideally we'd use a BO to avoid taking up cache space for the temporary
416 * data, but FlushMappedBufferRange may be followed by further writes to
417 * the pointer, so we would have to re-map after emitting our blit, which
418 * would defeat the point.
421 intel_bufferobj_flush_mapped_range(struct gl_context
*ctx
,
422 GLintptr offset
, GLsizeiptr length
,
423 struct gl_buffer_object
*obj
)
425 struct intel_context
*intel
= intel_context(ctx
);
426 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
427 drm_intel_bo
*temp_bo
;
429 /* Unless we're in the range map using a temporary system buffer,
430 * there's no work to do.
432 if (intel_obj
->range_map_buffer
== NULL
)
438 temp_bo
= drm_intel_bo_alloc(intel
->bufmgr
, "range map flush", length
, 64);
440 drm_intel_bo_subdata(temp_bo
, 0, length
, intel_obj
->range_map_buffer
);
442 intel_emit_linear_blit(intel
,
443 intel_obj
->buffer
, obj
->Offset
+ offset
,
447 drm_intel_bo_unreference(temp_bo
);
452 * Called via glUnmapBuffer().
455 intel_bufferobj_unmap(struct gl_context
* ctx
, struct gl_buffer_object
*obj
)
457 struct intel_context
*intel
= intel_context(ctx
);
458 struct intel_buffer_object
*intel_obj
= intel_buffer_object(obj
);
461 assert(obj
->Pointer
);
462 if (intel_obj
->sys_buffer
!= NULL
) {
463 /* always keep the mapping around. */
464 } else if (intel_obj
->range_map_buffer
!= NULL
) {
465 /* Since we've emitted some blits to buffers that will (likely) be used
466 * in rendering operations in other cache domains in this batch, emit a
467 * flush. Once again, we wish for a domain tracker in libdrm to cover
468 * usage inside of a batchbuffer.
470 intel_batchbuffer_emit_mi_flush(intel
);
471 free(intel_obj
->range_map_buffer
);
472 intel_obj
->range_map_buffer
= NULL
;
473 } else if (intel_obj
->range_map_bo
!= NULL
) {
474 if (intel_obj
->mapped_gtt
) {
475 drm_intel_gem_bo_unmap_gtt(intel_obj
->range_map_bo
);
477 drm_intel_bo_unmap(intel_obj
->range_map_bo
);
480 intel_emit_linear_blit(intel
,
481 intel_obj
->buffer
, obj
->Offset
,
482 intel_obj
->range_map_bo
, 0,
485 /* Since we've emitted some blits to buffers that will (likely) be used
486 * in rendering operations in other cache domains in this batch, emit a
487 * flush. Once again, we wish for a domain tracker in libdrm to cover
488 * usage inside of a batchbuffer.
490 intel_batchbuffer_emit_mi_flush(intel
);
492 drm_intel_bo_unreference(intel_obj
->range_map_bo
);
493 intel_obj
->range_map_bo
= NULL
;
494 } else if (intel_obj
->buffer
!= NULL
) {
495 if (intel_obj
->mapped_gtt
) {
496 drm_intel_gem_bo_unmap_gtt(intel_obj
->buffer
);
498 drm_intel_bo_unmap(intel_obj
->buffer
);
509 intel_bufferobj_buffer(struct intel_context
*intel
,
510 struct intel_buffer_object
*intel_obj
,
513 if (intel_obj
->region
) {
514 if (flag
== INTEL_WRITE_PART
)
515 intel_bufferobj_cow(intel
, intel_obj
);
516 else if (flag
== INTEL_WRITE_FULL
) {
517 intel_bufferobj_release_region(intel_obj
);
518 intel_bufferobj_alloc_buffer(intel
, intel_obj
);
522 if (intel_obj
->source
)
523 release_buffer(intel_obj
);
525 if (intel_obj
->buffer
== NULL
) {
526 intel_bufferobj_alloc_buffer(intel
, intel_obj
);
527 drm_intel_bo_subdata(intel_obj
->buffer
,
528 0, intel_obj
->Base
.Size
,
529 intel_obj
->sys_buffer
);
531 free(intel_obj
->sys_buffer
);
532 intel_obj
->sys_buffer
= NULL
;
533 intel_obj
->offset
= 0;
536 return intel_obj
->buffer
;
539 #define INTEL_UPLOAD_SIZE (64*1024)
542 intel_upload_finish(struct intel_context
*intel
)
544 if (!intel
->upload
.bo
)
547 if (intel
->upload
.buffer_len
) {
548 drm_intel_bo_subdata(intel
->upload
.bo
,
549 intel
->upload
.buffer_offset
,
550 intel
->upload
.buffer_len
,
551 intel
->upload
.buffer
);
552 intel
->upload
.buffer_len
= 0;
555 drm_intel_bo_unreference(intel
->upload
.bo
);
556 intel
->upload
.bo
= NULL
;
559 static void wrap_buffers(struct intel_context
*intel
, GLuint size
)
561 intel_upload_finish(intel
);
563 if (size
< INTEL_UPLOAD_SIZE
)
564 size
= INTEL_UPLOAD_SIZE
;
566 intel
->upload
.bo
= drm_intel_bo_alloc(intel
->bufmgr
, "upload", size
, 0);
567 intel
->upload
.offset
= 0;
570 void intel_upload_data(struct intel_context
*intel
,
571 const void *ptr
, GLuint size
, GLuint align
,
572 drm_intel_bo
**return_bo
,
573 GLuint
*return_offset
)
577 base
= (intel
->upload
.offset
+ align
- 1) / align
* align
;
578 if (intel
->upload
.bo
== NULL
|| base
+ size
> intel
->upload
.bo
->size
) {
579 wrap_buffers(intel
, size
);
583 drm_intel_bo_reference(intel
->upload
.bo
);
584 *return_bo
= intel
->upload
.bo
;
585 *return_offset
= base
;
587 delta
= base
- intel
->upload
.offset
;
588 if (intel
->upload
.buffer_len
&&
589 intel
->upload
.buffer_len
+ delta
+ size
> sizeof(intel
->upload
.buffer
))
591 drm_intel_bo_subdata(intel
->upload
.bo
,
592 intel
->upload
.buffer_offset
,
593 intel
->upload
.buffer_len
,
594 intel
->upload
.buffer
);
595 intel
->upload
.buffer_len
= 0;
598 if (size
< sizeof(intel
->upload
.buffer
))
600 if (intel
->upload
.buffer_len
== 0)
601 intel
->upload
.buffer_offset
= base
;
603 intel
->upload
.buffer_len
+= delta
;
605 memcpy(intel
->upload
.buffer
+ intel
->upload
.buffer_len
, ptr
, size
);
606 intel
->upload
.buffer_len
+= size
;
610 drm_intel_bo_subdata(intel
->upload
.bo
, base
, size
, ptr
);
613 intel
->upload
.offset
= base
+ size
;
616 void *intel_upload_map(struct intel_context
*intel
, GLuint size
, GLuint align
)
621 base
= (intel
->upload
.offset
+ align
- 1) / align
* align
;
622 if (intel
->upload
.bo
== NULL
|| base
+ size
> intel
->upload
.bo
->size
) {
623 wrap_buffers(intel
, size
);
627 delta
= base
- intel
->upload
.offset
;
628 if (intel
->upload
.buffer_len
&&
629 intel
->upload
.buffer_len
+ delta
+ size
> sizeof(intel
->upload
.buffer
))
631 drm_intel_bo_subdata(intel
->upload
.bo
,
632 intel
->upload
.buffer_offset
,
633 intel
->upload
.buffer_len
,
634 intel
->upload
.buffer
);
635 intel
->upload
.buffer_len
= 0;
638 if (size
<= sizeof(intel
->upload
.buffer
)) {
639 if (intel
->upload
.buffer_len
== 0)
640 intel
->upload
.buffer_offset
= base
;
642 intel
->upload
.buffer_len
+= delta
;
644 ptr
= intel
->upload
.buffer
+ intel
->upload
.buffer_len
;
645 intel
->upload
.buffer_len
+= size
;
652 void intel_upload_unmap(struct intel_context
*intel
,
653 const void *ptr
, GLuint size
, GLuint align
,
654 drm_intel_bo
**return_bo
,
655 GLuint
*return_offset
)
659 base
= (intel
->upload
.offset
+ align
- 1) / align
* align
;
660 if (size
> sizeof(intel
->upload
.buffer
)) {
661 drm_intel_bo_subdata(intel
->upload
.bo
, base
, size
, ptr
);
665 drm_intel_bo_reference(intel
->upload
.bo
);
666 *return_bo
= intel
->upload
.bo
;
667 *return_offset
= base
;
669 intel
->upload
.offset
= base
+ size
;
673 intel_bufferobj_source(struct intel_context
*intel
,
674 struct intel_buffer_object
*intel_obj
,
675 GLuint align
, GLuint
*offset
)
677 if (intel_obj
->buffer
== NULL
) {
678 intel_upload_data(intel
,
679 intel_obj
->sys_buffer
, intel_obj
->Base
.Size
, align
,
680 &intel_obj
->buffer
, &intel_obj
->offset
);
681 intel_obj
->source
= 1;
684 *offset
= intel_obj
->offset
;
685 return intel_obj
->buffer
;
689 intel_bufferobj_copy_subdata(struct gl_context
*ctx
,
690 struct gl_buffer_object
*src
,
691 struct gl_buffer_object
*dst
,
692 GLintptr read_offset
, GLintptr write_offset
,
695 struct intel_context
*intel
= intel_context(ctx
);
696 struct intel_buffer_object
*intel_src
= intel_buffer_object(src
);
697 struct intel_buffer_object
*intel_dst
= intel_buffer_object(dst
);
698 drm_intel_bo
*src_bo
, *dst_bo
;
704 /* If we're in system memory, just map and memcpy. */
705 if (intel_src
->sys_buffer
|| intel_dst
->sys_buffer
|| intel
->gen
>= 6) {
706 /* The same buffer may be used, but note that regions copied may
710 char *ptr
= intel_bufferobj_map_range(ctx
, 0, dst
->Size
,
711 GL_MAP_READ_BIT
, dst
);
712 memmove(ptr
+ write_offset
, ptr
+ read_offset
, size
);
713 intel_bufferobj_unmap(ctx
, dst
);
718 src_ptr
= intel_bufferobj_map_range(ctx
, 0, src
->Size
,
719 GL_MAP_READ_BIT
, src
);
720 dst_ptr
= intel_bufferobj_map_range(ctx
, 0, dst
->Size
,
721 GL_MAP_WRITE_BIT
, dst
);
723 memcpy(dst_ptr
+ write_offset
, src_ptr
+ read_offset
, size
);
725 intel_bufferobj_unmap(ctx
, src
);
726 intel_bufferobj_unmap(ctx
, dst
);
731 /* Otherwise, we have real BOs, so blit them. */
733 dst_bo
= intel_bufferobj_buffer(intel
, intel_dst
, INTEL_WRITE_PART
);
734 src_bo
= intel_bufferobj_source(intel
, intel_src
, 64, &src_offset
);
736 intel_emit_linear_blit(intel
,
737 dst_bo
, write_offset
,
738 src_bo
, read_offset
+ src_offset
, size
);
740 /* Since we've emitted some blits to buffers that will (likely) be used
741 * in rendering operations in other cache domains in this batch, emit a
742 * flush. Once again, we wish for a domain tracker in libdrm to cover
743 * usage inside of a batchbuffer.
745 intel_batchbuffer_emit_mi_flush(intel
);
748 #if FEATURE_APPLE_object_purgeable
750 intel_buffer_purgeable(drm_intel_bo
*buffer
)
755 retained
= drm_intel_bo_madvise (buffer
, I915_MADV_DONTNEED
);
757 return retained
? GL_VOLATILE_APPLE
: GL_RELEASED_APPLE
;
761 intel_buffer_object_purgeable(struct gl_context
* ctx
,
762 struct gl_buffer_object
*obj
,
765 struct intel_buffer_object
*intel_obj
= intel_buffer_object (obj
);
767 if (intel_obj
->buffer
!= NULL
)
768 return intel_buffer_purgeable(intel_obj
->buffer
);
770 if (option
== GL_RELEASED_APPLE
) {
771 if (intel_obj
->sys_buffer
!= NULL
) {
772 free(intel_obj
->sys_buffer
);
773 intel_obj
->sys_buffer
= NULL
;
776 return GL_RELEASED_APPLE
;
778 /* XXX Create the buffer and madvise(MADV_DONTNEED)? */
779 struct intel_context
*intel
= intel_context(ctx
);
780 drm_intel_bo
*bo
= intel_bufferobj_buffer(intel
, intel_obj
, INTEL_READ
);
782 return intel_buffer_purgeable(bo
);
787 intel_texture_object_purgeable(struct gl_context
* ctx
,
788 struct gl_texture_object
*obj
,
791 struct intel_texture_object
*intel
;
796 intel
= intel_texture_object(obj
);
797 if (intel
->mt
== NULL
|| intel
->mt
->region
== NULL
)
798 return GL_RELEASED_APPLE
;
800 return intel_buffer_purgeable(intel
->mt
->region
->buffer
);
804 intel_render_object_purgeable(struct gl_context
* ctx
,
805 struct gl_renderbuffer
*obj
,
808 struct intel_renderbuffer
*intel
;
813 intel
= intel_renderbuffer(obj
);
814 if (intel
->region
== NULL
)
815 return GL_RELEASED_APPLE
;
817 return intel_buffer_purgeable(intel
->region
->buffer
);
821 intel_buffer_unpurgeable(drm_intel_bo
*buffer
)
827 retained
= drm_intel_bo_madvise (buffer
, I915_MADV_WILLNEED
);
829 return retained
? GL_RETAINED_APPLE
: GL_UNDEFINED_APPLE
;
833 intel_buffer_object_unpurgeable(struct gl_context
* ctx
,
834 struct gl_buffer_object
*obj
,
840 return intel_buffer_unpurgeable(intel_buffer_object (obj
)->buffer
);
844 intel_texture_object_unpurgeable(struct gl_context
* ctx
,
845 struct gl_texture_object
*obj
,
848 struct intel_texture_object
*intel
;
853 intel
= intel_texture_object(obj
);
854 if (intel
->mt
== NULL
|| intel
->mt
->region
== NULL
)
855 return GL_UNDEFINED_APPLE
;
857 return intel_buffer_unpurgeable(intel
->mt
->region
->buffer
);
861 intel_render_object_unpurgeable(struct gl_context
* ctx
,
862 struct gl_renderbuffer
*obj
,
865 struct intel_renderbuffer
*intel
;
870 intel
= intel_renderbuffer(obj
);
871 if (intel
->region
== NULL
)
872 return GL_UNDEFINED_APPLE
;
874 return intel_buffer_unpurgeable(intel
->region
->buffer
);
879 intelInitBufferObjectFuncs(struct dd_function_table
*functions
)
881 functions
->NewBufferObject
= intel_bufferobj_alloc
;
882 functions
->DeleteBuffer
= intel_bufferobj_free
;
883 functions
->BufferData
= intel_bufferobj_data
;
884 functions
->BufferSubData
= intel_bufferobj_subdata
;
885 functions
->GetBufferSubData
= intel_bufferobj_get_subdata
;
886 functions
->MapBufferRange
= intel_bufferobj_map_range
;
887 functions
->FlushMappedBufferRange
= intel_bufferobj_flush_mapped_range
;
888 functions
->UnmapBuffer
= intel_bufferobj_unmap
;
889 functions
->CopyBufferSubData
= intel_bufferobj_copy_subdata
;
891 #if FEATURE_APPLE_object_purgeable
892 functions
->BufferObjectPurgeable
= intel_buffer_object_purgeable
;
893 functions
->TextureObjectPurgeable
= intel_texture_object_purgeable
;
894 functions
->RenderObjectPurgeable
= intel_render_object_purgeable
;
896 functions
->BufferObjectUnpurgeable
= intel_buffer_object_unpurgeable
;
897 functions
->TextureObjectUnpurgeable
= intel_texture_object_unpurgeable
;
898 functions
->RenderObjectUnpurgeable
= intel_render_object_unpurgeable
;