i830_dri.c

来自「是由intel提供的针对intel显卡915以上系列的linux驱动」· C语言 代码 · 共 1,519 行 · 第 1/3 页

C
1,519
字号
      I830SelectBuffer(pScrn, I830_SELECT_BACK);      I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);      pbox++;   }   /* Clear the depth buffer - uses 0xffff rather than 0.    */   pbox = REGION_RECTS(prgn);   nbox = REGION_NUM_RECTS(prgn);   I830SelectBuffer(pScrn, I830_SELECT_DEPTH);   switch (pScrn->bitsPerPixel) {   case 16:      I830SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);      break;   case 32:      I830SetupForSolidFill(pScrn, 0xffffff, GXcopy, -1);      break;   }   while (nbox--) {      I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);      pbox++;   }   I830SelectBuffer(pScrn, I830_SELECT_FRONT);   pI830->AccelInfoRec->NeedToSync = TRUE;}/* This routine is a modified form of XAADoBitBlt with the calls to * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source * instead of destination. My origin is upside down so the ydir cases * are reversed. */static voidI830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,		   RegionPtr prgnSrc, CARD32 index){   ScreenPtr pScreen = pParent->drawable.pScreen;   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];   I830Ptr pI830 = I830PTR(pScrn);   BoxPtr pboxTmp, pboxNext, pboxBase;   DDXPointPtr pptTmp, pptNew2;   int xdir, ydir;#if 0   int screenwidth = pScrn->virtualX;   int screenheight = pScrn->virtualY;#else   int screenwidth = pScreen->width;   int screenheight = pScreen->height;#endif   BoxPtr pbox = REGION_RECTS(prgnSrc);   int nbox = REGION_NUM_RECTS(prgnSrc);   BoxPtr pboxNew1 = 0;   BoxPtr pboxNew2 = 0;   DDXPointPtr pptNew1 = 0;   DDXPointPtr pptSrc = &ptOldOrg;   int dx = pParent->drawable.x - ptOldOrg.x;   int dy = pParent->drawable.y - ptOldOrg.y;   /* If the copy will overlap in Y, reverse the order */   if (dy > 0) {      ydir = -1;      if (nbox > 1) {	 /* Keep ordering in each band, reverse order of bands */	 pboxNew1 = (BoxPtr) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);	 if (!pboxNew1)	    return;	 pptNew1 = (DDXPointPtr) ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);	 if (!pptNew1) {	    DEALLOCATE_LOCAL(pboxNew1);	    return;	 }	 pboxBase = pboxNext = pbox + nbox - 1;	 while (pboxBase >= pbox) {	    while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))	       pboxNext--;	    pboxTmp = pboxNext + 1;	    pptTmp = pptSrc + (pboxTmp - pbox);	    while (pboxTmp <= pboxBase) {	       *pboxNew1++ = *pboxTmp++;	       *pptNew1++ = *pptTmp++;	    }	    pboxBase = pboxNext;	 }	 pboxNew1 -= nbox;	 pbox = pboxNew1;	 pptNew1 -= nbox;	 pptSrc = pptNew1;      }   } else {      /* No changes required */      ydir = 1;   }   /* If the regions will overlap in X, reverse the order */   if (dx > 0) {      xdir = -1;      if (nbox > 1) {	 /*reverse orderof rects in each band */	 pboxNew2 = (BoxPtr) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);	 pptNew2 = (DDXPointPtr) ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);	 if (!pboxNew2 || !pptNew2) {	    if (pptNew2)	       DEALLOCATE_LOCAL(pptNew2);	    if (pboxNew2)	       DEALLOCATE_LOCAL(pboxNew2);	    if (pboxNew1) {	       DEALLOCATE_LOCAL(pptNew1);	       DEALLOCATE_LOCAL(pboxNew1);	    }	    return;	 }	 pboxBase = pboxNext = pbox;	 while (pboxBase < pbox + nbox) {	    while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1))	       pboxNext++;	    pboxTmp = pboxNext;	    pptTmp = pptSrc + (pboxTmp - pbox);	    while (pboxTmp != pboxBase) {	       *pboxNew2++ = *--pboxTmp;	       *pptNew2++ = *--pptTmp;	    }	    pboxBase = pboxNext;	 }	 pboxNew2 -= nbox;	 pbox = pboxNew2;	 pptNew2 -= nbox;	 pptSrc = pptNew2;      }   } else {      /* No changes are needed */      xdir = 1;   }   /* SelectBuffer isn't really a good concept for the i810.    */   I830EmitFlush(pScrn);   I830SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);   for (; nbox--; pbox++) {      int x1 = pbox->x1;      int y1 = pbox->y1;      int destx = x1 + dx;      int desty = y1 + dy;      int w = pbox->x2 - x1 + 1;      int h = pbox->y2 - y1 + 1;      if (destx < 0)	 x1 -= destx, w += destx, destx = 0;      if (desty < 0)	 y1 -= desty, h += desty, desty = 0;      if (destx + w > screenwidth)	 w = screenwidth - destx;      if (desty + h > screenheight)	 h = screenheight - desty;      if (w <= 0)	 continue;      if (h <= 0)	 continue;      if (I810_DEBUG & DEBUG_VERBOSE_DRI)	 ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n",		x1, y1, w, h, dx, dy);      I830SelectBuffer(pScrn, I830_SELECT_BACK);      I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);      I830SelectBuffer(pScrn, I830_SELECT_DEPTH);      I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);   }   I830SelectBuffer(pScrn, I830_SELECT_FRONT);   I830EmitFlush(pScrn);   if (pboxNew2) {      DEALLOCATE_LOCAL(pptNew2);      DEALLOCATE_LOCAL(pboxNew2);   }   if (pboxNew1) {      DEALLOCATE_LOCAL(pptNew1);      DEALLOCATE_LOCAL(pboxNew1);   }   pI830->AccelInfoRec->NeedToSync = TRUE;}/* Initialize the first context */voidI830EmitInvarientState(ScrnInfoPtr pScrn){   I830Ptr pI830 = I830PTR(pScrn);   CARD32 ctx_addr;   ctx_addr = pI830->ContextMem.Start;   /* Align to a 2k boundry */   ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;   {      BEGIN_LP_RING(2);      OUT_RING(MI_SET_CONTEXT);      OUT_RING(ctx_addr |	       CTXT_NO_RESTORE |	       CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);      ADVANCE_LP_RING();   }}/* Fullscreen hooks.  The DRI fullscreen mode can probably be removed * as it adds little or nothing above the mechanism below.  (and isn't * widely used) */static BoolI830DRIOpenFullScreen(ScreenPtr pScreen){  return TRUE;}static BoolI830DRICloseFullScreen(ScreenPtr pScreen){  return TRUE;}/* Use callbacks from dri.c to support pageflipping mode for a single * 3d context without need for any specific full-screen extension. * * Also see tdfx driver for example of using these callbacks to * allocate and free 3d-specific memory on demand. *//* Use the miext/shadow module to maintain a list of dirty rectangles. * These are blitted to the back buffer to keep both buffers clean * during page-flipping when the 3d application isn't fullscreen. * * Unlike most use of the shadow code, both buffers are in video * memory. * * An alternative to this would be to organize for all on-screen * drawing operations to be duplicated for the two buffers.  That * might be faster, but seems like a lot more work... */#if 0/* This should be done *before* XAA syncs, * Otherwise will have to sync again??? */static voidI830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf){   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];   I830Ptr pI830 = I830PTR(pScrn);   RegionPtr damage = &pBuf->damage;   int i, num =  REGION_NUM_RECTS(damage);   BoxPtr pbox = REGION_RECTS(damage);   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);   int cmd, br13;   /* Don't want to do this when no 3d is active and pages are    * right-way-round :    */   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)      return;   br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);   if (pScrn->bitsPerPixel == 32) {      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |	     XY_SRC_COPY_BLT_WRITE_RGB);      br13 |= 3 << 24;   } else {      cmd = (XY_SRC_COPY_BLT_CMD);      br13 |= 1 << 24;   }   for (i = 0 ; i < num ; i++, pbox++) {      BEGIN_LP_RING(8);      OUT_RING(cmd);      OUT_RING(br13);      OUT_RING((pbox->y1 << 16) | pbox->x1);      OUT_RING((pbox->y2 << 16) | pbox->x2);      OUT_RING(pI830->BackBuffer.Start);      OUT_RING((pbox->y1 << 16) | pbox->x1);      OUT_RING(br13 & 0xffff);      OUT_RING(pI830->FrontBuffer.Start);      ADVANCE_LP_RING();   }}#endifstatic voidI830EnablePageFlip(ScreenPtr pScreen){   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];   I830Ptr pI830 = I830PTR(pScrn);   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);   pSAREAPriv->pf_enabled = pI830->allowPageFlip;   pSAREAPriv->pf_active = 0;   if (pI830->allowPageFlip) {      int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);      BEGIN_LP_RING(8);      if (pScrn->bitsPerPixel == 32) {	 OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |		  XY_SRC_COPY_BLT_WRITE_RGB);	 br13 |= 3 << 24;      } else {	 OUT_RING(XY_SRC_COPY_BLT_CMD);	 br13 |= 1 << 24;      }      OUT_RING(br13);      OUT_RING(0);      OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX);      OUT_RING(pI830->BackBuffer.Start);      OUT_RING(0);      OUT_RING(br13 & 0xffff);      OUT_RING(pI830->FrontBuffer.Start);      ADVANCE_LP_RING();      pSAREAPriv->pf_active = 1;   }}static voidI830DisablePageFlip(ScreenPtr pScreen){   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);   pSAREAPriv->pf_active = 0;}static voidI830DRITransitionSingleToMulti3d(ScreenPtr pScreen){   /* Tell the clients not to pageflip.  How?    *   -- Field in sarea, plus bumping the window counters.    *   -- DRM needs to cope with Front-to-Back swapbuffers.    */   I830DisablePageFlip(pScreen);}static voidI830DRITransitionMultiToSingle3d(ScreenPtr pScreen){   /* Let the remaining 3d app start page flipping again.    */   I830EnablePageFlip(pScreen);}static voidI830DRITransitionTo3d(ScreenPtr pScreen){   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];   I830Ptr pI830 = I830PTR(pScrn);   I830EnablePageFlip(pScreen);   pI830->have3DWindows = 1;}static voidI830DRITransitionTo2d(ScreenPtr pScreen){   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];   I830Ptr pI830 = I830PTR(pScrn);   drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);   /* Try flipping back to the front page if necessary */   if (sPriv->pf_current_page == 1)      drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP);   /* Shut down shadowing if we've made it back to the front page:    */   if (sPriv->pf_current_page == 0) {      I830DisablePageFlip(pScreen);   }   pI830->have3DWindows = 0;}/** * Update the SAREA fields with the most recent values. * This gets called after the screen orientation/rotation changes. */BoolI830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea){   I830Ptr pI830 = I830PTR(pScrn);   ScreenPtr pScreen = pScrn->pScreen;   Bool success;   I830DRIUnmapScreenRegions(pScrn, sarea);   if (pI830->rotation == RR_Rotate_0) {      sarea->front_offset = pI830->FrontBuffer.Start;      /* Don't use FrontBuffer.Size here as it includes the pixmap cache area       * Instead, calculate the entire framebuffer.       */      sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp;   } else {      /* Need to deal with rotated2 once we have dual head DRI */      sarea->front_offset = pI830->RotatedMem.Start;      sarea->front_size = pI830->RotatedMem.Size;   }   xf86DrvMsg(pScrn->scrnIndex, X_INFO,              "[drm] init sarea width,height = %d x %d (pitch %d)\n",              pScreen->width, pScreen->height,pScrn->displayWidth);   sarea->width = pScreen->width;   sarea->height = pScreen->height;   sarea->back_offset = pI830->BackBuffer.Start;   sarea->back_size = pI830->BackBuffer.Size;   sarea->depth_offset = pI830->DepthBuffer.Start;   sarea->depth_size = pI830->DepthBuffer.Size;   sarea->tex_offset = pI830->TexMem.Start;   sarea->tex_size = pI830->TexMem.Size;   sarea->log_tex_granularity = pI830->TexGranularity;   sarea->pitch = pScrn->displayWidth;   sarea->virtualX = pScrn->virtualX;   sarea->virtualY = pScrn->virtualY;   switch (pI830->rotation) {      case RR_Rotate_0:         sarea->rotation = 0;         break;      case RR_Rotate_90:         sarea->rotation = 90;         break;      case RR_Rotate_180:         sarea->rotation = 180;         break;      case RR_Rotate_270:         sarea->rotation = 270;         break;      default:         sarea->rotation = 0;   }   if (pI830->rotation == RR_Rotate_0) {      sarea->rotated_offset = -1;      sarea->rotated_size = 0;   }   else {      sarea->rotated_offset = pI830->FrontBuffer.Start;      sarea->rotated_size = pI830->FrontBuffer.Size;   }   /* This is the original pitch */   sarea->rotated_pitch = pI830->displayWidth;   success = I830DRIMapScreenRegions(pScrn, sarea);   I830InitTextureHeap(pScrn, sarea);   return success;}BoolI830DRILock(ScrnInfoPtr pScrn){   I830Ptr pI830 = I830PTR(pScrn);   if (pI830->directRenderingEnabled && !pI830->LockHeld) {      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);      pI830->LockHeld = 1;      I830RefreshRing(pScrn);      return TRUE;   }   else      return FALSE;}voidI830DRIUnlock(ScrnInfoPtr pScrn){   I830Ptr pI830 = I830PTR(pScrn);   if (pI830->directRenderingEnabled && pI830->LockHeld) {      DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);      pI830->LockHeld = 0;   }}

⌨️ 快捷键说明

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