示例#1
0
/**
 * Replace data in a subrange of buffer object.  If the data range
 * specified by size + offset extends beyond the end of the buffer or
 * if data is NULL, no copy is performed.
 * Called via glBufferSubDataARB().
 */
static void
intel_bufferobj_subdata(struct gl_context * ctx,
                        GLintptrARB offset,
                        GLsizeiptrARB size,
                        const GLvoid * data, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
   bool busy;

   if (size == 0)
      return;

   assert(intel_obj);

   /* If we have a single copy in system memory, update that */
   if (intel_obj->sys_buffer) {
      if (intel_obj->source)
	 release_buffer(intel_obj);

      if (intel_obj->buffer == NULL) {
	 memcpy((char *)intel_obj->sys_buffer + offset, data, size);
	 return;
      }

      free(intel_obj->sys_buffer);
      intel_obj->sys_buffer = NULL;
   }

   /* Otherwise we need to update the copy in video memory. */
   busy =
      drm_intel_bo_busy(intel_obj->buffer) ||
      drm_intel_bo_references(intel->batch.bo, intel_obj->buffer);

   if (busy) {
      if (size == intel_obj->Base.Size) {
	 /* Replace the current busy bo with fresh data. */
	 drm_intel_bo_unreference(intel_obj->buffer);
	 intel_bufferobj_alloc_buffer(intel, intel_obj);
	 drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
      } else {
         perf_debug("Using a blit copy to avoid stalling on %ldb "
                    "glBufferSubData() to a busy buffer object.\n",
                    (long)size);
	 drm_intel_bo *temp_bo =
	    drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);

	 drm_intel_bo_subdata(temp_bo, 0, size, data);

	 intel_emit_linear_blit(intel,
				intel_obj->buffer, offset,
				temp_bo, 0,
				size);

	 drm_intel_bo_unreference(temp_bo);
      }
   } else {
      drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
   }
}
示例#2
0
/**
 * The BufferData() driver hook.
 *
 * Implements glBufferData(), which recreates a buffer object's data store
 * and populates it with the given data, if present.
 *
 * Any data that was previously stored in the buffer object is lost.
 *
 * \return true for success, false if out of memory
 */
static GLboolean
intel_bufferobj_data(struct gl_context * ctx,
                     GLenum target,
                     GLsizeiptrARB size,
                     const GLvoid * data,
                     GLenum usage, struct gl_buffer_object *obj)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);

   /* Part of the ABI, but this function doesn't use it.
    */
   (void) target;

   intel_obj->Base.Size = size;
   intel_obj->Base.Usage = usage;

   assert(!obj->Pointer); /* Mesa should have unmapped it */

   if (intel_obj->buffer != NULL)
      release_buffer(intel_obj);

   if (size != 0) {
      intel_bufferobj_alloc_buffer(brw, intel_obj);
      if (!intel_obj->buffer)
         return false;

      if (data != NULL)
	 drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
   }

   return true;
}
/* Ideally we'd use a BO to avoid taking up cache space for the temporary
 * data, but FlushMappedBufferRange may be followed by further writes to
 * the pointer, so we would have to re-map after emitting our blit, which
 * would defeat the point.
 */
