From 6a49473ab5797b1e6ce021e396902f9cb77674ef Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 22 Jun 2009 10:54:50 -0700 Subject: intel: Remove long-unused intel_region_fill and intelEmitFillBlit. --- src/mesa/drivers/dri/intel/intel_blit.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/mesa/drivers/dri/intel/intel_blit.h') diff --git a/src/mesa/drivers/dri/intel/intel_blit.h b/src/mesa/drivers/dri/intel/intel_blit.h index 52065b13ed..2b4267ef6a 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.h +++ b/src/mesa/drivers/dri/intel/intel_blit.h @@ -50,15 +50,6 @@ extern void intelEmitCopyBlit(struct intel_context *intel, GLshort w, GLshort h, GLenum logicop ); -extern void intelEmitFillBlit(struct intel_context *intel, - GLuint cpp, - GLshort dst_pitch, - dri_bo *dst_buffer, - GLuint dst_offset, - uint32_t dst_tiling, - GLshort x, GLshort y, - GLshort w, GLshort h, GLuint color); - void intelEmitImmediateColorExpandBlit(struct intel_context *intel, GLuint cpp, -- cgit v1.2.3 From 8f81a6468fdbc7320800ea497791e3e1b8f782ca Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 22 Jun 2009 11:00:11 -0700 Subject: intel: Avoid trying to do blits to Y tiled regions. This is somewhat nasty, but we need to do Y-tiled depth for FBO support. May help with corruption and hangs since enabling texture tiling, and since switching depth textures to Y tiled. Fixes piglit depthtex.c on 965. --- src/mesa/drivers/dri/intel/intel_blit.c | 26 +++++++++++++---- src/mesa/drivers/dri/intel/intel_blit.h | 5 ++-- src/mesa/drivers/dri/intel/intel_mipmap_tree.c | 29 +++++++++++++----- src/mesa/drivers/dri/intel/intel_pixel_bitmap.c | 39 +++++++++++++------------ src/mesa/drivers/dri/intel/intel_pixel_copy.c | 16 ++++++---- src/mesa/drivers/dri/intel/intel_pixel_read.c | 23 ++++++++------- src/mesa/drivers/dri/intel/intel_regions.c | 30 +++++++++---------- src/mesa/drivers/dri/intel/intel_regions.h | 17 ++++++----- src/mesa/drivers/dri/intel/intel_tex_copy.c | 27 +++++++++-------- src/mesa/drivers/dri/intel/intel_tex_image.c | 15 ++++++---- 10 files changed, 137 insertions(+), 90 deletions(-) (limited to 'src/mesa/drivers/dri/intel/intel_blit.h') diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 698a0bf465..e0596a5531 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -108,6 +108,8 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; } + assert(src->tiling != I915_TILING_Y); + assert(dst->tiling != I915_TILING_Y); #ifndef I915 if (src->tiling != I915_TILING_NONE) { CMD |= XY_SRC_TILED; @@ -201,7 +203,7 @@ static GLuint translate_raster_op(GLenum logicop) /* Copy BitBlt */ -void +GLboolean intelEmitCopyBlit(struct intel_context *intel, GLuint cpp, GLshort src_pitch, @@ -223,6 +225,11 @@ intelEmitCopyBlit(struct intel_context *intel, dri_bo *aper_array[3]; BATCH_LOCALS; + if (dst_tiling == I915_TILING_Y) + return GL_FALSE; + if (src_tiling == I915_TILING_Y) + return GL_FALSE; + /* do space/cliprects check before going any further */ do { aper_array[0] = intel->batch->buf; @@ -260,7 +267,7 @@ intelEmitCopyBlit(struct intel_context *intel, if (locked) UNLOCK_HARDWARE(intel); - return; + return GL_TRUE; } intel_batchbuffer_require_space(intel->batch, 8 * 4, NO_LOOP_CLIPRECTS); @@ -287,7 +294,7 @@ intelEmitCopyBlit(struct intel_context *intel, CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; break; default: - return; + return GL_FALSE; } #ifndef I915 @@ -302,7 +309,7 @@ intelEmitCopyBlit(struct intel_context *intel, #endif if (dst_y2 <= dst_y || dst_x2 <= dst_x) { - return; + return GL_TRUE; } assert(dst_x < dst_x2); @@ -324,6 +331,8 @@ intelEmitCopyBlit(struct intel_context *intel, ADVANCE_BATCH(); intel_batchbuffer_emit_mi_flush(intel->batch); + + return GL_TRUE; } @@ -536,7 +545,7 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask) UNLOCK_HARDWARE(intel); } -void +GLboolean intelEmitImmediateColorExpandBlit(struct intel_context *intel, GLuint cpp, GLubyte *src_bits, GLuint src_size, @@ -552,11 +561,14 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, int dwords = ALIGN(src_size, 8) / 4; uint32_t opcode, br13, blit_cmd; + if (dst_tiling == I915_TILING_Y) + return GL_FALSE; + assert( logic_op - GL_CLEAR >= 0 ); assert( logic_op - GL_CLEAR < 0x10 ); if (w < 0 || h < 0) - return; + return GL_TRUE; dst_pitch *= cpp; @@ -613,4 +625,6 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, REFERENCES_CLIPRECTS ); intel_batchbuffer_emit_mi_flush(intel->batch); + + return GL_TRUE; } diff --git a/src/mesa/drivers/dri/intel/intel_blit.h b/src/mesa/drivers/dri/intel/intel_blit.h index 2b4267ef6a..152fa3f17b 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.h +++ b/src/mesa/drivers/dri/intel/intel_blit.h @@ -35,7 +35,8 @@ extern void intelCopyBuffer(const __DRIdrawablePrivate * dpriv, extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask); -extern void intelEmitCopyBlit(struct intel_context *intel, +GLboolean +intelEmitCopyBlit(struct intel_context *intel, GLuint cpp, GLshort src_pitch, dri_bo *src_buffer, @@ -50,7 +51,7 @@ extern void intelEmitCopyBlit(struct intel_context *intel, GLshort w, GLshort h, GLenum logicop ); -void +GLboolean intelEmitImmediateColorExpandBlit(struct intel_context *intel, GLuint cpp, GLubyte *src_bits, GLuint src_size, diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index fadcc89b3e..660d7e5350 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -498,6 +498,7 @@ intel_miptree_image_copy(struct intel_context *intel, const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level); const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level); GLuint i; + GLboolean success; if (dst->compressed) { GLuint alignment = intel_compressed_alignment(dst->internal_format); @@ -506,12 +507,26 @@ intel_miptree_image_copy(struct intel_context *intel, } for (i = 0; i < depth; i++) { - intel_region_copy(intel, - dst->region, dst_offset + dst_depth_offset[i], - 0, - 0, - src->region, src_offset + src_depth_offset[i], - 0, 0, width, height, GL_COPY); + success = intel_region_copy(intel, + dst->region, dst_offset + dst_depth_offset[i], + 0, 0, + src->region, src_offset + src_depth_offset[i], + 0, 0, width, height, GL_COPY); + if (!success) { + GLubyte *src_ptr, *dst_ptr; + + src_ptr = intel_region_map(intel, src->region); + dst_ptr = intel_region_map(intel, dst->region); + + _mesa_copy_rect(dst_ptr + dst_offset + dst_depth_offset[i], + dst->cpp, + dst->pitch, + 0, 0, width, height, + src_ptr + src_offset + src_depth_offset[i], + src->pitch, + 0, 0); + intel_region_unmap(intel, src->region); + intel_region_unmap(intel, dst->region); + } } - } diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c index 191d9b0846..e678cd2c26 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c @@ -194,7 +194,7 @@ do_blit_bitmap( GLcontext *ctx, struct gl_framebuffer *fb = ctx->DrawBuffer; GLfloat tmpColor[4]; GLubyte ubcolor[4]; - GLuint color8888, color565; + GLuint color; unsigned int num_cliprects; drm_clip_rect_t *cliprects; int x_off, y_off; @@ -232,8 +232,11 @@ do_blit_bitmap( GLcontext *ctx, UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]); - color8888 = INTEL_PACKCOLOR8888(ubcolor[0], ubcolor[1], ubcolor[2], ubcolor[3]); - color565 = INTEL_PACKCOLOR565(ubcolor[0], ubcolor[1], ubcolor[2]); + if (dst->cpp == 2) + color = INTEL_PACKCOLOR565(ubcolor[0], ubcolor[1], ubcolor[2]); + else + color = INTEL_PACKCOLOR8888(ubcolor[0], ubcolor[1], + ubcolor[2], ubcolor[3]); if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) return GL_FALSE; @@ -307,21 +310,21 @@ do_blit_bitmap( GLcontext *ctx, fb->Name == 0 ? GL_TRUE : GL_FALSE) == 0) continue; - /* - */ - intelEmitImmediateColorExpandBlit( intel, - dst->cpp, - (GLubyte *)stipple, - sz, - (dst->cpp == 2) ? color565 : color8888, - dst->pitch, - dst->buffer, - 0, - dst->tiling, - box_x + px, - box_y + py, - w, h, - logic_op); + if (!intelEmitImmediateColorExpandBlit(intel, + dst->cpp, + (GLubyte *)stipple, + sz, + color, + dst->pitch, + dst->buffer, + 0, + dst->tiling, + box_x + px, + box_y + py, + w, h, + logic_op)) { + return GL_FALSE; + } } } } diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c index 1a3e363846..f523d3eead 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c @@ -362,12 +362,16 @@ do_blit_copypixels(GLcontext * ctx, &clip_x, &clip_y, &clip_w, &clip_h)) continue; - intel_region_copy(intel, - dst, 0, clip_x, clip_y, - src, 0, clip_x + delta_x, clip_y + delta_y, - clip_w, clip_h, - ctx->Color.ColorLogicOpEnabled ? - ctx->Color.LogicOp : GL_COPY); + if (!intel_region_copy(intel, + dst, 0, clip_x, clip_y, + src, 0, clip_x + delta_x, clip_y + delta_y, + clip_w, clip_h, + ctx->Color.ColorLogicOpEnabled ? + ctx->Color.LogicOp : GL_COPY)) { + DBG("%s: blit failure\n", __FUNCTION__); + UNLOCK_HARDWARE(intel); + return GL_FALSE; + } } } out: diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c index 74da6d39a2..8713463ace 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_read.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c @@ -261,16 +261,19 @@ do_blit_readpixels(GLcontext * ctx, if (!intel_intersect_cliprects(&rect, &src_rect, &box[i])) continue; - intelEmitCopyBlit(intel, - src->cpp, - src->pitch, src->buffer, 0, src->tiling, - rowLength, dst_buffer, dst_offset, GL_FALSE, - rect.x1, - rect.y1, - rect.x1 - src_rect.x1, - rect.y2 - src_rect.y2, - rect.x2 - rect.x1, rect.y2 - rect.y1, - GL_COPY); + if (!intelEmitCopyBlit(intel, + src->cpp, + src->pitch, src->buffer, 0, src->tiling, + rowLength, dst_buffer, dst_offset, GL_FALSE, + rect.x1, + rect.y1, + rect.x1 - src_rect.x1, + rect.y2 - src_rect.y2, + rect.x2 - rect.x1, rect.y2 - rect.y1, + GL_COPY)) { + UNLOCK_HARDWARE(intel); + return GL_FALSE; + } } } UNLOCK_HARDWARE(intel); diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index 98109235b7..4ce7f12e40 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -360,7 +360,7 @@ intel_region_data(struct intel_context *intel, /* Copy rectangular sub-regions. Need better logic about when to * push buffers into AGP - will currently do so whenever possible. */ -void +GLboolean intel_region_copy(struct intel_context *intel, struct intel_region *dst, GLuint dst_offset, @@ -373,7 +373,7 @@ intel_region_copy(struct intel_context *intel, _DBG("%s\n", __FUNCTION__); if (intel == NULL) - return; + return GL_FALSE; if (dst->pbo) { if (dstx == 0 && @@ -385,12 +385,12 @@ intel_region_copy(struct intel_context *intel, assert(src->cpp == dst->cpp); - intelEmitCopyBlit(intel, - dst->cpp, - src->pitch, src->buffer, src_offset, src->tiling, - dst->pitch, dst->buffer, dst_offset, dst->tiling, - srcx, srcy, dstx, dsty, width, height, - logicop); + return intelEmitCopyBlit(intel, + dst->cpp, + src->pitch, src->buffer, src_offset, src->tiling, + dst->pitch, dst->buffer, dst_offset, dst->tiling, + srcx, srcy, dstx, dsty, width, height, + logicop); } /* Attach to a pbo, discarding our data. Effectively zero-copy upload @@ -477,13 +477,13 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region) if (!was_locked) LOCK_HARDWARE(intel); - intelEmitCopyBlit(intel, - region->cpp, - region->pitch, pbo->buffer, 0, region->tiling, - region->pitch, region->buffer, 0, region->tiling, - 0, 0, 0, 0, - region->pitch, region->height, - GL_COPY); + assert(intelEmitCopyBlit(intel, + region->cpp, + region->pitch, pbo->buffer, 0, region->tiling, + region->pitch, region->buffer, 0, region->tiling, + 0, 0, 0, 0, + region->pitch, region->height, + GL_COPY)); if (!was_locked) UNLOCK_HARDWARE(intel); diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h index c2d4810df2..0d379bdc6e 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.h +++ b/src/mesa/drivers/dri/intel/intel_regions.h @@ -110,14 +110,15 @@ void intel_region_data(struct intel_context *intel, /* Copy rectangular sub-regions */ -void intel_region_copy(struct intel_context *intel, - struct intel_region *dest, - GLuint dest_offset, - GLuint destx, GLuint desty, - struct intel_region *src, - GLuint src_offset, - GLuint srcx, GLuint srcy, GLuint width, GLuint height, - GLenum logicop); +GLboolean +intel_region_copy(struct intel_context *intel, + struct intel_region *dest, + GLuint dest_offset, + GLuint destx, GLuint desty, + struct intel_region *src, + GLuint src_offset, + GLuint srcx, GLuint srcy, GLuint width, GLuint height, + GLenum logicop); /* Helpers for zerocopy uploads, particularly texture image uploads: */ diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index e1820e3fcf..0335c13307 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -147,18 +147,21 @@ do_copy_texsubimage(struct intel_context *intel, src_pitch = src->pitch; } - intelEmitCopyBlit(intel, - intelImage->mt->cpp, - src_pitch, - src->buffer, - 0, - src->tiling, - intelImage->mt->pitch, - dst_bo, - image_offset, - intelImage->mt->region->tiling, - x, y, dstx, dsty, width, height, - GL_COPY); + if (!intelEmitCopyBlit(intel, + intelImage->mt->cpp, + src_pitch, + src->buffer, + 0, + src->tiling, + intelImage->mt->pitch, + dst_bo, + image_offset, + intelImage->mt->region->tiling, + x, y, dstx, dsty, width, height, + GL_COPY)) { + UNLOCK_HARDWARE(intel); + return GL_FALSE; + } } UNLOCK_HARDWARE(intel); diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 03311e58aa..ab9541359d 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -235,12 +235,15 @@ try_pbo_upload(struct intel_context *intel, INTEL_WRITE_FULL); - intelEmitCopyBlit(intel, - intelImage->mt->cpp, - src_stride, src_buffer, src_offset, GL_FALSE, - dst_stride, dst_buffer, dst_offset, GL_FALSE, - 0, 0, 0, 0, width, height, - GL_COPY); + if (!intelEmitCopyBlit(intel, + intelImage->mt->cpp, + src_stride, src_buffer, src_offset, GL_FALSE, + dst_stride, dst_buffer, dst_offset, GL_FALSE, + 0, 0, 0, 0, width, height, + GL_COPY)) { + UNLOCK_HARDWARE(intel); + return GL_FALSE; + } } UNLOCK_HARDWARE(intel); -- cgit v1.2.3 From 2d5c74fac3cc0f9d45a9e11b2fcdea1bc67928c4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 26 Aug 2009 18:08:52 -0700 Subject: intel: Add support for GL_ARB_map_buffer_range. Passes glean's bufferObject test, and should provide good performance in the cases applications are expected to use. --- src/mesa/drivers/dri/intel/intel_blit.c | 40 +++++ src/mesa/drivers/dri/intel/intel_blit.h | 6 + src/mesa/drivers/dri/intel/intel_buffer_objects.c | 171 +++++++++++++++++----- src/mesa/drivers/dri/intel/intel_buffer_objects.h | 5 + src/mesa/drivers/dri/intel/intel_extensions.c | 2 + 5 files changed, 189 insertions(+), 35 deletions(-) (limited to 'src/mesa/drivers/dri/intel/intel_blit.h') diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 979f202584..0c5be4c798 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -636,3 +636,43 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, return GL_TRUE; } + +/* We don't have a memmove-type blit like some other hardware, so we'll do a + * rectangular blit covering a large space, then emit 1-scanline blit at the + * end to cover the last if we need. + */ +void +intel_emit_linear_blit(struct intel_context *intel, + drm_intel_bo *dst_bo, + unsigned int dst_offset, + drm_intel_bo *src_bo, + unsigned int src_offset, + unsigned int size) +{ + GLuint pitch, height; + + /* The pitch is a signed value. */ + pitch = MIN2(size, (1 << 15) - 1); + height = size / pitch; + intelEmitCopyBlit(intel, 1, + pitch, src_bo, src_offset, I915_TILING_NONE, + pitch, dst_bo, dst_offset, I915_TILING_NONE, + 0, 0, /* src x/y */ + 0, 0, /* dst x/y */ + pitch, height, /* w, h */ + GL_COPY); + + src_offset += pitch * height; + dst_offset += pitch * height; + size -= pitch * height; + assert (size < (1 << 15)); + if (size != 0) { + intelEmitCopyBlit(intel, 1, + size, src_bo, src_offset, I915_TILING_NONE, + size, dst_bo, dst_offset, I915_TILING_NONE, + 0, 0, /* src x/y */ + 0, 0, /* dst x/y */ + size, 1, /* w, h */ + GL_COPY); + } +} diff --git a/src/mesa/drivers/dri/intel/intel_blit.h b/src/mesa/drivers/dri/intel/intel_blit.h index 152fa3f17b..240cb7cd1b 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.h +++ b/src/mesa/drivers/dri/intel/intel_blit.h @@ -63,5 +63,11 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, GLshort x, GLshort y, GLshort w, GLshort h, GLenum logic_op); +void intel_emit_linear_blit(struct intel_context *intel, + drm_intel_bo *dst_bo, + unsigned int dst_offset, + drm_intel_bo *src_bo, + unsigned int src_offset, + unsigned int size); #endif diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index a740397943..3cf0ea0991 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c @@ -270,29 +270,155 @@ intel_bufferobj_map(GLcontext * ctx, return obj->Pointer; } +/** + * Called via glMapBufferRange(). + * + * The goal of this extension is to allow apps to accumulate their rendering + * at the same time as they accumulate their buffer object. Without it, + * you'd end up blocking on execution of rendering every time you mapped + * the buffer to put new data in. + * + * We support it in 3 ways: If unsynchronized, then don't bother + * flushing the batchbuffer before mapping the buffer, which can save blocking + * in many cases. If we would still block, and they allow the whole buffer + * to be invalidated, then just allocate a new buffer to replace the old one. + * If not, and we'd block, and they allow the subrange of the buffer to be + * invalidated, then we can make a new little BO, let them write into that, + * and blit it into the real BO at unmap time. + */ +static void * +intel_bufferobj_map_range(GLcontext * ctx, + GLenum target, GLsizei offset, GLsizeiptr length, + GLbitfield access, struct gl_buffer_object *obj) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_buffer_object *intel_obj = intel_buffer_object(obj); + + assert(intel_obj); + + if (intel_obj->sys_buffer) { + obj->Pointer = intel_obj->sys_buffer + offset; + return obj->Pointer; + } + + if (intel_obj->region) + intel_bufferobj_cow(intel, intel_obj); + + /* If the mapping is synchronized with other GL operations, flush + * the batchbuffer so that GEM knows about the buffer access for later + * syncing. + */ + if ((access & GL_MAP_WRITE_BIT) && !(access & GL_MAP_UNSYNCHRONIZED_BIT)) + intelFlush(ctx); + + /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also + * internally uses our functions directly. + */ + obj->Offset = offset; + obj->Length = length; + obj->AccessFlags = access; + + if (intel_obj->buffer == NULL) { + obj->Pointer = NULL; + return NULL; + } + + /* If the user doesn't care about existing buffer contents and mapping + * would cause us to block, then throw out the old buffer. + */ + if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) && + (access & GL_MAP_INVALIDATE_BUFFER_BIT) && + drm_intel_bo_busy(intel_obj->buffer)) { + drm_intel_bo_unreference(intel_obj->buffer); + intel_obj->buffer = dri_bo_alloc(intel->bufmgr, "bufferobj", + intel_obj->Base.Size, 64); + } + + /* If the user is mapping a range of an active buffer object but + * doesn't require the current contents of that range, make a new + * BO, and we'll copy what they put in there out at unmap or + * FlushRange time. + */ + if ((access & GL_MAP_INVALIDATE_RANGE_BIT) && + drm_intel_bo_busy(intel_obj->buffer)) { + intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr, + "range map", + length, 64); + if (!(access & GL_MAP_READ_BIT) && + intel->intelScreen->kernel_exec_fencing) { + drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo); + intel_obj->mapped_gtt = GL_TRUE; + } else { + drm_intel_bo_map(intel_obj->range_map_bo, + (access & GL_MAP_WRITE_BIT) != 0); + intel_obj->mapped_gtt = GL_FALSE; + } + obj->Pointer = intel_obj->range_map_bo->virtual; + return obj->Pointer; + } + + if (!(access & GL_MAP_READ_BIT) && + intel->intelScreen->kernel_exec_fencing) { + drm_intel_gem_bo_map_gtt(intel_obj->buffer); + intel_obj->mapped_gtt = GL_TRUE; + } else { + drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0); + intel_obj->mapped_gtt = GL_FALSE; + } + + obj->Pointer = intel_obj->buffer->virtual + offset; + return obj->Pointer; +} + /** - * Called via glMapBufferARB(). + * Called via glUnmapBuffer(). */ static GLboolean intel_bufferobj_unmap(GLcontext * ctx, GLenum target, struct gl_buffer_object *obj) { + struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); assert(intel_obj); + assert(obj->Pointer); if (intel_obj->sys_buffer != NULL) { - assert(obj->Pointer); - obj->Pointer = NULL; + /* always keep the mapping around. */ + } else if (intel_obj->range_map_bo != NULL) { + if (intel_obj->mapped_gtt) { + drm_intel_gem_bo_unmap_gtt(intel_obj->range_map_bo); + } else { + drm_intel_bo_unmap(intel_obj->range_map_bo); + } + + /* We ignore the FLUSH_EXPLICIT bit and the calls associated with it. + * It would be a small win to support that, but for now we just copy + * the whole mapped range into place. + */ + intel_emit_linear_blit(intel, + intel_obj->buffer, obj->Offset, + intel_obj->range_map_bo, 0, + obj->Length); + + /* Since we've emitted some blits to buffers that will (likely) be used + * in rendering operations in other cache domains in this batch, emit a + * flush. Once again, we wish for a domain tracker in libdrm to cover + * usage inside of a batchbuffer. + */ + intel_batchbuffer_emit_mi_flush(intel->batch); + + drm_intel_bo_unreference(intel_obj->range_map_bo); + intel_obj->range_map_bo = NULL; } else if (intel_obj->buffer != NULL) { - assert(obj->Pointer); if (intel_obj->mapped_gtt) { drm_intel_gem_bo_unmap_gtt(intel_obj->buffer); } else { drm_intel_bo_unmap(intel_obj->buffer); } - obj->Pointer = NULL; } + obj->Pointer = NULL; + return GL_TRUE; } @@ -340,7 +466,6 @@ intel_bufferobj_copy_subdata(GLcontext *ctx, struct intel_buffer_object *intel_src = intel_buffer_object(src); struct intel_buffer_object *intel_dst = intel_buffer_object(dst); drm_intel_bo *src_bo, *dst_bo; - GLuint pitch, height; if (size == 0) return; @@ -371,39 +496,14 @@ intel_bufferobj_copy_subdata(GLcontext *ctx, } } - /* Otherwise, we have real BOs, so blit them. We don't have a memmove-type - * blit like some other hardware, so we'll do a rectangular blit covering - * a large space, then emit a scanline blit at the end to cover the last - * if we need. - */ + /* Otherwise, we have real BOs, so blit them. */ dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART); src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ); - /* The pitch is a signed value. */ - pitch = MIN2(size, (1 << 15) - 1); - height = size / pitch; - intelEmitCopyBlit(intel, 1, - pitch, src_bo, read_offset, I915_TILING_NONE, - pitch, dst_bo, write_offset, I915_TILING_NONE, - 0, 0, /* src x/y */ - 0, 0, /* dst x/y */ - pitch, height, /* w, h */ - GL_COPY); - - read_offset += pitch * height; - write_offset += pitch * height; - size -= pitch * height; - assert (size < (1 << 15)); - if (size != 0) { - intelEmitCopyBlit(intel, 1, - size, src_bo, read_offset, I915_TILING_NONE, - size, dst_bo, write_offset, I915_TILING_NONE, - 0, 0, /* src x/y */ - 0, 0, /* dst x/y */ - size, 1, /* w, h */ - GL_COPY); - } + intel_emit_linear_blit(intel, + dst_bo, write_offset, + src_bo, read_offset, size); /* Since we've emitted some blits to buffers that will (likely) be used * in rendering operations in other cache domains in this batch, emit a @@ -422,6 +522,7 @@ intelInitBufferObjectFuncs(struct dd_function_table *functions) functions->BufferSubData = intel_bufferobj_subdata; functions->GetBufferSubData = intel_bufferobj_get_subdata; functions->MapBuffer = intel_bufferobj_map; + functions->MapBufferRange = intel_bufferobj_map_range; functions->UnmapBuffer = intel_bufferobj_unmap; functions->CopyBufferSubData = intel_bufferobj_copy_subdata; } diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h index 8164407f07..06a8ab9824 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h @@ -48,6 +48,11 @@ struct intel_buffer_object struct intel_region *region; /* Is there a zero-copy texture associated with this (pixel) buffer object? */ + + drm_intel_bo *range_map_bo; + unsigned int range_map_offset; + GLsizei range_map_size; + GLboolean mapped_gtt; }; diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index ff9ad5acce..7aee70f0a8 100644 --- a/src/mesa/drivers/dri/intel/intel_extensions.c +++ b/src/mesa/drivers/dri/intel/intel_extensions.c @@ -32,6 +32,7 @@ #define need_GL_ARB_copy_buffer #define need_GL_ARB_framebuffer_object +#define need_GL_ARB_map_buffer_range #define need_GL_ARB_occlusion_query #define need_GL_ARB_point_parameters #define need_GL_ARB_shader_objects @@ -72,6 +73,7 @@ static const struct dri_extension card_extensions[] = { { "GL_ARB_copy_buffer", GL_ARB_copy_buffer_functions }, { "GL_ARB_half_float_pixel", NULL }, + { "GL_ARB_map_buffer_range", GL_ARB_map_buffer_range_functions }, { "GL_ARB_multitexture", NULL }, { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, { "GL_ARB_point_sprite", NULL }, -- cgit v1.2.3