ttmtest.c revision 9968a21be11a3d64dac9daab768a11d729cdd77c
1#ifdef HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include <X11/Xlib.h> 6#include <X11/Xutil.h> 7#include <drm/drm.h> 8#include "xf86dri.h" 9#include "xf86drm.h" 10#include "stdio.h" 11#include "sys/types.h" 12#include <unistd.h> 13#include <string.h> 14#include <errno.h> 15#include <stdlib.h> 16#include "sys/mman.h" 17 18 19typedef struct 20{ 21 enum 22 { 23 haveNothing, 24 haveDisplay, 25 haveConnection, 26 haveDriverName, 27 haveDeviceInfo, 28 haveDRM, 29 haveContext 30 } 31 state; 32 33 Display *display; 34 int screen; 35 drm_handle_t sAreaOffset; 36 char *curBusID; 37 char *driverName; 38 int drmFD; 39 XVisualInfo visualInfo; 40 XID id; 41 drm_context_t hwContext; 42 void *driPriv; 43 int driPrivSize; 44 int fbSize; 45 int fbOrigin; 46 int fbStride; 47 drm_handle_t fbHandle; 48 int ddxDriverMajor; 49 int ddxDriverMinor; 50 int ddxDriverPatch; 51} TinyDRIContext; 52 53#ifndef __x86_64__ 54static unsigned 55fastrdtsc(void) 56{ 57 unsigned eax; 58 __asm__ volatile ("\t" 59 "pushl %%ebx\n\t" 60 "cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax) 61 :"0"(0) 62 :"ecx", "edx", "cc"); 63 64 return eax; 65} 66#else 67static unsigned 68fastrdtsc(void) 69{ 70 unsigned eax; 71 __asm__ volatile ("\t" 72 "cpuid\n\t" ".byte 0x0f, 0x31\n\t" :"=a" (eax) 73 :"0"(0) 74 :"ecx", "edx", "ebx", "cc"); 75 76 return eax; 77} 78#endif 79 80 81void 82bmError(int val, const char *file, const char *function, int line) 83{ 84 fprintf(stderr,"Fatal video memory manager error \"%s\".\n" 85 "Check kernel logs or set the LIBGL_DEBUG\n" 86 "environment variable to \"verbose\" for more info.\n" 87 "Detected in file %s, line %d, function %s.\n", 88 strerror(-val), file, line, function); 89 abort(); 90} 91 92#define BM_CKFATAL(val) \ 93 do{ \ 94 int tstVal = (val); \ 95 if (tstVal) \ 96 bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \ 97 } while(0); 98 99 100 101static unsigned 102time_diff(unsigned t, unsigned t2) 103{ 104 return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); 105} 106 107static int 108releaseContext(TinyDRIContext * ctx) 109{ 110 switch (ctx->state) { 111 case haveContext: 112 uniDRIDestroyContext(ctx->display, ctx->screen, ctx->id); 113 case haveDRM: 114 drmClose(ctx->drmFD); 115 case haveDeviceInfo: 116 XFree(ctx->driPriv); 117 case haveDriverName: 118 XFree(ctx->driverName); 119 case haveConnection: 120 XFree(ctx->curBusID); 121 uniDRICloseConnection(ctx->display, ctx->screen); 122 case haveDisplay: 123 XCloseDisplay(ctx->display); 124 default: 125 break; 126 } 127 return -1; 128} 129 130static void readBuf(void *buf, unsigned long size) 131{ 132 volatile unsigned *buf32 = (unsigned *)buf; 133 unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32); 134 135 while(buf32 < end) { 136 (void) *buf32++; 137 } 138} 139 140 141static int benchmarkBuffer(TinyDRIContext *ctx, unsigned long size, 142 unsigned long *ticks) 143{ 144 unsigned long curTime, oldTime; 145 int ret; 146 drmBO buf; 147 void *virtual; 148 149 /* 150 * Test system memory objects. 151 */ 152 153 154 oldTime = fastrdtsc(); 155 BM_CKFATAL(drmBOCreate(ctx->drmFD, 0, size, 0, NULL, 156 drm_bo_type_dc, 157 DRM_BO_FLAG_READ | 158 DRM_BO_FLAG_WRITE | 159 DRM_BO_FLAG_MEM_LOCAL | 160 DRM_BO_FLAG_NO_EVICT, 0, &buf)); 161 curTime = fastrdtsc(); 162 *ticks++ = time_diff(oldTime, curTime); 163 164 oldTime = fastrdtsc(); 165 BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, 166 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, 167 &virtual)); 168 curTime = fastrdtsc(); 169 *ticks++ = time_diff(oldTime, curTime); 170 171 oldTime = fastrdtsc(); 172 memset(virtual, 0xF0, buf.size); 173 curTime = fastrdtsc(); 174 *ticks++ = time_diff(oldTime, curTime); 175 176 oldTime = fastrdtsc(); 177 memset(virtual, 0x0F, buf.size); 178 curTime = fastrdtsc(); 179 *ticks++ = time_diff(oldTime, curTime); 180 181 oldTime = fastrdtsc(); 182 readBuf(virtual, buf.size); 183 curTime = fastrdtsc(); 184 *ticks++ = time_diff(oldTime, curTime); 185 186 oldTime = fastrdtsc(); 187 BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); 188 curTime = fastrdtsc(); 189 *ticks++ = time_diff(oldTime, curTime); 190 191 192 /* 193 * Test TT bound buffer objects. 194 */ 195 196 197 BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0)); 198 oldTime = fastrdtsc(); 199 BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf, 200 DRM_BO_FLAG_MEM_TT, DRM_BO_MASK_MEM, 201 DRM_BO_HINT_DONT_FENCE)); 202 curTime = fastrdtsc(); 203 BM_CKFATAL(drmUnlock(ctx->drmFD, ctx->hwContext)); 204 *ticks++ = time_diff(oldTime, curTime); 205 206 oldTime = fastrdtsc(); 207 BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, 208 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, 209 &virtual)); 210 curTime = fastrdtsc(); 211 *ticks++ = time_diff(oldTime, curTime); 212 213 oldTime = fastrdtsc(); 214 memset(virtual, 0xF0, buf.size); 215 curTime = fastrdtsc(); 216 *ticks++ = time_diff(oldTime, curTime); 217 218 oldTime = fastrdtsc(); 219 memset(virtual, 0x0F, buf.size); 220 curTime = fastrdtsc(); 221 *ticks++ = time_diff(oldTime, curTime); 222 223 oldTime = fastrdtsc(); 224 readBuf(virtual, buf.size); 225 curTime = fastrdtsc(); 226 *ticks++ = time_diff(oldTime, curTime); 227 228 BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); 229 230 BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0)); 231 oldTime = fastrdtsc(); 232 BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf, 233 DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, 234 DRM_BO_HINT_DONT_FENCE)); 235 curTime = fastrdtsc(); 236 *ticks++ = time_diff(oldTime, curTime); 237 238 /* 239 * Test cached buffers objects. 240 */ 241 242 oldTime = fastrdtsc(); 243 ret = drmBOValidate(ctx->drmFD, &buf, 244 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_BIND_CACHED, 245 DRM_BO_MASK_MEM | DRM_BO_FLAG_BIND_CACHED, 246 DRM_BO_HINT_DONT_FENCE); 247 curTime = fastrdtsc(); 248 drmUnlock(ctx->drmFD, ctx->hwContext); 249 250 if (ret) { 251 printf("Couldn't bind cached. Probably no support\n"); 252 BM_CKFATAL(drmBODestroy(ctx->drmFD, &buf)); 253 return 1; 254 } 255 *ticks++ = time_diff(oldTime, curTime); 256 257 oldTime = fastrdtsc(); 258 BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, 259 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, 260 &virtual)); 261 262 263 curTime = fastrdtsc(); 264 *ticks++ = time_diff(oldTime, curTime); 265 266 oldTime = fastrdtsc(); 267 memset(virtual, 0xF0, buf.size); 268 curTime = fastrdtsc(); 269 *ticks++ = time_diff(oldTime, curTime); 270 271 oldTime = fastrdtsc(); 272 memset(virtual, 0x0F, buf.size); 273 curTime = fastrdtsc(); 274 *ticks++ = time_diff(oldTime, curTime); 275 276 oldTime = fastrdtsc(); 277 readBuf(virtual, buf.size); 278 curTime = fastrdtsc(); 279 *ticks++ = time_diff(oldTime, curTime); 280 281 BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); 282 BM_CKFATAL(drmBODestroy(ctx->drmFD, &buf)); 283 284 return 0; 285} 286 287 288static void 289testAGP(TinyDRIContext * ctx) 290{ 291 unsigned long ticks[128], *pTicks; 292 unsigned long size = 4096*1024; 293 int ret; 294 295 ret = benchmarkBuffer(ctx, size, ticks); 296 if (ret < 0) { 297 fprintf(stderr, "Buffer error %s\n", strerror(-ret)); 298 return; 299 } 300 pTicks = ticks; 301 302 printf("Buffer size %d bytes\n", size); 303 printf("System memory timings ********************************\n"); 304 printf("Creation took %12lu ticks\n", *pTicks++); 305 printf("Mapping took %12lu ticks\n", *pTicks++); 306 printf("Writing took %12lu ticks\n", *pTicks++); 307 printf("Writing Again took %12lu ticks\n", *pTicks++); 308 printf("Reading took %12lu ticks\n", *pTicks++); 309 printf("Unmapping took %12lu ticks\n", *pTicks++); 310 311 printf("\nTT Memory timings ************************************\n"); 312 printf("Moving to TT took %12lu ticks\n", *pTicks++); 313 printf("Mapping in TT took %12lu ticks\n", *pTicks++); 314 printf("Writing to TT took %12lu ticks\n", *pTicks++); 315 printf("Writing again to TT took %12lu ticks\n", *pTicks++); 316 printf("Reading from TT took %12lu ticks\n", *pTicks++); 317 printf("Moving to system took %12lu ticks\n", *pTicks++); 318 319 if (ret == 1) 320 return; 321 322 printf("\nCached TT Memory timings *****************************\n"); 323 printf("Moving to CTT took %12lu ticks\n", *pTicks++); 324 printf("Mapping in CTT took %12lu ticks\n", *pTicks++); 325 printf("Writing to CTT took %12lu ticks\n", *pTicks++); 326 printf("Re-writing to CTT took %12lu ticks\n", *pTicks++); 327 printf("Reading from CTT took %12lu ticks\n", *pTicks++); 328 printf("\n\n"); 329} 330 331int 332main() 333{ 334 int ret, screen, isCapable; 335 char *displayName = ":0"; 336 TinyDRIContext ctx; 337 unsigned magic; 338 339 ctx.screen = 0; 340 ctx.state = haveNothing; 341 ctx.display = XOpenDisplay(displayName); 342 if (!ctx.display) { 343 fprintf(stderr, "Could not open display\n"); 344 return releaseContext(&ctx); 345 } 346 ctx.state = haveDisplay; 347 348 ret = 349 uniDRIQueryDirectRenderingCapable(ctx.display, ctx.screen, 350 &isCapable); 351 if (!ret || !isCapable) { 352 fprintf(stderr, "No DRI on this display:sceen\n"); 353 return releaseContext(&ctx); 354 } 355 356 if (!uniDRIOpenConnection(ctx.display, ctx.screen, &ctx.sAreaOffset, 357 &ctx.curBusID)) { 358 fprintf(stderr, "Could not open DRI connection.\n"); 359 return releaseContext(&ctx); 360 } 361 ctx.state = haveConnection; 362 363 if (!uniDRIGetClientDriverName(ctx.display, ctx.screen, 364 &ctx.ddxDriverMajor, &ctx.ddxDriverMinor, 365 &ctx.ddxDriverPatch, &ctx.driverName)) { 366 fprintf(stderr, "Could not get DRI driver name.\n"); 367 return releaseContext(&ctx); 368 } 369 ctx.state = haveDriverName; 370 371 if (!uniDRIGetDeviceInfo(ctx.display, ctx.screen, 372 &ctx.fbHandle, &ctx.fbOrigin, &ctx.fbSize, 373 &ctx.fbStride, &ctx.driPrivSize, &ctx.driPriv)) { 374 fprintf(stderr, "Could not get DRI device info.\n"); 375 return releaseContext(&ctx); 376 } 377 ctx.state = haveDriverName; 378 379 if ((ctx.drmFD = drmOpen(NULL, ctx.curBusID)) < 0) { 380 perror("DRM Device could not be opened"); 381 return releaseContext(&ctx); 382 } 383 ctx.state = haveDRM; 384 385 drmGetMagic(ctx.drmFD, &magic); 386 if (!uniDRIAuthConnection(ctx.display, ctx.screen, magic)) { 387 fprintf(stderr, "Could not get X server to authenticate us.\n"); 388 return releaseContext(&ctx); 389 } 390 391 ret = XMatchVisualInfo(ctx.display, ctx.screen, 24, TrueColor, 392 &ctx.visualInfo); 393 if (!ret) { 394 ret = XMatchVisualInfo(ctx.display, ctx.screen, 16, TrueColor, 395 &ctx.visualInfo); 396 if (!ret) { 397 fprintf(stderr, "Could not find a matching visual.\n"); 398 return releaseContext(&ctx); 399 } 400 } 401 402 if (!uniDRICreateContext(ctx.display, ctx.screen, ctx.visualInfo.visual, 403 &ctx.id, &ctx.hwContext)) { 404 fprintf(stderr, "Could not create DRI context.\n"); 405 return releaseContext(&ctx); 406 } 407 ctx.state = haveContext; 408 409 testAGP(&ctx); 410 411 releaseContext(&ctx); 412 printf("Terminating normally\n"); 413 return 0; 414} 415