blob: ae261e284a1583e766ff1edd3dbeb7f35eb57522 [file] [log] [blame]
Thomas Hellstrom2bc92542007-01-30 14:41:02 +01001/**************************************************************************
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
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +010032#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>
Thomas Hellstrom9968a212007-01-30 14:38:49 +010045#include <errno.h>
46#include <stdlib.h>
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +010047#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;
Thomas Hellstrom09322692007-01-30 14:42:27 +0100101 __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax)
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +0100102 :"0"(0)
Thomas Hellstrom09322692007-01-30 14:42:27 +0100103 :"ecx", "edx", "ebx", "cc");
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +0100104
105 return eax;
106}
107#endif
108
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100109void
110bmError(int val, const char *file, const char *function, int line)
111{
Thomas Hellstrom09322692007-01-30 14:42:27 +0100112 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);
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100117 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
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +0100127static 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
Thomas Hellstrom09322692007-01-30 14:42:27 +0100156static void
157readBuf(void *buf, unsigned long size)
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100158{
159 volatile unsigned *buf32 = (unsigned *)buf;
160 unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32);
161
Thomas Hellstrom09322692007-01-30 14:42:27 +0100162 while (buf32 < end) {
163 (void)*buf32++;
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100164 }
165}
166
Thomas Hellstrom09322692007-01-30 14:42:27 +0100167static int
168benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
169 unsigned long *ticks)
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100170{
171 unsigned long curTime, oldTime;
172 int ret;
173 drmBO buf;
174 void *virtual;
175
176 /*
177 * Test system memory objects.
178 */
179
Thomas Hellstrom09322692007-01-30 14:42:27 +0100180 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 |
Thomas Hellstrom07fabc32007-01-31 11:41:44 +0100185 DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_NO_MOVE, 0, &buf));
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100186 curTime = fastrdtsc();
187 *ticks++ = time_diff(oldTime, curTime);
188
Thomas Hellstrom09322692007-01-30 14:42:27 +0100189 oldTime = fastrdtsc();
190 BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
191 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100192 curTime = fastrdtsc();
193 *ticks++ = time_diff(oldTime, curTime);
194
Thomas Hellstrom09322692007-01-30 14:42:27 +0100195 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100196 memset(virtual, 0xF0, buf.size);
197 curTime = fastrdtsc();
198 *ticks++ = time_diff(oldTime, curTime);
199
Thomas Hellstrom09322692007-01-30 14:42:27 +0100200 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100201 memset(virtual, 0x0F, buf.size);
202 curTime = fastrdtsc();
203 *ticks++ = time_diff(oldTime, curTime);
204
Thomas Hellstrom09322692007-01-30 14:42:27 +0100205 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100206 readBuf(virtual, buf.size);
207 curTime = fastrdtsc();
208 *ticks++ = time_diff(oldTime, curTime);
209
Thomas Hellstrom09322692007-01-30 14:42:27 +0100210 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100211 BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
212 curTime = fastrdtsc();
213 *ticks++ = time_diff(oldTime, curTime);
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100214
215 /*
216 * Test TT bound buffer objects.
217 */
218
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100219 BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0));
Thomas Hellstrom09322692007-01-30 14:42:27 +0100220 oldTime = fastrdtsc();
221 BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf,
222 DRM_BO_FLAG_MEM_TT, DRM_BO_MASK_MEM, DRM_BO_HINT_DONT_FENCE));
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100223 curTime = fastrdtsc();
224 BM_CKFATAL(drmUnlock(ctx->drmFD, ctx->hwContext));
225 *ticks++ = time_diff(oldTime, curTime);
226
Thomas Hellstrom09322692007-01-30 14:42:27 +0100227 oldTime = fastrdtsc();
228 BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
229 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100230 curTime = fastrdtsc();
231 *ticks++ = time_diff(oldTime, curTime);
232
Thomas Hellstrom09322692007-01-30 14:42:27 +0100233 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100234 memset(virtual, 0xF0, buf.size);
235 curTime = fastrdtsc();
236 *ticks++ = time_diff(oldTime, curTime);
237
Thomas Hellstrom09322692007-01-30 14:42:27 +0100238 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100239 memset(virtual, 0x0F, buf.size);
240 curTime = fastrdtsc();
241 *ticks++ = time_diff(oldTime, curTime);
242
Thomas Hellstrom09322692007-01-30 14:42:27 +0100243 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100244 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));
Thomas Hellstrom09322692007-01-30 14:42:27 +0100251 oldTime = fastrdtsc();
252 BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf,
253 DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, DRM_BO_HINT_DONT_FENCE));
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100254 curTime = fastrdtsc();
255 *ticks++ = time_diff(oldTime, curTime);
256
257 /*
258 * Test cached buffers objects.
259 */
260
Thomas Hellstrom09322692007-01-30 14:42:27 +0100261 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);
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100265 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
Thomas Hellstrom09322692007-01-30 14:42:27 +0100275 oldTime = fastrdtsc();
276 BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
277 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100278
279 curTime = fastrdtsc();
280 *ticks++ = time_diff(oldTime, curTime);
281
Thomas Hellstrom09322692007-01-30 14:42:27 +0100282 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100283 memset(virtual, 0xF0, buf.size);
284 curTime = fastrdtsc();
285 *ticks++ = time_diff(oldTime, curTime);
286
Thomas Hellstrom09322692007-01-30 14:42:27 +0100287 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100288 memset(virtual, 0x0F, buf.size);
289 curTime = fastrdtsc();
290 *ticks++ = time_diff(oldTime, curTime);
291
Thomas Hellstrom09322692007-01-30 14:42:27 +0100292 oldTime = fastrdtsc();
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100293 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;
Thomas Hellstrom09322692007-01-30 14:42:27 +0100301}
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100302
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +0100303static void
304testAGP(TinyDRIContext * ctx)
305{
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100306 unsigned long ticks[128], *pTicks;
Thomas Hellstrom09322692007-01-30 14:42:27 +0100307 unsigned long size = 4096 * 1024;
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100308 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++);
Thomas Hellstrom09322692007-01-30 14:42:27 +0100330 printf("Writing again to TT took %12lu ticks\n", *pTicks++);
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100331 printf("Reading from TT took %12lu ticks\n", *pTicks++);
Thomas Hellstrom09322692007-01-30 14:42:27 +0100332 printf("Moving to system took %12lu ticks\n", *pTicks++);
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100333
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++);
Thomas Hellstrom09322692007-01-30 14:42:27 +0100341 printf("Re-writing to CTT took %12lu ticks\n", *pTicks++);
Thomas Hellstrom9968a212007-01-30 14:38:49 +0100342 printf("Reading from CTT took %12lu ticks\n", *pTicks++);
343 printf("\n\n");
Thomas Hellstromc01fe2c2007-01-30 12:56:51 +0100344}
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}