static void
intel_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target,
				   GLintptr offset, GLsizeiptr length,
				   struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
   drm_intel_bo *temp_bo;

   /* Unless we're in the range map using a temporary system buffer,
    * there's no work to do.
    */
   if (intel_obj->range_map_buffer == NULL)
      return;

   temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64);

   drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer);

   intel_emit_linear_blit(intel,
			  intel_obj->buffer, obj->Offset + offset,
			  temp_bo, 0,
			  length);

   drm_intel_bo_unreference(temp_bo);
}
示例#4
0
drm_intel_bo *
intel_bufferobj_buffer(struct intel_context *intel,
                       struct intel_buffer_object *intel_obj,
		       GLuint flag)
{
   if (intel_obj->region) {
      if (flag == INTEL_WRITE_PART)
         intel_bufferobj_cow(intel, intel_obj);
      else if (flag == INTEL_WRITE_FULL) {
         intel_bufferobj_release_region(intel, intel_obj);
	 intel_bufferobj_alloc_buffer(intel, intel_obj);
      }
   }

   if (intel_obj->source)
      release_buffer(intel_obj);

   if (intel_obj->buffer == NULL) {
      intel_bufferobj_alloc_buffer(intel, intel_obj);
      drm_intel_bo_subdata(intel_obj->buffer,
			   0, intel_obj->Base.Size,
			   intel_obj->sys_buffer);

      free(intel_obj->sys_buffer);
      intel_obj->sys_buffer = NULL;
      intel_obj->offset = 0;
   }

   return intel_obj->buffer;
}
示例#5
0
void *intel_upload_map(struct intel_context *intel, GLuint size, GLuint align)
{
   GLuint base, delta;
   char *ptr;

   base = (intel->upload.offset + align - 1) / align * align;
   if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) {
      wrap_buffers(intel, size);
      base = 0;
   }

   delta = base - intel->upload.offset;
   if (intel->upload.buffer_len &&
       intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer))
   {
      drm_intel_bo_subdata(intel->upload.bo,
			   intel->upload.buffer_offset,
			   intel->upload.buffer_len,
			   intel->upload.buffer);
      intel->upload.buffer_len = 0;
   }

   if (size <= sizeof(intel->upload.buffer)) {
      if (intel->upload.buffer_len == 0)
	 intel->upload.buffer_offset = base;
      else
	 intel->upload.buffer_len += delta;

      ptr = intel->upload.buffer + intel->upload.buffer_len;
      intel->upload.buffer_len += size;
   } else
      ptr = malloc(size);

   return ptr;
}
static int
batch_flush(struct intel_info *info)
{
	int size, ret;

	batch_dword(info, MI_BATCH_BUFFER_END);
	size = batch_count(info);
	if (size & 1) {
		batch_dword(info, MI_NOOP);
		size = batch_count(info);
	}

	size *= sizeof(info->batch[0]);
	ret = drm_intel_bo_subdata(info->batch_ibo, 0, size, info->batch);
	if (ret) {
		ALOGE("failed to subdata batch");
		goto fail;
	}
	ret = drm_intel_bo_mrb_exec(info->batch_ibo, size,
		NULL, 0, 0, info->exec_blt);
	if (ret) {
		ALOGE("failed to exec batch");
		goto fail;
	}

	return batch_next(info);

fail:
	info->cur = info->batch;

	return ret;
}
示例#7
0
void intel_upload_data(struct intel_context *intel,
		       const void *ptr, GLuint size, GLuint align,
		       drm_intel_bo **return_bo,
		       GLuint *return_offset)
{
   GLuint base, delta;

   base = (intel->upload.offset + align - 1) / align * align;
   if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) {
      wrap_buffers(intel, size);
      base = 0;
   }

   drm_intel_bo_reference(intel->upload.bo);
   *return_bo = intel->upload.bo;
   *return_offset = base;

   delta = base - intel->upload.offset;
   if (intel->upload.buffer_len &&
       intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer))
   {
      drm_intel_bo_subdata(intel->upload.bo,
			   intel->upload.buffer_offset,
			   intel->upload.buffer_len,
			   intel->upload.buffer);
      intel->upload.buffer_len = 0;
   }

   if (size < sizeof(intel->upload.buffer))
   {
      if (intel->upload.buffer_len == 0)
	 intel->upload.buffer_offset = base;
      else
	 intel->upload.buffer_len += delta;

      memcpy(intel->upload.buffer + intel->upload.buffer_len, ptr, size);
      intel->upload.buffer_len += size;
   }
   else
   {
      drm_intel_bo_subdata(intel->upload.bo, base, size, ptr);
   }

   intel->upload.offset = base + size;
}
示例#8
0
void
intel_upload_data(struct brw_context *brw,
                  const void *ptr, GLuint size, GLuint align,
                  drm_intel_bo **return_bo,
                  GLuint *return_offset)
{
   GLuint base, delta;

   base = (brw->upload.offset + align - 1) / align * align;
   if (brw->upload.bo == NULL || base + size > brw->upload.bo->size) {
      wrap_buffers(brw, size);
      base = 0;
   }

   drm_intel_bo_reference(brw->upload.bo);
   *return_bo = brw->upload.bo;
   *return_offset = base;

   delta = base - brw->upload.offset;
   if (brw->upload.buffer_len &&
       brw->upload.buffer_len + delta + size > sizeof(brw->upload.buffer)) {
      drm_intel_bo_subdata(brw->upload.bo,
                           brw->upload.buffer_offset,
                           brw->upload.buffer_len,
                           brw->upload.buffer);
      brw->upload.buffer_len = 0;
   }

   if (size < sizeof(brw->upload.buffer)) {
      if (brw->upload.buffer_len == 0)
         brw->upload.buffer_offset = base;
      else
         brw->upload.buffer_len += delta;

      memcpy(brw->upload.buffer + brw->upload.buffer_len, ptr, size);
      brw->upload.buffer_len += size;
   } else {
      drm_intel_bo_subdata(brw->upload.bo, base, size, ptr);
   }

   brw->upload.offset = base + size;
}
static void
gen6_render_flush(struct intel_batchbuffer *batch, uint32_t batch_end)
{
	int ret;

	ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer);
	if (ret == 0)
		ret = drm_intel_bo_mrb_exec(batch->bo, batch_end,
					    NULL, 0, 0, 0);
	assert(ret == 0);
}
static void *work(void *arg)
{
	struct intel_batchbuffer *batch;
	render_copyfunc_t rendercopy = get_render_copyfunc(devid);
	drm_intel_context *context;
	drm_intel_bufmgr *bufmgr;
	int thread_id = *(int *)arg;
	int td_fd;
	int i;

	if (multiple_fds)
		td_fd = fd = drm_open_any();
	else
		td_fd = fd;

	assert(td_fd >= 0);

	bufmgr = drm_intel_bufmgr_gem_init(td_fd, 4096);
	batch = intel_batchbuffer_alloc(bufmgr, devid);
	context = drm_intel_gem_context_create(bufmgr);

	if (!context) {
		returns[thread_id] = 77;
		goto out;
	}

	for (i = 0; i < iter; i++) {
		struct scratch_buf src, dst;

		init_buffer(bufmgr, &src, 4096);
		init_buffer(bufmgr, &dst, 4096);


		if (uncontexted) {
			assert(rendercopy);
			rendercopy(batch, &src, 0, 0, 0, 0, &dst, 0, 0);
		} else {
			int ret;
			ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer);
			assert(ret == 0);
			intel_batchbuffer_flush_with_context(batch, context);
		}
	}

