summaryrefslogtreecommitdiff
path: root/shared-core/r300_cmdbuf.c
AgeCommit message (Expand)Author
2008-05-23r500: add two more register ranges for mesa driver to setupDave Airlie
2008-05-17r500: add more register ranges for Mesa driverDave Airlie
2008-05-05r500: add allowed range for us config/pixsizeDave Airlie
2008-03-30drm/r300: fix wait interface mixupDave Airlie
2008-03-29r300: Correctly translate the value for the R300_CMD_WAIT command.Oliver McFadden
2008-03-21r500: fragment program upload is also used to upload constants.Dave Airlie
2008-03-20drm: fixup r500fp submissionDave Airlie
2008-03-19move some more r300 regs into not allowed on r500Dave Airlie
2008-03-17initial r500 RS and FP register and upload codeDave Airlie
2007-11-27r500: add a bunch of all r5xx pci ids..Dave Airlie
2007-11-21r500: suggestion from glisse to not add cliprect offset on r5xxDave Airlie
2007-11-05drm: remove lots of spurious whitespace.Dave Airlie
2007-07-20Replace filp in ioctl arguments with drm_file *file_priv.Eric Anholt
2007-07-20Remove DRM_ERR OS macro.Eric Anholt
2007-07-16drm: remove drm_buf_tDave Airlie
2007-07-16drm: remove drmP.h internal typedefsDave Airlie
2007-07-16drm: detypedef drm.h and fixup all problemsDave Airlie
2007-06-21r300: Allow writes to R300_VAP_PVS_WAITIDLE.Oliver McFadden
2007-06-18r300: Registers 0x2220-0x2230 are known as R300_VAP_CLIP_X_0-R300_VAP_CLIP_Y_1.Oliver McFadden
2007-05-06r300: Use the defined names for known registers.Oliver McFadden
2007-03-13r300: Renamed the CACHE_CTLSTAT values to include UNKNOWN in the name; notOliver McFadden
2007-03-13Add defines for the values written to R300_RB3D_ZCACHE_CTLSTAT.Oliver McFadden
2007-03-13Corrected values written to R300_RB3D_DSTCACHE_CTLSTAT to eitherOliver McFadden
2007-03-13Guess another unknown register used for R300 pacification.Oliver McFadden
2006-12-14Unify radeon offset checking.Michel Dänzer
2006-10-10only allow specific type-3 packets to pass the verifier instead of all for r1...Roland Scheidegger
2006-04-23Fix from Benh for ppc r300 scratchDave Airlie
2006-04-08Compile fixes for FreeBSD.Eric Anholt
2006-03-25radeon fix up the PCI ids for new memory map like the kernel one.. notDave Airlie
2006-03-07ia64 support for r300_scratch. (not tested)Aapo Tahkola
2006-03-06Add general-purpose packet for manipulating scratch registers (r300)Aapo Tahkola
2006-02-19missed a piece of benh patchDave Airlie
2006-02-18fix brace placementDave Airlie
2006-02-18add proper checking for bitblt multiDave Airlie
2006-02-18major realigment of DRM CVS with kernel code, makes integration much easierDave Airlie
2006-01-20Add support for texture cache flushes (R300_TX_CNTL)Aapo Tahkola
2006-01-20Sync from r300_reg.h from Mesa.Aapo Tahkola
2006-01-02The radeon DRM wasn't passing sparse checking in the kernel, this fixes itDave Airlie
2005-12-05add texrect support for r300Dave Airlie
2005-07-28Fix issues with buffer aging when more than one dma buffer is discarded inEric Anholt
2005-07-20Add latest r300 support from r300.sf.net CVS. Patch submitted by volodya,Eric Anholt
id='n325' href='#n325'>325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
/**************************************************************************
 * 
 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
 * All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 * 
 * 
 **************************************************************************/
