diff options
author | Eric Anholt <eric@anholt.net> | 2009-08-27 16:53:50 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-08-27 17:51:29 -0700 |
commit | 60b072d49fd2a1b2bf59442ae7209379152b1500 (patch) | |
tree | f7e99174dcbdb283d57c15223aa4aed971033128 | |
parent | 812ccacabcc6af300cf476d7f82ecb75d4982cd6 (diff) |
intel: Add support for ARB_copy_buffer.
Passes glean's bufferObject test for this extension.
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_buffer_objects.c | 93 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_extensions.c | 2 |
2 files changed, 93 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index 9600557f2cc..a7403979439 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c | |||
@@ -28,9 +28,11 @@ | |||
28 | 28 | ||
29 | #include "main/imports.h" | 29 | #include "main/imports.h" |
30 | #include "main/mtypes.h" | 30 | #include "main/mtypes.h" |
31 | #include "main/macros.h" | ||
31 | #include "main/bufferobj.h" | 32 | #include "main/bufferobj.h" |
32 | 33 | ||
33 | #include "intel_context.h" | 34 | #include "intel_context.h" |
35 | #include "intel_blit.h" | ||
34 | #include "intel_buffer_objects.h" | 36 | #include "intel_buffer_objects.h" |
35 | #include "intel_batchbuffer.h" | 37 | #include "intel_batchbuffer.h" |
36 | #include "intel_regions.h" | 38 | #include "intel_regions.h" |
@@ -243,8 +245,10 @@ intel_bufferobj_map(GLcontext * ctx, | |||
243 | return obj->Pointer; | 245 | return obj->Pointer; |
244 | } | 246 | } |
245 | 247 | ||
246 | if (!read_only) | 248 | /* Flush any existing batchbuffer that might have written to this |
247 | intelFlush(ctx); | 249 | * buffer. |
250 | */ | ||
251 | intelFlush(ctx); | ||
248 | 252 | ||
249 | if (intel_obj->region) | 253 | if (intel_obj->region) |
250 | intel_bufferobj_cow(intel, intel_obj); | 254 | intel_bufferobj_cow(intel, intel_obj); |
@@ -325,6 +329,90 @@ intel_bufferobj_buffer(struct intel_context *intel, | |||
325 | return intel_obj->buffer; | 329 | return intel_obj->buffer; |
326 | } | 330 | } |
327 | 331 | ||
332 | static void | ||
333 | intel_bufferobj_copy_subdata(GLcontext *ctx, | ||
334 | struct gl_buffer_object *src, | ||
335 | struct gl_buffer_object *dst, | ||
336 | GLintptr read_offset, GLintptr write_offset, | ||
337 | GLsizeiptr size) | ||
338 | { | ||
339 | struct intel_context *intel = intel_context(ctx); | ||
340 | struct intel_buffer_object *intel_src = intel_buffer_object(src); | ||
341 | struct intel_buffer_object *intel_dst = intel_buffer_object(dst); | ||
342 | drm_intel_bo *src_bo, *dst_bo; | ||
343 | GLuint pitch, height; | ||
344 | |||
345 | if (size == 0) | ||
346 | return; | ||
347 | |||
348 | /* If we're in system memory, just map and memcpy. */ | ||
349 | if (intel_src->sys_buffer || intel_dst->sys_buffer) { | ||
350 | /* The same buffer may be used, but note that regions copied may | ||
351 | * not overlap. | ||
352 | */ | ||
353 | if (src == dst) { | ||
354 | char *ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER, | ||
355 | GL_READ_WRITE, dst); | ||
356 | memcpy(ptr + write_offset, ptr + read_offset, size); | ||
357 | intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst); | ||
358 | } else { | ||
359 | const char *src_ptr; | ||
360 | char *dst_ptr; | ||
361 | |||
362 | src_ptr = intel_bufferobj_map(ctx, GL_COPY_READ_BUFFER, | ||
363 | GL_READ_ONLY, src); | ||
364 | dst_ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER, | ||
365 | GL_WRITE_ONLY, dst); | ||
366 | |||
367 | memcpy(dst_ptr + write_offset, src_ptr + read_offset, size); | ||
368 | |||
369 | intel_bufferobj_unmap(ctx, GL_COPY_READ_BUFFER, src); | ||
370 | intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* Otherwise, we have real BOs, so blit them. We don't have a memmove-type | ||
375 | * blit like some other hardware, so we'll do a rectangular blit covering | ||
376 | * a large space, then emit a scanline blit at the end to cover the last | ||
377 | * if we need. | ||
378 | */ | ||
379 | |||
380 | dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART); | ||
381 | src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ); | ||
382 | |||
383 | /* The pitch is a signed value. */ | ||
384 | pitch = MIN2(size, (1 << 15) - 1); | ||
385 | height = size / pitch; | ||
386 | intelEmitCopyBlit(intel, 1, | ||
387 | pitch, src_bo, read_offset, I915_TILING_NONE, | ||
388 | pitch, dst_bo, write_offset, I915_TILING_NONE, | ||
389 | 0, 0, /* src x/y */ | ||
390 | 0, 0, /* dst x/y */ | ||
391 | pitch, height, /* w, h */ | ||
392 | GL_COPY); | ||
393 | |||
394 | read_offset += pitch * height; | ||
395 | write_offset += pitch * height; | ||
396 | size -= pitch * height; | ||
397 | assert (size < (1 << 15)); | ||
398 | if (size != 0) { | ||
399 | intelEmitCopyBlit(intel, 1, | ||
400 | size, src_bo, read_offset, I915_TILING_NONE, | ||
401 | size, dst_bo, write_offset, I915_TILING_NONE, | ||
402 | 0, 0, /* src x/y */ | ||
403 | 0, 0, /* dst x/y */ | ||
404 | size, 1, /* w, h */ | ||
405 | GL_COPY); | ||
406 | } | ||
407 | |||
408 | /* Since we've emitted some blits to buffers that will (likely) be used | ||
409 | * in rendering operations in other cache domains in this batch, emit a | ||
410 | * flush. Once again, we wish for a domain tracker in libdrm to cover | ||
411 | * usage inside of a batchbuffer. | ||
412 | */ | ||
413 | intel_batchbuffer_emit_mi_flush(intel->batch); | ||
414 | } | ||
415 | |||
328 | void | 416 | void |
329 | intelInitBufferObjectFuncs(struct dd_function_table *functions) | 417 | intelInitBufferObjectFuncs(struct dd_function_table *functions) |
330 | { | 418 | { |
@@ -335,4 +423,5 @@ intelInitBufferObjectFuncs(struct dd_function_table *functions) | |||
335 | functions->GetBufferSubData = intel_bufferobj_get_subdata; | 423 | functions->GetBufferSubData = intel_bufferobj_get_subdata; |
336 | functions->MapBuffer = intel_bufferobj_map; | 424 | functions->MapBuffer = intel_bufferobj_map; |
337 | functions->UnmapBuffer = intel_bufferobj_unmap; | 425 | functions->UnmapBuffer = intel_bufferobj_unmap; |
426 | functions->CopyBufferSubData = intel_bufferobj_copy_subdata; | ||
338 | } | 427 | } |
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index 9f90ef0a697..ff9ad5acced 100644 --- a/src/mesa/drivers/dri/intel/intel_extensions.c +++ b/src/mesa/drivers/dri/intel/intel_extensions.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "intel_extensions.h" | 30 | #include "intel_extensions.h" |
31 | 31 | ||
32 | 32 | ||
33 | #define need_GL_ARB_copy_buffer | ||
33 | #define need_GL_ARB_framebuffer_object | 34 | #define need_GL_ARB_framebuffer_object |
34 | #define need_GL_ARB_occlusion_query | 35 | #define need_GL_ARB_occlusion_query |
35 | #define need_GL_ARB_point_parameters | 36 | #define need_GL_ARB_point_parameters |
@@ -69,6 +70,7 @@ | |||
69 | * i965_dri. | 70 | * i965_dri. |
70 | */ | 71 | */ |
71 | static const struct dri_extension card_extensions[] = { | 72 | static const struct dri_extension card_extensions[] = { |
73 | { "GL_ARB_copy_buffer", GL_ARB_copy_buffer_functions }, | ||
72 | { "GL_ARB_half_float_pixel", NULL }, | 74 | { "GL_ARB_half_float_pixel", NULL }, |
73 | { "GL_ARB_multitexture", NULL }, | 75 | { "GL_ARB_multitexture", NULL }, |
74 | { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, | 76 | { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, |