summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-09-11 16:05:15 +0100
committerKeith Whitwell <keith@tungstengraphics.com>2008-09-11 16:05:15 +0100
commit0397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1 (patch)
tree732c93d74ed806942a13bf15575a61aa4f001253 /src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c
parent80af50b35b5a4e8890e15b28940576f8a1ac1476 (diff)
parente6887a5752774c18cf527477fdd3e57e4893ff3b (diff)
Merge branch 'gallium-0.1' into gallium-0.2
A first attempt at moving gallium onto a branch directly off master... It will be interesting to see how much work this takes to get running. Have resolved the conflicts semi-arbitarily, not compiled or tested. Conflicts: .gitignore Makefile configs/config.mgw configs/darwin configs/darwin-x86ppc configs/default configs/freebsd-dri configs/linux-dri configs/linux-dri-xcb configs/linux-fbdev configs/linux-static configs/linux-x86-64-static configs/linux-x86-static doxygen/Makefile include/GL/gl.h progs/demos/Makefile progs/demos/descrip.mms progs/demos/texenv.c progs/egl/.gitignore progs/egl/Makefile progs/glsl/.gitignore progs/glsl/Makefile progs/glsl/convolutions.c progs/samples/Makefile.mgw progs/tests/.gitignore progs/trivial/.gitignore progs/trivial/point-param.c progs/trivial/tri.c progs/xdemos/.gitignore progs/xdemos/glthreads.c src/egl/drivers/demo/Makefile src/egl/drivers/dri/Makefile src/egl/main/Makefile src/glu/Makefile src/glu/sgi/Makefile src/glu/sgi/Makefile.mgw src/glut/glx/Makefile.mgw src/glut/os2/WarpWin.cpp src/glut/os2/glut_cindex.cpp src/glut/os2/glut_gamemode.cpp src/glut/os2/glut_win.cpp src/glut/os2/glut_winmisc.cpp src/glut/os2/os2_glx.cpp src/glut/os2/os2_menu.cpp src/glut/os2/os2_winproc.cpp src/glw/Makefile src/glx/x11/dri_glx.c src/glx/x11/glxext.c src/mesa/Makefile src/mesa/Makefile.mgw src/mesa/descrip.mms src/mesa/drivers/beos/Makefile src/mesa/drivers/common/descrip.mms src/mesa/drivers/common/driverfuncs.c src/mesa/drivers/directfb/Makefile src/mesa/drivers/dri/Makefile.template src/mesa/drivers/dri/common/dri_bufmgr.c src/mesa/drivers/dri/common/dri_bufmgr.h src/mesa/drivers/dri/common/dri_util.c src/mesa/drivers/dri/common/extension_helper.h src/mesa/drivers/dri/common/mmio.h src/mesa/drivers/dri/common/utils.c src/mesa/drivers/dri/common/utils.h src/mesa/drivers/dri/glcore/Makefile src/mesa/drivers/dri/i810/i810screen.c src/mesa/drivers/dri/i915/intel_ioctl.c src/mesa/drivers/dri/i915/intel_ioctl.h src/mesa/drivers/dri/i915/intel_screen.c src/mesa/drivers/dri/i915/server/i830_common.h src/mesa/drivers/dri/i915/server/i830_dri.h src/mesa/drivers/dri/i965/intel_screen.c src/mesa/drivers/dri/i965/server/i830_common.h src/mesa/drivers/dri/i965/server/i830_dri.h src/mesa/drivers/dri/mach64/mach64_screen.c src/mesa/drivers/dri/nouveau/nouveau_context.h src/mesa/drivers/dri/nouveau/nouveau_fifo.c src/mesa/drivers/dri/nouveau/nouveau_fifo.h src/mesa/drivers/dri/nouveau/nouveau_screen.c src/mesa/drivers/dri/nouveau/nouveau_screen.h src/mesa/drivers/dri/r128/r128_tex.h src/mesa/drivers/dri/savage/savageioctl.h src/mesa/drivers/fbdev/Makefile src/mesa/drivers/osmesa/Makefile src/mesa/drivers/osmesa/descrip.mms src/mesa/drivers/x11/Makefile src/mesa/drivers/x11/descrip.mms src/mesa/drivers/x11/xm_dd.c src/mesa/glapi/glapi.c src/mesa/glapi/glthread.c src/mesa/main/api_validate.c src/mesa/main/attrib.c src/mesa/main/bufferobj.c src/mesa/main/bufferobj.h src/mesa/main/buffers.c src/mesa/main/config.h src/mesa/main/context.c src/mesa/main/descrip.mms src/mesa/main/drawpix.c src/mesa/main/enums.c src/mesa/main/fbobject.c src/mesa/main/glheader.h src/mesa/main/imports.c src/mesa/main/mipmap.c src/mesa/main/mm.c src/mesa/main/mm.h src/mesa/main/mtypes.h src/mesa/main/points.c src/mesa/main/sources src/mesa/main/state.c src/mesa/main/texcompress_fxt1.c src/mesa/main/texenvprogram.c src/mesa/main/texobj.c src/mesa/main/texstate.c src/mesa/main/texstore.c src/mesa/math/descrip.mms src/mesa/shader/arbprogram.c src/mesa/shader/descrip.mms src/mesa/shader/prog_execute.c src/mesa/shader/prog_statevars.c src/mesa/shader/prog_statevars.h src/mesa/shader/prog_uniform.c src/mesa/shader/program.c src/mesa/shader/program.h src/mesa/shader/shader_api.c src/mesa/shader/slang/descrip.mms src/mesa/shader/slang/library/slang_vertex_builtin_gc.h src/mesa/sources src/mesa/swrast/descrip.mms src/mesa/swrast/s_drawpix.c src/mesa/swrast/s_fragprog.c src/mesa/swrast/s_readpix.c src/mesa/swrast/s_span.c src/mesa/swrast_setup/descrip.mms src/mesa/tnl/descrip.mms src/mesa/tnl/t_context.h src/mesa/tnl/t_vp_build.c src/mesa/tnl/tnl.h src/mesa/vbo/descrip.mms src/mesa/vbo/vbo_context.c src/mesa/vbo/vbo_exec_array.c src/mesa/x86-64/xform4.S src/mesa/x86/rtasm/x86sse.c src/mesa/x86/rtasm/x86sse.h windows/VC6/progs/glut/glut.dsp windows/VC7/mesa/gdi/gdi.vcproj windows/VC7/mesa/glu/glu.vcproj windows/VC7/mesa/mesa.sln windows/VC7/mesa/mesa/mesa.vcproj windows/VC7/mesa/osmesa/osmesa.vcproj windows/VC7/progs/glut/glut.vcproj windows/VC8/mesa/gdi/gdi.vcproj windows/VC8/mesa/glu/glu.vcproj windows/VC8/mesa/mesa.sln windows/VC8/mesa/mesa/mesa.vcproj windows/VC8/progs/glut/glut.vcproj
Diffstat (limited to 'src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c')
-rw-r--r--src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c429
1 files changed, 429 insertions, 0 deletions
diff --git a/src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c b/src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c
new file mode 100644
index 0000000000..bc13a5761e
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/common/intel_be_batchbuffer.c
@@ -0,0 +1,429 @@
+
+#include "intel_be_batchbuffer.h"
+#include "intel_be_context.h"
+#include "intel_be_device.h"
+#include <errno.h>
+
+#include "xf86drm.h"
+
+static void
+intel_realloc_relocs(struct intel_be_batchbuffer *batch, int num_relocs)
+{
+ unsigned long size = num_relocs * I915_RELOC0_STRIDE + I915_RELOC_HEADER;
+
+ size *= sizeof(uint32_t);
+ batch->reloc = realloc(batch->reloc, size);
+ batch->reloc_size = num_relocs;
+}
+
+
+void
+intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch)
+{
+ /*
+ * Get a new, free batchbuffer.
+ */
+ drmBO *bo;
+ struct drm_bo_info_req *req;
+
+ driBOUnrefUserList(batch->list);
+ driBOResetList(batch->list);
+
+ /* base.size is the size available to the i915simple driver */
+ batch->base.size = batch->device->max_batch_size - BATCH_RESERVED;
+ batch->base.actual_size = batch->device->max_batch_size;
+ driBOData(batch->buffer, batch->base.actual_size, NULL, NULL, 0);
+
+ /*
+ * Add the batchbuffer to the validate list.
+ */
+
+ driBOAddListItem(batch->list, batch->buffer,
+ DRM_BO_FLAG_EXE | DRM_BO_FLAG_MEM_TT,
+ DRM_BO_FLAG_EXE | DRM_BO_MASK_MEM,
+ &batch->dest_location, &batch->node);
+
+ req = &batch->node->bo_arg.d.req.bo_req;
+
+ /*
+ * Set up information needed for us to make relocations
+ * relative to the underlying drm buffer objects.
+ */
+
+ driReadLockKernelBO();
+ bo = driBOKernel(batch->buffer);
+ req->presumed_offset = (uint64_t) bo->offset;
+ req->hint = DRM_BO_HINT_PRESUMED_OFFSET;
+ batch->drmBOVirtual = (uint8_t *) bo->virtual;
+ driReadUnlockKernelBO();
+
+ /*
+ * Adjust the relocation buffer size.
+ */
+
+ if (batch->reloc_size > INTEL_MAX_RELOCS ||
+ batch->reloc == NULL)
+ intel_realloc_relocs(batch, INTEL_DEFAULT_RELOCS);
+
+ assert(batch->reloc != NULL);
+ batch->reloc[0] = 0; /* No relocs yet. */
+ batch->reloc[1] = 1; /* Reloc type 1 */
+ batch->reloc[2] = 0; /* Only a single relocation list. */
+ batch->reloc[3] = 0; /* Only a single relocation list. */
+
+ batch->base.map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
+ batch->poolOffset = driBOPoolOffset(batch->buffer);
+ batch->base.ptr = batch->base.map;
+ batch->dirty_state = ~0;
+ batch->nr_relocs = 0;
+ batch->flags = 0;
+ batch->id = 0;//batch->intel->intelScreen->batch_id++;
+}
+
+/*======================================================================
+ * Public functions
+ */
+struct intel_be_batchbuffer *
+intel_be_batchbuffer_alloc(struct intel_be_context *intel)
+{
+ struct intel_be_batchbuffer *batch = calloc(sizeof(*batch), 1);
+
+ batch->intel = intel;
+ batch->device = intel->device;
+
+ driGenBuffers(intel->device->batchPool, "batchbuffer", 1,
+ &batch->buffer, 4096,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0);
+ batch->last_fence = NULL;
+ batch->list = driBOCreateList(20);
+ batch->reloc = NULL;
+ intel_be_batchbuffer_reset(batch);
+ return batch;
+}
+
+void
+intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch)
+{
+ if (batch->last_fence) {
+ driFenceFinish(batch->last_fence,
+ DRM_FENCE_TYPE_EXE, FALSE);
+ driFenceUnReference(&batch->last_fence);
+ }
+ if (batch->base.map) {
+ driBOUnmap(batch->buffer);
+ batch->base.map = NULL;
+ }
+ driBOUnReference(batch->buffer);
+ driBOFreeList(batch->list);
+ if (batch->reloc)
+ free(batch->reloc);
+ batch->buffer = NULL;
+ free(batch);
+}
+
+void
+intel_be_offset_relocation(struct intel_be_batchbuffer *batch,
+ unsigned pre_add,
+ struct _DriBufferObject *driBO,
+ uint64_t val_flags,
+ uint64_t val_mask)
+{
+ int itemLoc;
+ struct _drmBONode *node;
+ uint32_t *reloc;
+ struct drm_bo_info_req *req;
+
+ driBOAddListItem(batch->list, driBO, val_flags, val_mask,
+ &itemLoc, &node);
+ req = &node->bo_arg.d.req.bo_req;
+
+ if (!(req->hint & DRM_BO_HINT_PRESUMED_OFFSET)) {
+
+ /*
+ * Stop other threads from tampering with the underlying
+ * drmBO while we're reading its offset.
+ */
+
+ driReadLockKernelBO();
+ req->presumed_offset = (uint64_t) driBOKernel(driBO)->offset;
+ driReadUnlockKernelBO();
+ req->hint = DRM_BO_HINT_PRESUMED_OFFSET;
+ }
+
+ pre_add += driBOPoolOffset(driBO);
+
+ if (batch->nr_relocs == batch->reloc_size)
+ intel_realloc_relocs(batch, batch->reloc_size * 2);
+
+ reloc = batch->reloc +
+ (I915_RELOC_HEADER + batch->nr_relocs * I915_RELOC0_STRIDE);
+
+ reloc[0] = ((uint8_t *)batch->base.ptr - batch->drmBOVirtual);
+ i915_batchbuffer_dword(&batch->base, req->presumed_offset + pre_add);
+ reloc[1] = pre_add;
+ reloc[2] = itemLoc;
+ reloc[3] = batch->dest_location;
+ batch->nr_relocs++;
+}
+
+static void
+i915_drm_copy_reply(const struct drm_bo_info_rep * rep, drmBO * buf)
+{
+ buf->handle = rep->handle;
+ buf->flags = rep->flags;
+ buf->size = rep->size;
+ buf->offset = rep->offset;
+ buf->mapHandle = rep->arg_handle;
+ buf->proposedFlags = rep->proposed_flags;
+ buf->start = rep->buffer_start;
+ buf->fenceFlags = rep->fence_flags;
+ buf->replyFlags = rep->rep_flags;
+ buf->pageAlignment = rep->page_alignment;
+}
+
+static int
+i915_execbuf(struct intel_be_batchbuffer *batch,
+ unsigned int used,
+ boolean ignore_cliprects,
+ drmBOList *list,
+ struct drm_i915_execbuffer *ea)
+{
+// struct intel_be_context *intel = batch->intel;
+ drmBONode *node;
+ drmMMListHead *l;
+ struct drm_i915_op_arg *arg, *first;
+ struct drm_bo_op_req *req;
+ struct drm_bo_info_rep *rep;
+ uint64_t *prevNext = NULL;
+ drmBO *buf;
+ int ret = 0;
+ uint32_t count = 0;
+
+ first = NULL;
+ for (l = list->list.next; l != &list->list; l = l->next) {
+ node = DRMLISTENTRY(drmBONode, l, head);
+
+ arg = &node->bo_arg;
+ req = &arg->d.req;
+
+ if (!first)
+ first = arg;
+
+ if (prevNext)
+ *prevNext = (unsigned long)arg;
+
+ prevNext = &arg->next;
+ req->bo_req.handle = node->buf->handle;
+ req->op = drm_bo_validate;
+ req->bo_req.flags = node->arg0;
+ req->bo_req.mask = node->arg1;
+ req->bo_req.hint |= 0;
+ count++;
+ }
+
+ memset(ea, 0, sizeof(*ea));
+ ea->num_buffers = count;
+ ea->batch.start = batch->poolOffset;
+ ea->batch.used = used;
+#if 0 /* ZZZ JB: no cliprects used */
+ ea->batch.cliprects = intel->pClipRects;
+ ea->batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
+ ea->batch.DR1 = 0;
+ ea->batch.DR4 = 0;((((GLuint) intel->drawX) & 0xffff) |
+ (((GLuint) intel->drawY) << 16));
+#else
+ ea->batch.cliprects = NULL;
+ ea->batch.num_cliprects = 0;
+ ea->batch.DR1 = 0;
+ ea->batch.DR4 = 0;
+#endif
+ ea->fence_arg.flags = DRM_I915_FENCE_FLAG_FLUSHED;
+ ea->ops_list = (unsigned long) first;
+ first->reloc_ptr = (unsigned long) batch->reloc;
+ batch->reloc[0] = batch->nr_relocs;
+
+ //return -EFAULT;
+ do {
+ ret = drmCommandWriteRead(batch->device->fd, DRM_I915_EXECBUFFER, ea,
+ sizeof(*ea));
+ } while (ret == -EAGAIN);
+
+ if (ret != 0)
+ return ret;
+
+ for (l = list->list.next; l != &list->list; l = l->next) {
+ node = DRMLISTENTRY(drmBONode, l, head);
+ arg = &node->bo_arg;
+ rep = &arg->d.rep.bo_info;
+
+ if (!arg->handled) {
+ return -EFAULT;
+ }
+ if (arg->d.rep.ret)
+ return arg->d.rep.ret;
+
+ buf = node->buf;
+ i915_drm_copy_reply(rep, buf);
+ }
+ return 0;
+}
+
+/* TODO: Push this whole function into bufmgr.
+ */
+static struct _DriFenceObject *
+do_flush_locked(struct intel_be_batchbuffer *batch,
+ unsigned int used,
+ boolean ignore_cliprects, boolean allow_unlock)
+{
+ struct intel_be_context *intel = batch->intel;
+ struct _DriFenceObject *fo;
+ drmFence fence;
+ drmBOList *boList;
+ struct drm_i915_execbuffer ea;
+ int ret = 0;
+
+ driBOValidateUserList(batch->list);
+ boList = driGetdrmBOList(batch->list);
+
+#if 0 /* ZZZ JB Allways run */
+ if (!(intel->numClipRects == 0 && !ignore_cliprects)) {
+#else
+ if (1) {
+#endif
+ ret = i915_execbuf(batch, used, ignore_cliprects, boList, &ea);
+ } else {
+ driPutdrmBOList(batch->list);
+ fo = NULL;
+ goto out;
+ }
+ driPutdrmBOList(batch->list);
+ if (ret)
+ abort();
+
+ if (ea.fence_arg.error != 0) {
+
+ /*
+ * The hardware has been idled by the kernel.
+ * Don't fence the driBOs.
+ */
+
+ if (batch->last_fence)
+ driFenceUnReference(&batch->last_fence);
+#if 0 /* ZZZ JB: no _mesa_* funcs in gallium */
+ _mesa_printf("fence error\n");
+#endif
+ batch->last_fence = NULL;
+ fo = NULL;
+ goto out;
+ }
+
+ fence.handle = ea.fence_arg.handle;
+ fence.fence_class = ea.fence_arg.fence_class;
+ fence.type = ea.fence_arg.type;
+ fence.flags = ea.fence_arg.flags;
+ fence.signaled = ea.fence_arg.signaled;
+
+ fo = driBOFenceUserList(batch->device->fenceMgr, batch->list,
+ "SuperFence", &fence);
+
+ if (driFenceType(fo) & DRM_I915_FENCE_TYPE_RW) {
+ if (batch->last_fence)
+ driFenceUnReference(&batch->last_fence);
+ /*
+ * FIXME: Context last fence??
+ */
+ batch->last_fence = fo;
+ driFenceReference(fo);
+ }
+ out:
+#if 0 /* ZZZ JB: fix this */
+ intel->vtbl.lost_hardware(intel);
+#else
+ (void)intel;
+#endif
+ return fo;
+}
+
+
+struct _DriFenceObject *
+intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch)
+{
+ struct intel_be_context *intel = batch->intel;
+ unsigned int used = batch->base.ptr - batch->base.map;
+ boolean was_locked = batch->intel->hardware_locked(intel);
+ struct _DriFenceObject *fence;
+
+ if (used == 0) {
+ driFenceReference(batch->last_fence);
+ return batch->last_fence;
+ }
+
+ /* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
+ * performance drain that we would like to avoid.
+ */
+#if 0 /* ZZZ JB: what should we do here? */
+ if (used & 4) {
+ ((int *) batch->base.ptr)[0] = intel->vtbl.flush_cmd();
+ ((int *) batch->base.ptr)[1] = 0;
+ ((int *) batch->base.ptr)[2] = MI_BATCH_BUFFER_END;
+ used += 12;
+ }
+ else {
+ ((int *) batch->base.ptr)[0] = intel->vtbl.flush_cmd();
+ ((int *) batch->base.ptr)[1] = MI_BATCH_BUFFER_END;
+ used += 8;
+ }
+#else
+ if (used & 4) {
+ ((int *) batch->base.ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH;
+ ((int *) batch->base.ptr)[1] = 0;
+ ((int *) batch->base.ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END;
+ used += 12;
+ }
+ else {
+ ((int *) batch->base.ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH;
+ ((int *) batch->base.ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END;
+ used += 8;
+ }
+#endif
+ driBOUnmap(batch->buffer);
+ batch->base.ptr = NULL;
+ batch->base.map = NULL;
+
+ /* TODO: Just pass the relocation list and dma buffer up to the
+ * kernel.
+ */
+ if (!was_locked)
+ intel->hardware_lock(intel);
+
+ fence = do_flush_locked(batch, used, !(batch->flags & INTEL_BATCH_CLIPRECTS),
+ FALSE);
+
+ if (!was_locked)
+ intel->hardware_unlock(intel);
+
+ /* Reset the buffer:
+ */
+ intel_be_batchbuffer_reset(batch);
+ return fence;
+}
+
+void
+intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch)
+{
+ struct _DriFenceObject *fence = intel_be_batchbuffer_flush(batch);
+ driFenceFinish(fence, driFenceType(fence), FALSE);
+ driFenceUnReference(&fence);
+}
+
+#if 0
+void
+intel_be_batchbuffer_data(struct intel_be_batchbuffer *batch,
+ const void *data, unsigned int bytes, unsigned int flags)
+{
+ assert((bytes & 3) == 0);
+ intel_batchbuffer_require_space(batch, bytes, flags);
+ memcpy(batch->base.ptr, data, bytes);
+ batch->base.ptr += bytes;
+}
+#endif