radeon_dri.c

来自「Mesa is an open-source implementation of」· C语言 代码 · 共 1,338 行 · 第 1/3 页

C
1,338
字号
    int  ret;    int  flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;    int            s, l;    ret = drmScatterGatherAlloc(ctx->drmFD, info->gartSize*1024*1024,				&info->gartMemHandle);    if (ret < 0) {	fprintf(stderr, "[pci] Out of memory (%d)\n", ret);	return 0;    }    fprintf(stderr,	       "[pci] %d kB allocated with handle 0x%08lx\n",	       info->gartSize*1024, info->gartMemHandle);   info->gartOffset = 0;      /* Initialize the CP ring buffer data */   info->ringStart       = info->gartOffset;   info->ringMapSize     = info->ringSize*1024*1024 + radeon_drm_page_size;   info->ringReadOffset  = info->ringStart + info->ringMapSize;   info->ringReadMapSize = radeon_drm_page_size;   /* Reserve space for vertex/indirect buffers */   info->bufStart        = info->ringReadOffset + info->ringReadMapSize;   info->bufMapSize      = info->bufSize*1024*1024;   /* Reserve the rest for AGP textures */   info->gartTexStart     = info->bufStart + info->bufMapSize;   s = (info->gartSize*1024*1024 - info->gartTexStart);   l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);   if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;   info->gartTexMapSize   = (s >> l) << l;   info->log2GARTTexGran  = l;    if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,		  DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {	fprintf(stderr,		   "[pci] Could not add ring mapping\n");	return 0;    }    fprintf(stderr,	       "[pci] ring handle = 0x%08x\n", info->ringHandle);    if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,		  DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {	fprintf(stderr,		   "[pci] Could not add ring read ptr mapping\n");	return 0;    }    fprintf(stderr, 	       "[pci] ring read ptr handle = 0x%08lx\n",	       info->ringReadPtrHandle);    if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,		  DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {	fprintf(stderr,		   "[pci] Could not add vertex/indirect buffers mapping\n");	return 0;    }    fprintf(stderr, 	       "[pci] vertex/indirect buffers handle = 0x%08lx\n",	       info->bufHandle);    if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize,		  DRM_SCATTER_GATHER, 0, &info->gartTexHandle) < 0) {	fprintf(stderr,		   "[pci] Could not add GART texture map mapping\n");	return 0;    }    fprintf(stderr, 	       "[pci] GART texture map handle = 0x%08x\n",	       info->gartTexHandle);    return 1;}/** * \brief Initialize the kernel data structures and enable the CP engine. * * \param ctx display handle. * \param info driver private data. * * \return non-zero on success, or zero on failure. * * This function is a wrapper around the DRM_RADEON_CP_INIT command, passing * all the parameters in a drm_radeon_init_t structure. */static int RADEONDRIKernelInit( const DRIDriverContext *ctx,			       RADEONInfoPtr info){   int cpp = ctx->bpp / 8;   drm_radeon_init_t  drmInfo;   int ret;   memset(&drmInfo, 0, sizeof(drm_radeon_init_t));   if ( (info->ChipFamily == CHIP_FAMILY_R200) ||	(info->ChipFamily == CHIP_FAMILY_RV250) ||	(info->ChipFamily == CHIP_FAMILY_M9) ||	(info->ChipFamily == CHIP_FAMILY_RV280) )      drmInfo.func             = RADEON_INIT_R200_CP;   else      drmInfo.func             = RADEON_INIT_CP;   /* This is the struct passed to the kernel module for its initialization */   drmInfo.sarea_priv_offset   = sizeof(drm_sarea_t);   drmInfo.is_pci              = ctx->isPCI;   drmInfo.cp_mode             = RADEON_DEFAULT_CP_BM_MODE;   drmInfo.gart_size            = info->gartSize*1024*1024;   drmInfo.ring_size           = info->ringSize*1024*1024;   drmInfo.usec_timeout        = 1000;   drmInfo.fb_bpp              = ctx->bpp;   drmInfo.depth_bpp           = ctx->bpp;   drmInfo.front_offset        = info->frontOffset;   drmInfo.front_pitch         = info->frontPitch * cpp;   drmInfo.back_offset         = info->backOffset;   drmInfo.back_pitch          = info->backPitch * cpp;   drmInfo.depth_offset        = info->depthOffset;   drmInfo.depth_pitch         = info->depthPitch * cpp;   drmInfo.fb_offset           = info->LinearAddr;   drmInfo.mmio_offset         = info->registerHandle;   drmInfo.ring_offset         = info->ringHandle;   drmInfo.ring_rptr_offset    = info->ringReadPtrHandle;   drmInfo.buffers_offset      = info->bufHandle;   drmInfo.gart_textures_offset = info->gartTexHandle;   ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_INIT, &drmInfo, 			 sizeof(drm_radeon_init_t));   return ret >= 0;}/** * \brief Initialize the AGP heap. * * \param ctx display handle. * \param info driver private data. * * This function is a wrapper around the DRM_RADEON_INIT_HEAP command, passing * all the parameters in a drm_radeon_mem_init_heap structure. */static void RADEONDRIAgpHeapInit(const DRIDriverContext *ctx,				 RADEONInfoPtr info){   drm_radeon_mem_init_heap_t drmHeap;   /* Start up the simple memory manager for gart space */   drmHeap.region = RADEON_MEM_REGION_GART;   drmHeap.start  = 0;   drmHeap.size   = info->gartTexMapSize;       if (drmCommandWrite(ctx->drmFD, DRM_RADEON_INIT_HEAP,		       &drmHeap, sizeof(drmHeap))) {      fprintf(stderr,	      "[drm] Failed to initialized gart heap manager\n");   } else {      fprintf(stderr,	      "[drm] Initialized kernel gart heap manager, %d\n",	      info->gartTexMapSize);   }}/** * \brief Add a map for the vertex buffers that will be accessed by any * DRI-based clients. *  * \param ctx display handle. * \param info driver private data. * * \return one on success, or zero on failure. * * Calls drmAddBufs() with the previously allocated vertex buffers. */static int RADEONDRIBufInit( const DRIDriverContext *ctx, RADEONInfoPtr info ){   /* Initialize vertex buffers */   info->bufNumBufs = drmAddBufs(ctx->drmFD,				 info->bufMapSize / RADEON_BUFFER_SIZE,				 RADEON_BUFFER_SIZE,				 ctx->isPCI ? DRM_SG_BUFFER : DRM_AGP_BUFFER,				 info->bufStart);   if (info->bufNumBufs <= 0) {      fprintf(stderr,	      "[drm] Could not create vertex/indirect buffers list\n");      return 0;   }   fprintf(stderr,	   "[drm] Added %d %d byte vertex/indirect buffers\n",	   info->bufNumBufs, RADEON_BUFFER_SIZE);      return 1;}/** * \brief Install an IRQ handler. *  * \param ctx display handle. * \param info driver private data. * * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to * IRQ-free operation on failure. */static void RADEONDRIIrqInit(const DRIDriverContext *ctx,			     RADEONInfoPtr info){   if (!info->irq) {      info->irq = drmGetInterruptFromBusID(ctx->drmFD,					   ctx->pciBus,					   ctx->pciDevice,					   ctx->pciFunc);      if ((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) {	 fprintf(stderr,		 "[drm] failure adding irq handler, "		 "there is a device already using that irq\n"		 "[drm] falling back to irq-free operation\n");	 info->irq = 0;      }   }   if (info->irq)      fprintf(stderr,	      "[drm] dma control initialized, using IRQ %d\n",	      info->irq);}static int RADEONCheckDRMVersion( const DRIDriverContext *ctx,				  RADEONInfoPtr info ){   drmVersionPtr  version;   version = drmGetVersion(ctx->drmFD);   if (version) {      int req_minor, req_patch;      /* Need 1.8.x for proper cleanup-on-client-exit behaviour.       */      req_minor = 8;      req_patch = 0;	      if (version->version_major != 1 ||	  version->version_minor < req_minor ||	  (version->version_minor == req_minor && 	   version->version_patchlevel < req_patch)) {	 /* Incompatible drm version */	 fprintf(stderr,		 "[dri] RADEONDRIScreenInit failed because of a version "		 "mismatch.\n"		 "[dri] radeon.o kernel module version is %d.%d.%d "		 "but version 1.%d.%d or newer is needed.\n"		 "[dri] Disabling DRI.\n",		 version->version_major,		 version->version_minor,		 version->version_patchlevel,		 req_minor,		 req_patch);	 drmFreeVersion(version);	 return 0;      }      info->drmMinor = version->version_minor;      drmFreeVersion(version);   }   return 1;}static int RADEONMemoryInit( const DRIDriverContext *ctx, RADEONInfoPtr info ){   int        width_bytes = ctx->shared.virtualWidth * ctx->cpp;   int        cpp         = ctx->cpp;   int        bufferSize  = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes			     + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);   int        depthSize   = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes			     + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);   int        l;   info->frontOffset = 0;   info->frontPitch = ctx->shared.virtualWidth;   fprintf(stderr, 	   "Using %d MB AGP aperture\n", info->gartSize);   fprintf(stderr, 	   "Using %d MB for the ring buffer\n", info->ringSize);   fprintf(stderr, 	   "Using %d MB for vertex/indirect buffers\n", info->bufSize);   fprintf(stderr, 	   "Using %d MB for AGP textures\n", info->gartTexSize);   /* Front, back and depth buffers - everything else texture??    */   info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize;   if (ctx->colorTiling==1)   {	info->textureSize = ctx->shared.fbSize - ((ctx->shared.fbSize - info->textureSize + width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes*16);   }   if (info->textureSize < 0)       return 0;   l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS);   if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;   /* Round the texture size up to the nearest whole number of    * texture regions.  Again, be greedy about this, don't    * round down.    */   info->log2TexGran = l;   info->textureSize = (info->textureSize >> l) << l;   /* Set a minimum usable local texture heap size.  This will fit    * two 256x256x32bpp textures.    */   if (info->textureSize < 512 * 1024) {      info->textureOffset = 0;      info->textureSize = 0;   }   /* Reserve space for textures */   if (ctx->colorTiling==1)   {      info->textureOffset = ((ctx->shared.fbSize - info->textureSize) / 			(width_bytes * 16)) * (width_bytes*16);   }   else   {      info->textureOffset = ((ctx->shared.fbSize - info->textureSize +   	 		   RADEON_BUFFER_ALIGN) &			  ~RADEON_BUFFER_ALIGN);   }   /* Reserve space for the shared depth    * buffer.    */   info->depthOffset = ((info->textureOffset - depthSize +			 RADEON_BUFFER_ALIGN) &			~RADEON_BUFFER_ALIGN);   info->depthPitch = ctx->shared.virtualWidth;   info->backOffset = ((info->depthOffset - bufferSize +			RADEON_BUFFER_ALIGN) &		       ~RADEON_BUFFER_ALIGN);   info->backPitch = ctx->shared.virtualWidth;   fprintf(stderr, 	   "Will use back buffer at offset 0x%x\n",	   info->backOffset);   fprintf(stderr, 	   "Will use depth buffer at offset 0x%x\n",	   info->depthOffset);   fprintf(stderr, 	   "Will use %d kb for textures at offset 0x%x\n",	   info->textureSize/1024, info->textureOffset);   info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |			     (info->frontOffset >> 10));   info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |			    (info->backOffset >> 10));   info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) |			     (info->depthOffset >> 10));   return 1;}static int RADEONColorTilingInit( const DRIDriverContext *ctx, RADEONInfoPtr info ){   int        width_bytes = ctx->shared.virtualWidth * ctx->cpp;   int        bufferSize  = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes			     + RADEON_BUFFER_ALIGN)			     & ~RADEON_BUFFER_ALIGN);   /* Setup color tiling */   if (info->drmMinor<14)      info->colorTiling=0;   if (info->colorTiling)   {      int colorTilingFlag;      drm_radeon_surface_alloc_t front,back;      RadeonSetParam(ctx, RADEON_SETPARAM_SWITCH_TILING, info->colorTiling ? 1 : 0);            /* Setup the surfaces */      if (info->ChipFamily < CHIP_FAMILY_R200)         colorTilingFlag=RADEON_SURF_TILE_COLOR_MACRO;      else         colorTilingFlag=R200_SURF_TILE_COLOR_MACRO;      front.address = info->frontOffset;      front.size = bufferSize;      front.flags = (width_bytes) | colorTilingFlag;      drmCommandWrite(ctx->drmFD, DRM_RADEON_SURF_ALLOC, &front,sizeof(front));        back.address = info->backOffset;      back.size = bufferSize;      back.flags = (width_bytes) | colorTilingFlag;      drmCommandWrite(ctx->drmFD, DRM_RADEON_SURF_ALLOC, &back,sizeof(back));    }   return 1;} /** * Called at the start of each server generation. * * \param ctx display handle. * \param info driver private data. * * \return non-zero on success, or zero on failure. * * Performs static frame buffer allocation. Opens the DRM device and add maps * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more * information. Creates a \e server context to grab the lock for the * initialization ioctls and calls the other initilization functions in this * file. Starts the CP engine via the DRM_RADEON_CP_START command. * * Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its * initialization. */static int RADEONScreenInit( DRIDriverContext *ctx, RADEONInfoPtr info ){   RADEONDRIPtr   pRADEONDRI;   int err;   usleep(100);   /*assert(!ctx->IsClient);*/   {      int  width_bytes = (ctx->shared.virtualWidth * ctx->cpp);      int  maxy        = ctx->shared.fbSize / width_bytes;      if (maxy <= ctx->shared.virtualHeight * 3) {	 fprintf(stderr, 		 "Static buffer allocation failed -- "		 "need at least %d kB video memory (have %d kB)\n",		 (ctx->shared.virtualWidth * ctx->shared.virtualHeight *		  ctx->cpp * 3 + 1023) / 1024,		 ctx->shared.fbSize / 1024);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?