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