static GstGLBuffer * _gl_buffer_copy (GstGLBuffer * src, gssize offset, gssize size) { GstAllocator *allocator = src->mem.mem.allocator; GstAllocationParams params = { 0, src->mem.mem.align, 0, 0 }; GstGLBuffer *dest = NULL; dest = _gl_buffer_new (allocator, NULL, src->mem.context, src->target, src->usage_hints, ¶ms, src->mem.mem.maxsize); /* If not doing a full copy, then copy to sysmem, the 2D represention of the * texture would become wrong */ if (GST_MEMORY_FLAG_IS_SET (src, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)) { if (!gst_gl_base_memory_memcpy (GST_GL_BASE_MEMORY_CAST (src), GST_GL_BASE_MEMORY_CAST (dest), offset, size)) { GST_CAT_WARNING (GST_CAT_GL_BUFFER, "Could not copy GL Buffer"); gst_memory_unref (GST_MEMORY_CAST (dest)); dest = NULL; } } else { if (!gst_gl_buffer_copy_buffer_sub_data (src, dest, offset, size)) { if (!gst_gl_base_memory_memcpy (GST_GL_BASE_MEMORY_CAST (src), GST_GL_BASE_MEMORY_CAST (dest), offset, size)) { GST_CAT_WARNING (GST_CAT_GL_BUFFER, "Could not copy GL Buffer"); gst_memory_unref (GST_MEMORY_CAST (dest)); dest = NULL; } } } return dest; }
/** * gst_gl_base_memory_memcpy: * @src: the source #GstGLBaseMemory * @dest: the destination #GstGLBaseMemory * @offset: the offset to start at * @size: the number of bytes to copy * * Returns: whether the copy suceeded. */ gboolean gst_gl_base_memory_memcpy (GstGLBaseMemory * src, GstGLBaseMemory * dest, gssize offset, gssize size) { GstMapInfo sinfo, dinfo; if (!gst_gl_base_memory_alloc_data (GST_GL_BASE_MEMORY_CAST (dest))) return FALSE; if (!gst_memory_map ((GstMemory *) src, &sinfo, GST_MAP_READ)) { GST_CAT_WARNING (GST_CAT_GL_BASE_MEMORY, "could not read map source memory %p", src); return FALSE; } if (!gst_memory_map ((GstMemory *) dest, &dinfo, GST_MAP_WRITE)) { GST_CAT_WARNING (GST_CAT_GL_BASE_MEMORY, "could not write map dest memory %p", dest); gst_memory_unmap ((GstMemory *) src, &sinfo); return FALSE; } if (size == -1) size = sinfo.size > offset ? sinfo.size - offset : 0; GST_CAT_DEBUG (GST_CAT_GL_BASE_MEMORY, "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, src, dest); memcpy (dinfo.data, sinfo.data + offset, size); gst_memory_unmap ((GstMemory *) dest, &dinfo); gst_memory_unmap ((GstMemory *) src, &sinfo); return TRUE; }
static gpointer gst_gl_buffer_cpu_access (GstGLBuffer * mem, GstMapInfo * info, gsize size) { const GstGLFuncs *gl = mem->mem.context->gl_vtable; gpointer data, ret; if (!gst_gl_base_memory_alloc_data (GST_GL_BASE_MEMORY_CAST (mem))) return NULL; ret = mem->mem.data; GST_CAT_LOG (GST_CAT_GL_BUFFER, "mapping id %d size %" G_GSIZE_FORMAT, mem->id, size); /* The extra data pointer indirection/memcpy is needed for coherent across * concurrent map()'s in both GL and CPU */ if (GST_MEMORY_FLAG_IS_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD) && (info->flags & GST_MAP_GL) == 0 && (info->flags & GST_MAP_READ) != 0) { gl->BindBuffer (mem->target, mem->id); if (gl->MapBufferRange) { /* FIXME: optionally remove this with a flag and return the * glMapBufferRange pointer (requires * GL_ARB_buffer_storage/GL4/GL_COHERENT_BIT) */ guint gl_map_flags = GL_MAP_READ_BIT; data = gl->MapBufferRange (mem->target, 0, size, gl_map_flags); if (data) memcpy (mem->mem.data, data, size); gl->UnmapBuffer (mem->target); ret = mem->mem.data; } else if (gl->GetBufferSubData) { gl->GetBufferSubData (mem->target, 0, size, mem->mem.data); ret = mem->mem.data; } else { ret = NULL; } gl->BindBuffer (mem->target, 0); } return ret; }