/*
 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdint.h>
#include <drm/drm.h>
#include "xf86dri.h"
#include "xf86drm.h"
#include "stdio.h"
#include "sys/types.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "sys/mman.h"

typedef struct
{
    enum
    {
	haveNothing,
	haveDisplay,
	haveConnection,
	haveDriverName,
	haveDeviceInfo,
	haveDRM,
	haveContext
    }
    state;

    Display *display;
    int screen;
    drm_handle_t sAreaOffset;
    char *curBusID;
    char *driverName;
    int drmFD;
    XVisualInfo visualInfo;
    XID id;
    drm_context_t hwContext;
    void *driPriv;
    int driPrivSize;
    int fbSize;
    int fbOrigin;
    int fbStride;
    drm_handle_t fbHandle;
    int ddxDriverMajor;
    int ddxDriverMinor;
    int ddxDriverPatch;
} TinyDRIContext;

#ifndef __x86_64__
static unsigned
fastrdtsc(void)
{
    unsigned eax;
    __asm__ volatile ("\t"
	"pushl  %%ebx\n\t"
	"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax)
	:"0"(0)
	:"ecx", "edx", "cc");

    return eax;
}
#else
static unsigned
fastrdtsc(void)
{
    unsigned eax;
    __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax)
	:"0"(0)
	:"ecx", "edx", "ebx", "cc");

    return eax;
}
#endif

void
bmError(int val, const char *file, const char *function, int line)
{
    fprintf(stderr, "Fatal video memory manager error \"%s\".\n"
	"Check kernel logs or set the LIBGL_DEBUG\n"
	"environment variable to \"verbose\" for more info.\n"
	"Detected in file %s, line %d, function %s.\n",
	strerror(-val), file, line, function);
    abort();
}

#define BM_CKFATAL(val)					       \
  do{							       \
    int tstVal = (val);					       \
    if (tstVal) 					       \
      bmError(tstVal, __FILE__, __FUNCTION__, __LINE__);       \
  } while(0);

static unsigned
time_diff(unsigned t, unsigned t2)
{
    return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
}

static int
releaseContext(TinyDRIContext * ctx)
{
    switch (ctx->state) {
    case haveContext:
	uniDRIDestroyContext(ctx->display, ctx->screen, ctx->id);
    case haveDRM:
	drmClose(ctx->drmFD);
    case haveDeviceInfo:
	XFree(ctx->driPriv);
    case haveDriverName:
	XFree(ctx->driverName);
    case haveConnection:
	XFree(ctx->curBusID);
	uniDRICloseConnection(ctx->display, ctx->screen);
    case haveDisplay:
	XCloseDisplay(ctx->display);
    default:
	break;
    }
    return -1;
}

static void
readBuf(void *buf, unsigned long size)
{
    volatile unsigned *buf32 = (unsigned *)buf;
    unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32);

    while (buf32 < end) {
	(void)*buf32++;
    }
}

static int
benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
    unsigned long *ticks)
{
    unsigned long curTime, oldTime;
    int ret;
    drmBO buf;
    void *virtual;

    /*
     * Test system memory objects.
     */
    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOCreate(ctx->drmFD, size, 0, NULL,
			   DRM_BO_FLAG_READ |
			   DRM_BO_FLAG_WRITE |
			   DRM_BO_FLAG_MEM_LOCAL, 0, &buf));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
	    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0xF0, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0x0F, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    readBuf(virtual, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    /*
     * Test TT bound buffer objects.
     */

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
			     DRM_BO_FLAG_MEM_TT, 
			     DRM_BO_MASK_MEM, 
			      0,0,0));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
	    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0xF0, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0x0F, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    readBuf(virtual, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
			     DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, 0, 0,0));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    /*
     * Test cached buffers objects.
     */

    oldTime = fastrdtsc();
    ret = drmBOSetStatus(ctx->drmFD, &buf,
			 DRM_BO_FLAG_MEM_TT | 
			 DRM_BO_FLAG_CACHED | 
			 DRM_BO_FLAG_FORCE_CACHING,
			 DRM_BO_MASK_MEMTYPE | 
			 DRM_BO_FLAG_FORCE_CACHING,
			 0, 0, 0);
    curTime = fastrdtsc();

    if (ret) {
	printf("Couldn't bind cached. Probably no support\n");
	BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));
	return 1;
    }
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
	    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));

    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0xF0, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0x0F, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    readBuf(virtual, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
    BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));

    return 0;
}