out:
	drm_intel_gem_context_destroy(context);
	intel_batchbuffer_free(batch);
	drm_intel_bufmgr_destroy(bufmgr);

	if (multiple_fds)
		close(td_fd);

	pthread_exit(&returns[thread_id]);
}
示例#11
0
/**
 * Allocate space for and store data in a buffer object.  Any data that was
 * previously stored in the buffer object is lost.  If data is NULL,
 * memory will be allocated, but no copy will occur.
 * Called via ctx->Driver.BufferData().
 * \return true for success, false if out of memory
 */
static GLboolean
intel_bufferobj_data(struct gl_context * ctx,
                     GLenum target,
                     GLsizeiptrARB size,
                     const GLvoid * data,
                     GLenum usage, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);

   /* Part of the ABI, but this function doesn't use it.
    */
#ifndef I915
   (void) target;
#endif

   intel_obj->Base.Size = size;
   intel_obj->Base.Usage = usage;

   assert(!obj->Pointer); /* Mesa should have unmapped it */

   if (intel_obj->buffer != NULL)
      release_buffer(intel_obj);

   free(intel_obj->sys_buffer);
   intel_obj->sys_buffer = NULL;

   if (size != 0) {
      if (usage == GL_DYNAMIC_DRAW
#ifdef I915
	  /* On pre-965, stick VBOs in system memory, as we're always doing
	   * swtnl with their contents anyway.
	   */
	  || target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER
#endif
	 )
      {
	 intel_obj->sys_buffer = malloc(size);
	 if (intel_obj->sys_buffer != NULL) {
	    if (data != NULL)
	       memcpy(intel_obj->sys_buffer, data, size);
	    return true;
	 }
      }
      intel_bufferobj_alloc_buffer(intel, intel_obj);
      if (!intel_obj->buffer)
         return false;

      if (data != NULL)
	 drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
   }

   return true;
}
示例#12
0
static int
i915_drm_buffer_write(struct i915_winsys *iws,
                       struct i915_winsys_buffer *buffer,
                       size_t offset,
                       size_t size,
                       const void *data)
{
   struct i915_drm_buffer *buf = i915_drm_buffer(buffer);

   return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
}
/**
 * Replace data in a subrange of buffer object.  If the data range
 * specified by size + offset extends beyond the end of the buffer or
 * if data is NULL, no copy is performed.
 * Called via glBufferSubDataARB().
 */
