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