summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2006-09-08 10:36:32 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2006-09-08 10:36:32 +0000
commit02df36f394da4f699b4841c279a6b573fcb7c32b (patch)
tree0c1885a25d16c1897d7de494c02b422b479932ab
parenta5e73e68878ebed7347532285019befc8c7b1106 (diff)
downloadmesa-02df36f394da4f699b4841c279a6b573fcb7c32b.tar.gz
Basic facility for playing back captured aubfiles. Requires a small
hack to the drm to disable command verification on the cmd_buffer ioctl. Doesn't exactly replay as commands are normally delivered as batchbuffers but are captured and replayed as commands on the ring.
-rw-r--r--src/mesa/drivers/dri/i965/Makefile1
-rw-r--r--src/mesa/drivers/dri/i965/brw_aub.c3
-rw-r--r--src/mesa/drivers/dri/i965/brw_aub.h3
-rw-r--r--src/mesa/drivers/dri/i965/brw_aub_playback.c161
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.c8
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c6
-rw-r--r--src/mesa/drivers/dri/i965/bufmgr.h4
-rw-r--r--src/mesa/drivers/dri/i965/bufmgr_fake.c15
8 files changed, 201 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile
index 1710d2b6d45..e4fb451cc09 100644
--- a/src/mesa/drivers/dri/i965/Makefile
+++ b/src/mesa/drivers/dri/i965/Makefile
@@ -20,6 +20,7 @@ DRIVER_SOURCES = \
intel_tex.c \
intel_tex_validate.c \
brw_aub.c \
+ brw_aub_playback.c \
brw_cc.c \
brw_clip.c \
brw_clip_line.c \
diff --git a/src/mesa/drivers/dri/i965/brw_aub.c b/src/mesa/drivers/dri/i965/brw_aub.c
index 2b7d1f4356a..cc70692adda 100644
--- a/src/mesa/drivers/dri/i965/brw_aub.c
+++ b/src/mesa/drivers/dri/i965/brw_aub.c
@@ -291,6 +291,9 @@ int brw_aub_init( struct brw_context *brw )
i++;
+ if (_mesa_getenv("INTEL_REPLAY"))
+ return 0;
+
if (_mesa_getenv("INTEL_AUBFILE")) {
val = snprintf(filename, sizeof(filename), "%s%d.aub", _mesa_getenv("INTEL_AUBFILE"), i%4);
_mesa_printf("--> Aub file: %s\n", filename);
diff --git a/src/mesa/drivers/dri/i965/brw_aub.h b/src/mesa/drivers/dri/i965/brw_aub.h
index a2e1f6112dd..198e36dc3c0 100644
--- a/src/mesa/drivers/dri/i965/brw_aub.h
+++ b/src/mesa/drivers/dri/i965/brw_aub.h
@@ -166,4 +166,7 @@ struct intel_context;
int brw_aub_init( struct brw_context *brw );
void brw_aub_destroy( struct brw_context *brw );
+int brw_playback_aubfile(struct brw_context *brw,
+ const char *filename);
+
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_aub_playback.c b/src/mesa/drivers/dri/i965/brw_aub_playback.c
new file mode 100644
index 00000000000..73743daa60c
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_aub_playback.c
@@ -0,0 +1,161 @@
+
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "brw_aub.h"
+#include "brw_context.h"
+#include "intel_ioctl.h"
+#include "bufmgr.h"
+
+struct aub_state {
+ struct intel_context *intel;
+ const char *map;
+ unsigned int csr;
+ unsigned int sz;
+};
+
+
+static int gobble( struct aub_state *s, int size )
+{
+ if (s->csr + size > s->sz) {
+ DBG("EOF in %s\n", __FUNCTION__);
+ return 1;
+ }
+
+ s->csr += size;
+ return 0;
+}
+
+/* In order to work, the memory layout has to be the same as the X
+ * server which created the aubfile.
+ */
+static int parse_block_header( struct aub_state *s )
+{
+ struct aub_block_header *bh = (struct aub_block_header *)(s->map + s->csr);
+ void *data = (void *)(bh + 1);
+ unsigned int len = (bh->length + 3) & ~3;
+
+ DBG("block header at 0x%x\n", s->csr);
+
+ if (s->csr + len + sizeof(*bh) > s->sz) {
+ DBG("EOF in data in %s\n", __FUNCTION__);
+ return 1;
+ }
+
+ if (bh->address_space == ADDR_GTT) {
+
+ switch (bh->operation)
+ {
+ case BH_DATA_WRITE: {
+ void *dest = bmFindVirtual( s->intel, bh->address, len );
+ if (dest == NULL) {
+ _mesa_printf("Couldn't find virtual address for offset %x\n", bh->address);
+ return 1;
+ }
+
+ /* Just copy the data to the indicated place in agp memory:
+ */
+ memcpy(dest, data, len);
+ break;
+ }
+ case BH_COMMAND_WRITE:
+ /* For ring data, just send off immediately via an ioctl.
+ * This differs slightly from how the stream was executed
+ * initially as this would have been a batchbuffer.
+ */
+ intel_cmd_ioctl(s->intel, data, len, GL_TRUE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ s->csr += sizeof(*bh) + len;
+ return 0;
+}
+
+
+#define AUB_FILE_HEADER 0xe085000b
+#define AUB_BLOCK_HEADER 0xe0c10003
+#define AUB_DUMP_BMP 0xe09e0004
+
+int brw_playback_aubfile(struct brw_context *brw,
+ const char *filename)
+{
+ struct intel_context *intel = &brw->intel;
+ struct aub_state state;
+ struct stat sb;
+ int fd;
+ int retval = 0;
+
+ state.intel = intel;
+
+ fd = open(filename, O_RDONLY, 0);
+ if (fd < 0) {
+ DBG("couldn't open aubfile: %s\n", filename);
+ return 1;
+ }
+
+ if (fstat(fd, &sb) != 0) {
+ DBG("couldn't open %s\n", filename);
+ return 1;
+ }
+
+ state.csr = 0;
+ state.sz = sb.st_size;
+ state.map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ if (state.map == NULL) {
+ DBG("couldn't mmap %s\n", filename);
+ return 1;
+ }
+
+ LOCK_HARDWARE(intel);
+ {
+ /* Make sure we don't confuse anything that might happen to be
+ * going on with the hardware:
+ */
+/* bmEvictAll(intel); */
+/* intel->vtbl.lost_hardware(intel); */
+
+
+ /* Replay the aubfile item by item:
+ */
+ while (retval == 0 &&
+ state.csr != state.sz) {
+ unsigned int insn = *(unsigned int *)(state.map + state.csr);
+
+ switch (insn) {
+ case AUB_FILE_HEADER:
+ retval = gobble(&state, sizeof(struct aub_file_header));
+ break;
+
+ case AUB_BLOCK_HEADER:
+ retval = parse_block_header(&state);
+ break;
+
+ case AUB_DUMP_BMP:
+ retval = gobble(&state, sizeof(struct aub_dump_bmp));
+ break;
+
+ default:
+ DBG("unknown instruction %x\n", insn);
+ retval = 1;
+ break;
+ }
+ }
+ }
+ UNLOCK_HARDWARE(intel);
+ return retval;
+}
+
+
+
+
+
+
+
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index dba6845e53e..c1f6617f3fd 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -162,6 +162,14 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
brw_exec_init( ctx );
brw_save_init( ctx );
+ {
+ const char *filename = getenv("INTEL_REPLAY");
+ if (filename) {
+ brw_playback_aubfile(brw, filename);
+ exit(0);
+ }
+ }
+
return GL_TRUE;
}
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 02c24574232..ef4f1104848 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -400,6 +400,12 @@ GLboolean brw_draw_prims( GLcontext *ctx,
retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index, flags);
}
+ if (intel->aub_file) {
+ intelFinish( &intel->ctx );
+ intel->aub_wrap = 1;
+ }
+
+
return retval;
}
diff --git a/src/mesa/drivers/dri/i965/bufmgr.h b/src/mesa/drivers/dri/i965/bufmgr.h
index ab5d56a231a..83a810cc6dd 100644
--- a/src/mesa/drivers/dri/i965/bufmgr.h
+++ b/src/mesa/drivers/dri/i965/bufmgr.h
@@ -186,6 +186,10 @@ void bmReleaseBuffers( struct intel_context * );
GLboolean bmError( struct intel_context * );
void bmEvictAll( struct intel_context * );
+void *bmFindVirtual( struct intel_context *intel,
+ unsigned int offset,
+ size_t sz );
+
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
diff --git a/src/mesa/drivers/dri/i965/bufmgr_fake.c b/src/mesa/drivers/dri/i965/bufmgr_fake.c
index 67fa7c8e2e2..40e92398836 100644
--- a/src/mesa/drivers/dri/i965/bufmgr_fake.c
+++ b/src/mesa/drivers/dri/i965/bufmgr_fake.c
@@ -650,6 +650,21 @@ static struct buffer *do_GenBuffer(struct intel_context *intel, const char *name
return buf;
}
+
+void *bmFindVirtual( struct intel_context *intel,
+ unsigned int offset,
+ size_t sz )
+{
+ struct bufmgr *bm = intel->bm;
+ int i;
+
+ for (i = 0; i < bm->nr_pools; i++)
+ if (offset >= bm->pool[i].low_offset &&
+ offset + sz <= bm->pool[i].low_offset + bm->pool[i].size)
+ return bm->pool[i].virtual + offset;
+
+ return NULL;
+}
void bmGenBuffers(struct intel_context *intel,