static void
intel_bufferobj_subdata(GLcontext * ctx,
                        GLenum target,
                        GLintptrARB offset,
                        GLsizeiptrARB size,
                        const GLvoid * data, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);

   if (size == 0)
      return;

   assert(intel_obj);

   if (intel_obj->region)
      intel_bufferobj_cow(intel, intel_obj);

   if (intel_obj->sys_buffer)
      memcpy((char *)intel_obj->sys_buffer + offset, data, size);
   else {
      /* Flush any existing batchbuffer that might reference this data. */
      if (drm_intel_bo_busy(intel_obj->buffer) ||
	  drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) {
	 drm_intel_bo *temp_bo;

	 temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);

	 drm_intel_bo_subdata(temp_bo, 0, size, data);

	 intel_emit_linear_blit(intel,
				intel_obj->buffer, offset,
				temp_bo, 0,
				size);

	 drm_intel_bo_unreference(temp_bo);
      } else {
	 drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
      }
   }
}
示例#14
0
static void
gen6_render_flush(struct intel_batchbuffer *batch,
		  drm_intel_context *context, uint32_t batch_end)
{
	int ret;

	ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer);
	if (ret == 0)
		ret = drm_intel_gem_bo_context_exec(batch->bo, context,
						    batch_end, 0);
	assert(ret == 0);
}
/**
 * Allocate space for and store data in a buffer object.  Any data that was
 * previously stored in the buffer object is lost.  If data is NULL,
 * memory will be allocated, but no copy will occur.
 * Called via ctx->Driver.BufferData().
 * \return GL_TRUE for success, GL_FALSE if out of memory
 */
static GLboolean
intel_bufferobj_data(GLcontext * ctx,
                     GLenum target,
                     GLsizeiptrARB size,
                     const GLvoid * data,
                     GLenum usage, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);

   intel_obj->Base.Size = size;
   intel_obj->Base.Usage = usage;

   assert(!obj->Pointer); /* Mesa should have unmapped it */

   if (intel_obj->region)
      intel_bufferobj_release_region(intel, intel_obj);

   if (intel_obj->buffer != NULL) {
      drm_intel_bo_unreference(intel_obj->buffer);
      intel_obj->buffer = NULL;
   }
   free(intel_obj->sys_buffer);
   intel_obj->sys_buffer = NULL;

   if (size != 0) {
#ifdef I915
      /* On pre-965, stick VBOs in system memory, as we're always doing swtnl
       * with their contents anyway.
       */
      if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) {
	 intel_obj->sys_buffer = malloc(size);
	 if (intel_obj->sys_buffer != NULL) {
	    if (data != NULL)
	       memcpy(intel_obj->sys_buffer, data, size);
	    return GL_TRUE;
	 }
      }
