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