diff options
Diffstat (limited to 'tests/ttmtest/src/ttmtest.c')
-rw-r--r-- | tests/ttmtest/src/ttmtest.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/tests/ttmtest/src/ttmtest.c b/tests/ttmtest/src/ttmtest.c new file mode 100644 index 00000000..ae261e28 --- /dev/null +++ b/tests/ttmtest/src/ttmtest.c @@ -0,0 +1,429 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <drm/drm.h> +#include "xf86dri.h" +#include "xf86drm.h" +#include "stdio.h" +#include "sys/types.h" +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include "sys/mman.h" + +typedef struct +{ + enum + { + haveNothing, + haveDisplay, + haveConnection, + haveDriverName, + haveDeviceInfo, + haveDRM, + haveContext + } + state; + + Display *display; + int screen; + drm_handle_t sAreaOffset; + char *curBusID; + char *driverName; + int drmFD; + XVisualInfo visualInfo; + XID id; + drm_context_t hwContext; + void *driPriv; + int driPrivSize; + int fbSize; + int fbOrigin; + int fbStride; + drm_handle_t fbHandle; + int ddxDriverMajor; + int ddxDriverMinor; + int ddxDriverPatch; +} TinyDRIContext; + +#ifndef __x86_64__ +static unsigned +fastrdtsc(void) +{ + unsigned eax; + __asm__ volatile ("\t" + "pushl %%ebx\n\t" + "cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax) + :"0"(0) + :"ecx", "edx", "cc"); + + return eax; +} +#else +static unsigned +fastrdtsc(void) +{ + unsigned eax; + __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax) + :"0"(0) + :"ecx", "edx", "ebx", "cc"); + + return eax; +} +#endif + +void +bmError(int val, const char *file, const char *function, int line) +{ + fprintf(stderr, "Fatal video memory manager error \"%s\".\n" + "Check kernel logs or set the LIBGL_DEBUG\n" + "environment variable to \"verbose\" for more info.\n" + "Detected in file %s, line %d, function %s.\n", + strerror(-val), file, line, function); + abort(); +} + +#define BM_CKFATAL(val) \ + do{ \ + int tstVal = (val); \ + if (tstVal) \ + bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \ + } while(0); + +static unsigned +time_diff(unsigned t, unsigned t2) +{ + return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); +} + +static int +releaseContext(TinyDRIContext * ctx) +{ + switch (ctx->state) { + case haveContext: + uniDRIDestroyContext(ctx->display, ctx->screen, ctx->id); + case haveDRM: + drmClose(ctx->drmFD); + case haveDeviceInfo: + XFree(ctx->driPriv); + case haveDriverName: + XFree(ctx->driverName); + case haveConnection: + XFree(ctx->curBusID); + uniDRICloseConnection(ctx->display, ctx->screen); + case haveDisplay: + XCloseDisplay(ctx->display); + default: + break; + } + return -1; +} + +static void +readBuf(void *buf, unsigned long size) +{ + volatile unsigned *buf32 = (unsigned *)buf; + unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32); + + while (buf32 < end) { + (void)*buf32++; + } +} + +static int +benchmarkBuffer(TinyDRIContext * ctx, unsigned long size, + unsigned long *ticks) +{ + unsigned long curTime, oldTime; + int ret; + drmBO buf; + void *virtual; + + /* + * Test system memory objects. + */ + + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOCreate(ctx->drmFD, 0, size, 0, NULL, + drm_bo_type_dc, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_NO_MOVE, 0, &buf)); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual)); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + memset(virtual, 0xF0, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + memset(virtual, 0x0F, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + readBuf(virtual, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + /* + * Test TT bound buffer objects. + */ + + BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0)); + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf, + DRM_BO_FLAG_MEM_TT, DRM_BO_MASK_MEM, DRM_BO_HINT_DONT_FENCE)); + curTime = fastrdtsc(); + BM_CKFATAL(drmUnlock(ctx->drmFD, ctx->hwContext)); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual)); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + memset(virtual, 0xF0, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + memset(virtual, 0x0F, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + readBuf(virtual, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); + + BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0)); + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf, + DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, DRM_BO_HINT_DONT_FENCE)); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + /* + * Test cached buffers objects. + */ + + oldTime = fastrdtsc(); + ret = drmBOValidate(ctx->drmFD, &buf, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_BIND_CACHED, + DRM_BO_MASK_MEM | DRM_BO_FLAG_BIND_CACHED, DRM_BO_HINT_DONT_FENCE); + curTime = fastrdtsc(); + drmUnlock(ctx->drmFD, ctx->hwContext); + + if (ret) { + printf("Couldn't bind cached. Probably no support\n"); + BM_CKFATAL(drmBODestroy(ctx->drmFD, &buf)); + return 1; + } + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual)); + + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + memset(virtual, 0xF0, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + memset(virtual, 0x0F, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + oldTime = fastrdtsc(); + readBuf(virtual, buf.size); + curTime = fastrdtsc(); + *ticks++ = time_diff(oldTime, curTime); + + BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); + BM_CKFATAL(drmBODestroy(ctx->drmFD, &buf)); + + return 0; +} + +static void +testAGP(TinyDRIContext * ctx) +{ + unsigned long ticks[128], *pTicks; + unsigned long size = 4096 * 1024; + int ret; + + ret = benchmarkBuffer(ctx, size, ticks); + if (ret < 0) { + fprintf(stderr, "Buffer error %s\n", strerror(-ret)); + return; + } + pTicks = ticks; + + printf("Buffer size %d bytes\n", size); + printf("System memory timings ********************************\n"); + printf("Creation took %12lu ticks\n", *pTicks++); + printf("Mapping took %12lu ticks\n", *pTicks++); + printf("Writing took %12lu ticks\n", *pTicks++); + printf("Writing Again took %12lu ticks\n", *pTicks++); + printf("Reading took %12lu ticks\n", *pTicks++); + printf("Unmapping took %12lu ticks\n", *pTicks++); + + printf("\nTT Memory timings ************************************\n"); + printf("Moving to TT took %12lu ticks\n", *pTicks++); + printf("Mapping in TT took %12lu ticks\n", *pTicks++); + printf("Writing to TT took %12lu ticks\n", *pTicks++); + printf("Writing again to TT took %12lu ticks\n", *pTicks++); + printf("Reading from TT took %12lu ticks\n", *pTicks++); + printf("Moving to system took %12lu ticks\n", *pTicks++); + + if (ret == 1) + return; + + printf("\nCached TT Memory timings *****************************\n"); + printf("Moving to CTT took %12lu ticks\n", *pTicks++); + printf("Mapping in CTT took %12lu ticks\n", *pTicks++); + printf("Writing to CTT took %12lu ticks\n", *pTicks++); + printf("Re-writing to CTT took %12lu ticks\n", *pTicks++); + printf("Reading from CTT took %12lu ticks\n", *pTicks++); + printf("\n\n"); +} + +int +main() +{ + int ret, screen, isCapable; + char *displayName = ":0"; + TinyDRIContext ctx; + unsigned magic; + + ctx.screen = 0; + ctx.state = haveNothing; + ctx.display = XOpenDisplay(displayName); + if (!ctx.display) { + fprintf(stderr, "Could not open display\n"); + return releaseContext(&ctx); + } + ctx.state = haveDisplay; + + ret = + uniDRIQueryDirectRenderingCapable(ctx.display, ctx.screen, + &isCapable); + if (!ret || !isCapable) { + fprintf(stderr, "No DRI on this display:sceen\n"); + return releaseContext(&ctx); + } + + if (!uniDRIOpenConnection(ctx.display, ctx.screen, &ctx.sAreaOffset, + &ctx.curBusID)) { + fprintf(stderr, "Could not open DRI connection.\n"); + return releaseContext(&ctx); + } + ctx.state = haveConnection; + + if (!uniDRIGetClientDriverName(ctx.display, ctx.screen, + &ctx.ddxDriverMajor, &ctx.ddxDriverMinor, + &ctx.ddxDriverPatch, &ctx.driverName)) { + fprintf(stderr, "Could not get DRI driver name.\n"); + return releaseContext(&ctx); + } + ctx.state = haveDriverName; + + if (!uniDRIGetDeviceInfo(ctx.display, ctx.screen, + &ctx.fbHandle, &ctx.fbOrigin, &ctx.fbSize, + &ctx.fbStride, &ctx.driPrivSize, &ctx.driPriv)) { + fprintf(stderr, "Could not get DRI device info.\n"); + return releaseContext(&ctx); + } + ctx.state = haveDriverName; + + if ((ctx.drmFD = drmOpen(NULL, ctx.curBusID)) < 0) { + perror("DRM Device could not be opened"); + return releaseContext(&ctx); + } + ctx.state = haveDRM; + + drmGetMagic(ctx.drmFD, &magic); + if (!uniDRIAuthConnection(ctx.display, ctx.screen, magic)) { + fprintf(stderr, "Could not get X server to authenticate us.\n"); + return releaseContext(&ctx); + } + + ret = XMatchVisualInfo(ctx.display, ctx.screen, 24, TrueColor, + &ctx.visualInfo); + if (!ret) { + ret = XMatchVisualInfo(ctx.display, ctx.screen, 16, TrueColor, + &ctx.visualInfo); + if (!ret) { + fprintf(stderr, "Could not find a matching visual.\n"); + return releaseContext(&ctx); + } + } + + if (!uniDRICreateContext(ctx.display, ctx.screen, ctx.visualInfo.visual, + &ctx.id, &ctx.hwContext)) { + fprintf(stderr, "Could not create DRI context.\n"); + return releaseContext(&ctx); + } + ctx.state = haveContext; + + testAGP(&ctx); + + releaseContext(&ctx); + printf("Terminating normally\n"); + return 0; +} |