#endif
      intel_bufferobj_alloc_buffer(intel, intel_obj);
      if (!intel_obj->buffer)
         return GL_FALSE;

      if (data != NULL)
	 drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
   }

   return GL_TRUE;
}
void
intel_batchbuffer_flush_on_ring(struct intel_batchbuffer *batch, int ring)
{
	unsigned int used = flush_on_ring_common(batch, ring);

	if (used == 0)
		return;

	do_or_die(drm_intel_bo_subdata(batch->bo, 0, used, batch->buffer));

	batch->ptr = NULL;

	do_or_die(drm_intel_bo_mrb_exec(batch->bo, used, NULL, 0, 0, ring));

	intel_batchbuffer_reset(batch);
}
示例#17
0
void
intel_upload_finish(struct brw_context *brw)
{
   if (!brw->upload.bo)
      return;

   if (brw->upload.buffer_len) {
      drm_intel_bo_subdata(brw->upload.bo,
                           brw->upload.buffer_offset,
                           brw->upload.buffer_len,
                           brw->upload.buffer);
      brw->upload.buffer_len = 0;
   }

   drm_intel_bo_unreference(brw->upload.bo);
   brw->upload.bo = NULL;
}
示例#18
0
void
intel_upload_finish(struct intel_context *intel)
{
   if (!intel->upload.bo)
	   return;

   if (intel->upload.buffer_len) {
	   drm_intel_bo_subdata(intel->upload.bo,
				intel->upload.buffer_offset,
				intel->upload.buffer_len,
				intel->upload.buffer);
	   intel->upload.buffer_len = 0;
   }

   drm_intel_bo_unreference(intel->upload.bo);
   intel->upload.bo = NULL;
}
示例#19
0
static void prw_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y,
			 struct scratch_buf *dst, unsigned dst_x, unsigned dst_y,
			 unsigned logical_tile_no)
{
	uint32_t tmp_tile[options.tile_size*options.tile_size];
	int i;

	assert(batch->ptr == batch->buffer);

	if (options.ducttape)
		drm_intel_bo_wait_rendering(dst->bo);

	if (src->tiling == I915_TILING_NONE) {
		for (i = 0; i < options.tile_size; i++) {
			unsigned ofs = src_x*sizeof(uint32_t) + src->stride*(src_y + i);
			drm_intel_bo_get_subdata(src->bo, ofs,
						 options.tile_size*sizeof(uint32_t),
						 tmp_tile + options.tile_size*i);
		}
	} else {
		if (options.use_cpu_maps)
			set_to_cpu_domain(src, 0);

		cpucpy2d(src->data, src->stride/sizeof(uint32_t), src_x, src_y,
			 tmp_tile, options.tile_size, 0, 0, logical_tile_no);
	}

	if (dst->tiling == I915_TILING_NONE) {
		for (i = 0; i < options.tile_size; i++) {
			unsigned ofs = dst_x*sizeof(uint32_t) + dst->stride*(dst_y + i);
			drm_intel_bo_subdata(dst->bo, ofs,
					     options.tile_size*sizeof(uint32_t),
					     tmp_tile + options.tile_size*i);
		}
	} else {
		if (options.use_cpu_maps)
			set_to_cpu_domain(dst, 1);

		cpucpy2d(tmp_tile, options.tile_size, 0, 0,
			 dst->data, dst->stride/sizeof(uint32_t), dst_x, dst_y,
			 logical_tile_no);
	}
}
示例#20
0
void intel_upload_unmap(struct intel_context *intel,
			const void *ptr, GLuint size, GLuint align,
			drm_intel_bo **return_bo,
			GLuint *return_offset)
{
   GLuint base;

   base = (intel->upload.offset + align - 1) / align * align;
   if (size > sizeof(intel->upload.buffer)) {
      drm_intel_bo_subdata(intel->upload.bo, base, size, ptr);
      free((void*)ptr);
   }

   drm_intel_bo_reference(intel->upload.bo);
   *return_bo = intel->upload.bo;
   *return_offset = base;

   intel->upload.offset = base + size;
}
void
intel_batchbuffer_flush_with_context(struct intel_batchbuffer *batch,
				     drm_intel_context *context)
{
	int ret;
	unsigned int used = flush_on_ring_common(batch, I915_EXEC_RENDER);

	if (used == 0)
		return;

	ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->buffer);
	assert(ret == 0);

	batch->ptr = NULL;

	ret = drm_intel_gem_bo_context_exec(batch->bo, context, used,
					    I915_EXEC_RENDER);
	assert(ret == 0);

	intel_batchbuffer_reset(batch);
}
示例#22
0
drm_intel_bo *
intel_bufferobj_buffer(struct intel_context *intel,
                       struct intel_buffer_object *intel_obj,
		       GLuint flag)
{
   if (intel_obj->source)
      release_buffer(intel_obj);

   if (intel_obj->buffer == NULL) {
      intel_bufferobj_alloc_buffer(intel, intel_obj);
      drm_intel_bo_subdata(intel_obj->buffer,
			   0, intel_obj->Base.Size,
			   intel_obj->sys_buffer);

      free(intel_obj->sys_buffer);
      intel_obj->sys_buffer = NULL;
      intel_obj->offset = 0;
   }

   return intel_obj->buffer;
}
static void
do_render(drm_intel_bufmgr *bufmgr, struct intel_batchbuffer *batch,
	  drm_intel_bo *dst_bo, int width, int height)
{
	uint32_t data[width * height];
	drm_intel_bo *src_bo;
	int i;
	static uint32_t seed = 1;

	/* Generate some junk.  Real workloads would be doing a lot more
	 * work to generate the junk.
	 */
	for (i = 0; i < width * height; i++) {
		data[i] = seed++;
	}

	/* Upload the junk. */
	src_bo = drm_intel_bo_alloc(bufmgr, "src", sizeof(data), 4096);
	drm_intel_bo_subdata(src_bo, 0, sizeof(data), data);

	/* Render the junk to the dst. */
	BLIT_COPY_BATCH_START(0);
	OUT_BATCH((3 << 24) | /* 32 bits */
		  (0xcc << 16) | /* copy ROP */
		  (width * 4) /* dst pitch */);
	OUT_BATCH(0); /* dst x1,y1 */
	OUT_BATCH((height << 16) | width); /* dst x2,y2 */
	OUT_RELOC(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
	OUT_BATCH(0); /* src x1,y1 */
	OUT_BATCH(width * 4); /* src pitch */
	OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
	ADVANCE_BATCH();

	intel_batchbuffer_flush(batch);

	drm_intel_bo_unreference(src_bo);
}
示例#24
0
void *
intel_upload_map(struct brw_context *brw, GLuint size, GLuint align)
{
   GLuint base, delta;
   char *ptr;

   base = (brw->upload.offset + align - 1) / align * align;
   if (brw->upload.bo == NULL || base + size > brw->upload.bo->size) {
      wrap_buffers(brw, size);
      base = 0;
   }

   delta = base - brw->upload.offset;
   if (brw->upload.buffer_len &&
       brw->upload.buffer_len + delta + size > sizeof(brw->upload.buffer)) {
      drm_intel_bo_subdata(brw->upload.bo,
                           brw->upload.buffer_offset,
                           brw->upload.buffer_len,
                           brw->upload.buffer);
      brw->upload.buffer_len = 0;
   }

   if (size <= sizeof(brw->upload.buffer)) {
      if (brw->upload.buffer_len == 0)
         brw->upload.buffer_offset = base;
      else
         brw->upload.buffer_len += delta;

      ptr = brw->upload.buffer + brw->upload.buffer_len;
      brw->upload.buffer_len += size;
   } else {
      ptr = malloc(size);
   }

   return ptr;
}
示例#25
0
/**
 * Replace data in a subrange of buffer object.  If the data range
 * specified by size + offset extends beyond the end of the buffer or
 * if data is NULL, no copy is performed.
 * Called via glBufferSubDataARB().
 */
static void
intel_bufferobj_subdata(struct gl_context * ctx,
                        GLintptrARB offset,
                        GLsizeiptrARB size,
                        const GLvoid * data, struct gl_buffer_object *obj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
   bool busy;

   if (size == 0)
      return;

   assert(intel_obj);

   /* If we have a single copy in system memory, update that */
   if (intel_obj->sys_buffer) {
      if (intel_obj->source)
	 release_buffer(intel_obj);

      if (intel_obj->buffer == NULL) {
	 memcpy((char *)intel_obj->sys_buffer + offset, data, size);
	 return;
      }

      free(intel_obj->sys_buffer);
      intel_obj->sys_buffer = NULL;
   }

   /* Otherwise we need to update the copy in video memory. */
   busy =
      drm_intel_bo_busy(intel_obj->buffer) ||
      drm_intel_bo_references(intel->batch.bo, intel_obj->buffer);

   /* replace the current busy bo with fresh data */
   if (busy && size == intel_obj->Base.Size) {
      drm_intel_bo_unreference(intel_obj->buffer);
      intel_bufferobj_alloc_buffer(intel, intel_obj);
      drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
   } else if (intel->gen < 6) {
      if (busy) {
	 drm_intel_bo *temp_bo;

	 temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);

	 drm_intel_bo_subdata(temp_bo, 0, size, data);

	 intel_emit_linear_blit(intel,
				intel_obj->buffer, offset,
				temp_bo, 0,
				size);

	 drm_intel_bo_unreference(temp_bo);
      } else {
	 drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
      }
   } else {
      /* Can't use the blit to modify the buffer in the middle of batch. */
      if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) {
	 intel_batchbuffer_flush(intel);
      }
      drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
   }
}
示例#26
0
int
intel_bo_pwrite(struct intel_bo *bo, unsigned long offset,
                unsigned long size, const void *data)
{
   return drm_intel_bo_subdata(gem_bo(bo), offset, size, data);
}