static void
testAGP(TinyDRIContext * ctx)
{
    unsigned long ticks[128], *pTicks;
    unsigned long size = 8 * 1024;
    int ret;

    ret = benchmarkBuffer(ctx, size, ticks);
    if (ret < 0) {
	fprintf(stderr, "Buffer error %s\n", strerror(-ret));
	return;
    }
    pTicks = ticks;

    printf("Buffer size %d bytes\n", size);
    printf("System memory timings ********************************\n");
    printf("Creation took            %12lu ticks\n", *pTicks++);
    printf("Mapping took             %12lu ticks\n", *pTicks++);
    printf("Writing took             %12lu ticks\n", *pTicks++);
    printf("Writing Again took       %12lu ticks\n", *pTicks++);
    printf("Reading took             %12lu ticks\n", *pTicks++);
    printf("Unmapping took           %12lu ticks\n", *pTicks++);

    printf("\nTT Memory timings ************************************\n");
    printf("Moving to TT took        %12lu ticks\n", *pTicks++);
    printf("Mapping in TT took       %12lu ticks\n", *pTicks++);
    printf("Writing to TT took       %12lu ticks\n", *pTicks++);
    printf("Writing again to TT took %12lu ticks\n", *pTicks++);
    printf("Reading from TT took     %12lu ticks\n", *pTicks++);
    printf("Moving to system took    %12lu ticks\n", *pTicks++);

    if (ret == 1)
	return;

    printf("\nCached TT Memory timings *****************************\n");
    printf("Moving to CTT took       %12lu ticks\n", *pTicks++);
    printf("Mapping in CTT took      %12lu ticks\n", *pTicks++);
    printf("Writing to CTT took      %12lu ticks\n", *pTicks++);
    printf("Re-writing to CTT took   %12lu ticks\n", *pTicks++);
    printf("Reading from CTT took    %12lu ticks\n", *pTicks++);
    printf("\n\n");
}

int
main()
{
    int ret, screen, isCapable;
    char *displayName = ":0";
    TinyDRIContext ctx;
    unsigned magic;

    ctx.screen = 0;
    ctx.state = haveNothing;
    ctx.display = XOpenDisplay(displayName);
    if (!ctx.display) {
	fprintf(stderr, "Could not open display\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveDisplay;

    ret =
	uniDRIQueryDirectRenderingCapable(ctx.display, ctx.screen,
	&isCapable);
    if (!ret || !isCapable) {
	fprintf(stderr, "No DRI on this display:sceen\n");
	return releaseContext(&ctx);
    }

    if (!uniDRIOpenConnection(ctx.display, ctx.screen, &ctx.sAreaOffset,
	    &ctx.curBusID)) {
	fprintf(stderr, "Could not open DRI connection.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveConnection;

    if (!uniDRIGetClientDriverName(ctx.display, ctx.screen,
	    &ctx.ddxDriverMajor, &ctx.ddxDriverMinor,
	    &ctx.ddxDriverPatch, &ctx.driverName)) {
	fprintf(stderr, "Could not get DRI driver name.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveDriverName;

    if (!uniDRIGetDeviceInfo(ctx.display, ctx.screen,
	    &ctx.fbHandle, &ctx.fbOrigin, &ctx.fbSize,
	    &ctx.fbStride, &ctx.driPrivSize, &ctx.driPriv)) {
	fprintf(stderr, "Could not get DRI device info.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveDriverName;

    if ((ctx.drmFD = drmOpen(NULL, ctx.curBusID)) < 0) {
	perror("DRM Device could not be opened");
	return releaseContext(&ctx);
    }
    ctx.state = haveDRM;

    drmGetMagic(ctx.drmFD, &magic);
    if (!uniDRIAuthConnection(ctx.display, ctx.screen, magic)) {
	fprintf(stderr, "Could not get X server to authenticate us.\n");
	return releaseContext(&ctx);
    }

    ret = XMatchVisualInfo(ctx.display, ctx.screen, 24, TrueColor,
	&ctx.visualInfo);
    if (!ret) {
	ret = XMatchVisualInfo(ctx.display, ctx.screen, 16, TrueColor,
	    &ctx.visualInfo);
	if (!ret) {
	    fprintf(stderr, "Could not find a matching visual.\n");
	    return releaseContext(&ctx);
	}
    }

    if (!uniDRICreateContext(ctx.display, ctx.screen, ctx.visualInfo.visual,
	    &ctx.id, &ctx.hwContext)) {
	fprintf(stderr, "Could not create DRI context.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveContext;

    testAGP(&ctx);

    releaseContext(&ctx);
    printf("Terminating normally\n");
    return 0;
}