19bd392adSmrg/************************************************************************** 29bd392adSmrg * 39bd392adSmrg * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA 49bd392adSmrg * All Rights Reserved. 59bd392adSmrg * 69bd392adSmrg * Permission is hereby granted, free of charge, to any person obtaining a 79bd392adSmrg * copy of this software and associated documentation files (the 89bd392adSmrg * "Software"), to deal in the Software without restriction, including 99bd392adSmrg * without limitation the rights to use, copy, modify, merge, publish, 109bd392adSmrg * distribute, sub license, and/or sell copies of the Software, and to 119bd392adSmrg * permit persons to whom the Software is furnished to do so, subject to 129bd392adSmrg * the following conditions: 139bd392adSmrg * 149bd392adSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 159bd392adSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 169bd392adSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 179bd392adSmrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 189bd392adSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 199bd392adSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 209bd392adSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 219bd392adSmrg * 229bd392adSmrg * The above copyright notice and this permission notice (including the 239bd392adSmrg * next paragraph) shall be included in all copies or substantial portions 249bd392adSmrg * of the Software. 259bd392adSmrg * 269bd392adSmrg * 279bd392adSmrg **************************************************************************/ 289bd392adSmrg/* 299bd392adSmrg * Authors: Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com> 309bd392adSmrg */ 319bd392adSmrg 329bd392adSmrg#ifdef HAVE_CONFIG_H 339bd392adSmrg#include "config.h" 349bd392adSmrg#endif 359bd392adSmrg 369bd392adSmrg#include <X11/Xlib.h> 379bd392adSmrg#include <X11/Xutil.h> 389bd392adSmrg#include <stdint.h> 399bd392adSmrg#include <drm/drm.h> 409bd392adSmrg#include "xf86dri.h" 419bd392adSmrg#include "xf86drm.h" 429bd392adSmrg#include "stdio.h" 439bd392adSmrg#include "sys/types.h" 449bd392adSmrg#include <unistd.h> 459bd392adSmrg#include <string.h> 469bd392adSmrg#include <errno.h> 479bd392adSmrg#include <stdlib.h> 489bd392adSmrg#include "sys/mman.h" 499bd392adSmrg 509bd392adSmrgtypedef struct 519bd392adSmrg{ 529bd392adSmrg enum 539bd392adSmrg { 549bd392adSmrg haveNothing, 559bd392adSmrg haveDisplay, 569bd392adSmrg haveConnection, 579bd392adSmrg haveDriverName, 589bd392adSmrg haveDeviceInfo, 599bd392adSmrg haveDRM, 609bd392adSmrg haveContext 619bd392adSmrg } 629bd392adSmrg state; 639bd392adSmrg 649bd392adSmrg Display *display; 659bd392adSmrg int screen; 669bd392adSmrg drm_handle_t sAreaOffset; 679bd392adSmrg char *curBusID; 689bd392adSmrg char *driverName; 699bd392adSmrg int drmFD; 709bd392adSmrg XVisualInfo visualInfo; 719bd392adSmrg XID id; 729bd392adSmrg drm_context_t hwContext; 739bd392adSmrg void *driPriv; 749bd392adSmrg int driPrivSize; 759bd392adSmrg int fbSize; 769bd392adSmrg int fbOrigin; 779bd392adSmrg int fbStride; 789bd392adSmrg drm_handle_t fbHandle; 799bd392adSmrg int ddxDriverMajor; 809bd392adSmrg int ddxDriverMinor; 819bd392adSmrg int ddxDriverPatch; 829bd392adSmrg} TinyDRIContext; 839bd392adSmrg 849bd392adSmrg#ifndef __x86_64__ 859bd392adSmrgstatic unsigned 869bd392adSmrgfastrdtsc(void) 879bd392adSmrg{ 889bd392adSmrg unsigned eax; 899bd392adSmrg __asm__ volatile ("\t" 909bd392adSmrg "pushl %%ebx\n\t" 919bd392adSmrg "cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax) 929bd392adSmrg :"0"(0) 939bd392adSmrg :"ecx", "edx", "cc"); 949bd392adSmrg 959bd392adSmrg return eax; 969bd392adSmrg} 979bd392adSmrg#else 989bd392adSmrgstatic unsigned 999bd392adSmrgfastrdtsc(void) 1009bd392adSmrg{ 1019bd392adSmrg unsigned eax; 1029bd392adSmrg __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax) 1039bd392adSmrg :"0"(0) 1049bd392adSmrg :"ecx", "edx", "ebx", "cc"); 1059bd392adSmrg 1069bd392adSmrg return eax; 1079bd392adSmrg} 1089bd392adSmrg#endif 1099bd392adSmrg 1109bd392adSmrgvoid 1119bd392adSmrgbmError(int val, const char *file, const char *function, int line) 1129bd392adSmrg{ 1139bd392adSmrg fprintf(stderr, "Fatal video memory manager error \"%s\".\n" 1149bd392adSmrg "Check kernel logs or set the LIBGL_DEBUG\n" 1159bd392adSmrg "environment variable to \"verbose\" for more info.\n" 1169bd392adSmrg "Detected in file %s, line %d, function %s.\n", 1179bd392adSmrg strerror(-val), file, line, function); 1189bd392adSmrg abort(); 1199bd392adSmrg} 1209bd392adSmrg 1219bd392adSmrg#define BM_CKFATAL(val) \ 1229bd392adSmrg do{ \ 1239bd392adSmrg int tstVal = (val); \ 1249bd392adSmrg if (tstVal) \ 1259bd392adSmrg bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \ 1269bd392adSmrg } while(0); 1279bd392adSmrg 1289bd392adSmrgstatic unsigned 1299bd392adSmrgtime_diff(unsigned t, unsigned t2) 1309bd392adSmrg{ 1319bd392adSmrg return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); 1329bd392adSmrg} 1339bd392adSmrg 1349bd392adSmrgstatic int 1359bd392adSmrgreleaseContext(TinyDRIContext * ctx) 1369bd392adSmrg{ 1379bd392adSmrg switch (ctx->state) { 1389bd392adSmrg case haveContext: 1399bd392adSmrg uniDRIDestroyContext(ctx->display, ctx->screen, ctx->id); 1409bd392adSmrg case haveDRM: 1419bd392adSmrg drmClose(ctx->drmFD); 1429bd392adSmrg case haveDeviceInfo: 1439bd392adSmrg XFree(ctx->driPriv); 1449bd392adSmrg case haveDriverName: 1459bd392adSmrg XFree(ctx->driverName); 1469bd392adSmrg case haveConnection: 1479bd392adSmrg XFree(ctx->curBusID); 1489bd392adSmrg uniDRICloseConnection(ctx->display, ctx->screen); 1499bd392adSmrg case haveDisplay: 1509bd392adSmrg XCloseDisplay(ctx->display); 1519bd392adSmrg default: 1529bd392adSmrg break; 1539bd392adSmrg } 1549bd392adSmrg return -1; 1559bd392adSmrg} 1569bd392adSmrg 1579bd392adSmrgstatic void 1589bd392adSmrgreadBuf(void *buf, unsigned long size) 1599bd392adSmrg{ 1609bd392adSmrg volatile unsigned *buf32 = (unsigned *)buf; 1619bd392adSmrg unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32); 1629bd392adSmrg 1639bd392adSmrg while (buf32 < end) { 1649bd392adSmrg (void)*buf32++; 1659bd392adSmrg } 1669bd392adSmrg} 1679bd392adSmrg 1689bd392adSmrgstatic int 1699bd392adSmrgbenchmarkBuffer(TinyDRIContext * ctx, unsigned long size, 1709bd392adSmrg unsigned long *ticks) 1719bd392adSmrg{ 1729bd392adSmrg unsigned long curTime, oldTime; 1739bd392adSmrg int ret; 1749bd392adSmrg drmBO buf; 1759bd392adSmrg void *virtual; 1769bd392adSmrg 1779bd392adSmrg /* 1789bd392adSmrg * Test system memory objects. 1799bd392adSmrg */ 1809bd392adSmrg oldTime = fastrdtsc(); 1819bd392adSmrg BM_CKFATAL(drmBOCreate(ctx->drmFD, size, 0, NULL, 1829bd392adSmrg DRM_BO_FLAG_READ | 1839bd392adSmrg DRM_BO_FLAG_WRITE | 1849bd392adSmrg DRM_BO_FLAG_MEM_LOCAL, 0, &buf)); 1859bd392adSmrg curTime = fastrdtsc(); 1869bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 1879bd392adSmrg 1889bd392adSmrg oldTime = fastrdtsc(); 1899bd392adSmrg BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, 1909bd392adSmrg DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual)); 1919bd392adSmrg curTime = fastrdtsc(); 1929bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 1939bd392adSmrg 1949bd392adSmrg oldTime = fastrdtsc(); 1959bd392adSmrg memset(virtual, 0xF0, buf.size); 1969bd392adSmrg curTime = fastrdtsc(); 1979bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 1989bd392adSmrg 1999bd392adSmrg oldTime = fastrdtsc(); 2009bd392adSmrg memset(virtual, 0x0F, buf.size); 2019bd392adSmrg curTime = fastrdtsc(); 2029bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2039bd392adSmrg 2049bd392adSmrg oldTime = fastrdtsc(); 2059bd392adSmrg readBuf(virtual, buf.size); 2069bd392adSmrg curTime = fastrdtsc(); 2079bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2089bd392adSmrg 2099bd392adSmrg oldTime = fastrdtsc(); 2109bd392adSmrg BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); 2119bd392adSmrg curTime = fastrdtsc(); 2129bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2139bd392adSmrg 2149bd392adSmrg /* 2159bd392adSmrg * Test TT bound buffer objects. 2169bd392adSmrg */ 2179bd392adSmrg 2189bd392adSmrg oldTime = fastrdtsc(); 2199bd392adSmrg BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf, 2209bd392adSmrg DRM_BO_FLAG_MEM_TT, 2219bd392adSmrg DRM_BO_MASK_MEM, 2229bd392adSmrg 0,0,0)); 2239bd392adSmrg curTime = fastrdtsc(); 2249bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2259bd392adSmrg 2269bd392adSmrg oldTime = fastrdtsc(); 2279bd392adSmrg BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, 2289bd392adSmrg DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual)); 2299bd392adSmrg curTime = fastrdtsc(); 2309bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2319bd392adSmrg 2329bd392adSmrg oldTime = fastrdtsc(); 2339bd392adSmrg memset(virtual, 0xF0, buf.size); 2349bd392adSmrg curTime = fastrdtsc(); 2359bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2369bd392adSmrg 2379bd392adSmrg oldTime = fastrdtsc(); 2389bd392adSmrg memset(virtual, 0x0F, buf.size); 2399bd392adSmrg curTime = fastrdtsc(); 2409bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2419bd392adSmrg 2429bd392adSmrg oldTime = fastrdtsc(); 2439bd392adSmrg readBuf(virtual, buf.size); 2449bd392adSmrg curTime = fastrdtsc(); 2459bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2469bd392adSmrg 2479bd392adSmrg BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); 2489bd392adSmrg 2499bd392adSmrg oldTime = fastrdtsc(); 2509bd392adSmrg BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf, 2519bd392adSmrg DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, 0, 0,0)); 2529bd392adSmrg curTime = fastrdtsc(); 2539bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2549bd392adSmrg 2559bd392adSmrg /* 2569bd392adSmrg * Test cached buffers objects. 2579bd392adSmrg */ 2589bd392adSmrg 2599bd392adSmrg oldTime = fastrdtsc(); 2609bd392adSmrg ret = drmBOSetStatus(ctx->drmFD, &buf, 2619bd392adSmrg DRM_BO_FLAG_MEM_TT | 2629bd392adSmrg DRM_BO_FLAG_CACHED | 2639bd392adSmrg DRM_BO_FLAG_FORCE_CACHING, 2649bd392adSmrg DRM_BO_MASK_MEMTYPE | 2659bd392adSmrg DRM_BO_FLAG_FORCE_CACHING, 2669bd392adSmrg 0, 0, 0); 2679bd392adSmrg curTime = fastrdtsc(); 2689bd392adSmrg 2699bd392adSmrg if (ret) { 2709bd392adSmrg printf("Couldn't bind cached. Probably no support\n"); 2719bd392adSmrg BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf)); 2729bd392adSmrg return 1; 2739bd392adSmrg } 2749bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2759bd392adSmrg 2769bd392adSmrg oldTime = fastrdtsc(); 2779bd392adSmrg BM_CKFATAL(drmBOMap(ctx->drmFD, &buf, 2789bd392adSmrg DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual)); 2799bd392adSmrg 2809bd392adSmrg curTime = fastrdtsc(); 2819bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2829bd392adSmrg 2839bd392adSmrg oldTime = fastrdtsc(); 2849bd392adSmrg memset(virtual, 0xF0, buf.size); 2859bd392adSmrg curTime = fastrdtsc(); 2869bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2879bd392adSmrg 2889bd392adSmrg oldTime = fastrdtsc(); 2899bd392adSmrg memset(virtual, 0x0F, buf.size); 2909bd392adSmrg curTime = fastrdtsc(); 2919bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2929bd392adSmrg 2939bd392adSmrg oldTime = fastrdtsc(); 2949bd392adSmrg readBuf(virtual, buf.size); 2959bd392adSmrg curTime = fastrdtsc(); 2969bd392adSmrg *ticks++ = time_diff(oldTime, curTime); 2979bd392adSmrg 2989bd392adSmrg BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf)); 2999bd392adSmrg BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf)); 3009bd392adSmrg 3019bd392adSmrg return 0; 3029bd392adSmrg} 3039bd392adSmrg 3049bd392adSmrgstatic void 3059bd392adSmrgtestAGP(TinyDRIContext * ctx) 3069bd392adSmrg{ 3079bd392adSmrg unsigned long ticks[128], *pTicks; 3089bd392adSmrg unsigned long size = 8 * 1024; 3099bd392adSmrg int ret; 3109bd392adSmrg 3119bd392adSmrg ret = benchmarkBuffer(ctx, size, ticks); 3129bd392adSmrg if (ret < 0) { 3139bd392adSmrg fprintf(stderr, "Buffer error %s\n", strerror(-ret)); 3149bd392adSmrg return; 3159bd392adSmrg } 3169bd392adSmrg pTicks = ticks; 3179bd392adSmrg 3189bd392adSmrg printf("Buffer size %d bytes\n", size); 3199bd392adSmrg printf("System memory timings ********************************\n"); 3209bd392adSmrg printf("Creation took %12lu ticks\n", *pTicks++); 3219bd392adSmrg printf("Mapping took %12lu ticks\n", *pTicks++); 3229bd392adSmrg printf("Writing took %12lu ticks\n", *pTicks++); 3239bd392adSmrg printf("Writing Again took %12lu ticks\n", *pTicks++); 3249bd392adSmrg printf("Reading took %12lu ticks\n", *pTicks++); 3259bd392adSmrg printf("Unmapping took %12lu ticks\n", *pTicks++); 3269bd392adSmrg 3279bd392adSmrg printf("\nTT Memory timings ************************************\n"); 3289bd392adSmrg printf("Moving to TT took %12lu ticks\n", *pTicks++); 3299bd392adSmrg printf("Mapping in TT took %12lu ticks\n", *pTicks++); 3309bd392adSmrg printf("Writing to TT took %12lu ticks\n", *pTicks++); 3319bd392adSmrg printf("Writing again to TT took %12lu ticks\n", *pTicks++); 3329bd392adSmrg printf("Reading from TT took %12lu ticks\n", *pTicks++); 3339bd392adSmrg printf("Moving to system took %12lu ticks\n", *pTicks++); 3349bd392adSmrg 3359bd392adSmrg if (ret == 1) 3369bd392adSmrg return; 3379bd392adSmrg 3389bd392adSmrg printf("\nCached TT Memory timings *****************************\n"); 3399bd392adSmrg printf("Moving to CTT took %12lu ticks\n", *pTicks++); 3409bd392adSmrg printf("Mapping in CTT took %12lu ticks\n", *pTicks++); 3419bd392adSmrg printf("Writing to CTT took %12lu ticks\n", *pTicks++); 3429bd392adSmrg printf("Re-writing to CTT took %12lu ticks\n", *pTicks++); 3439bd392adSmrg printf("Reading from CTT took %12lu ticks\n", *pTicks++); 3449bd392adSmrg printf("\n\n"); 3459bd392adSmrg} 3469bd392adSmrg 3479bd392adSmrgint 3489bd392adSmrgmain() 3499bd392adSmrg{ 3509bd392adSmrg int ret, screen, isCapable; 3519bd392adSmrg char *displayName = ":0"; 3529bd392adSmrg TinyDRIContext ctx; 3539bd392adSmrg unsigned magic; 3549bd392adSmrg 3559bd392adSmrg ctx.screen = 0; 3569bd392adSmrg ctx.state = haveNothing; 3579bd392adSmrg ctx.display = XOpenDisplay(displayName); 3589bd392adSmrg if (!ctx.display) { 3599bd392adSmrg fprintf(stderr, "Could not open display\n"); 3609bd392adSmrg return releaseContext(&ctx); 3619bd392adSmrg } 3629bd392adSmrg ctx.state = haveDisplay; 3639bd392adSmrg 3649bd392adSmrg ret = 3659bd392adSmrg uniDRIQueryDirectRenderingCapable(ctx.display, ctx.screen, 3669bd392adSmrg &isCapable); 3679bd392adSmrg if (!ret || !isCapable) { 3689bd392adSmrg fprintf(stderr, "No DRI on this display:sceen\n"); 3699bd392adSmrg return releaseContext(&ctx); 3709bd392adSmrg } 3719bd392adSmrg 3729bd392adSmrg if (!uniDRIOpenConnection(ctx.display, ctx.screen, &ctx.sAreaOffset, 3739bd392adSmrg &ctx.curBusID)) { 3749bd392adSmrg fprintf(stderr, "Could not open DRI connection.\n"); 3759bd392adSmrg return releaseContext(&ctx); 3769bd392adSmrg } 3779bd392adSmrg ctx.state = haveConnection; 3789bd392adSmrg 3799bd392adSmrg if (!uniDRIGetClientDriverName(ctx.display, ctx.screen, 3809bd392adSmrg &ctx.ddxDriverMajor, &ctx.ddxDriverMinor, 3819bd392adSmrg &ctx.ddxDriverPatch, &ctx.driverName)) { 3829bd392adSmrg fprintf(stderr, "Could not get DRI driver name.\n"); 3839bd392adSmrg return releaseContext(&ctx); 3849bd392adSmrg } 3859bd392adSmrg ctx.state = haveDriverName; 3869bd392adSmrg 3879bd392adSmrg if (!uniDRIGetDeviceInfo(ctx.display, ctx.screen, 3889bd392adSmrg &ctx.fbHandle, &ctx.fbOrigin, &ctx.fbSize, 3899bd392adSmrg &ctx.fbStride, &ctx.driPrivSize, &ctx.driPriv)) { 3909bd392adSmrg fprintf(stderr, "Could not get DRI device info.\n"); 3919bd392adSmrg return releaseContext(&ctx); 3929bd392adSmrg } 3939bd392adSmrg ctx.state = haveDriverName; 3949bd392adSmrg 3959bd392adSmrg if ((ctx.drmFD = drmOpen(NULL, ctx.curBusID)) < 0) { 3969bd392adSmrg perror("DRM Device could not be opened"); 3979bd392adSmrg return releaseContext(&ctx); 3989bd392adSmrg } 3999bd392adSmrg ctx.state = haveDRM; 4009bd392adSmrg 4019bd392adSmrg drmGetMagic(ctx.drmFD, &magic); 4029bd392adSmrg if (!uniDRIAuthConnection(ctx.display, ctx.screen, magic)) { 4039bd392adSmrg fprintf(stderr, "Could not get X server to authenticate us.\n"); 4049bd392adSmrg return releaseContext(&ctx); 4059bd392adSmrg } 4069bd392adSmrg 4079bd392adSmrg ret = XMatchVisualInfo(ctx.display, ctx.screen, 24, TrueColor, 4089bd392adSmrg &ctx.visualInfo); 4099bd392adSmrg if (!ret) { 4109bd392adSmrg ret = XMatchVisualInfo(ctx.display, ctx.screen, 16, TrueColor, 4119bd392adSmrg &ctx.visualInfo); 4129bd392adSmrg if (!ret) { 4139bd392adSmrg fprintf(stderr, "Could not find a matching visual.\n"); 4149bd392adSmrg return releaseContext(&ctx); 4159bd392adSmrg } 4169bd392adSmrg } 4179bd392adSmrg 4189bd392adSmrg if (!uniDRICreateContext(ctx.display, ctx.screen, ctx.visualInfo.visual, 4199bd392adSmrg &ctx.id, &ctx.hwContext)) { 4209bd392adSmrg fprintf(stderr, "Could not create DRI context.\n"); 4219bd392adSmrg return releaseContext(&ctx); 4229bd392adSmrg } 4239bd392adSmrg ctx.state = haveContext; 4249bd392adSmrg 4259bd392adSmrg testAGP(&ctx); 4269bd392adSmrg 4279bd392adSmrg releaseContext(&ctx); 4289bd392adSmrg printf("Terminating normally\n"); 4299bd392adSmrg return 0; 4309bd392adSmrg} 431