int viaOffScreenLinear(VIAMemPtr mem, ScrnInfoPtr pScrn, unsigned long size) { int depth = pScrn->bitsPerPixel >> 3; VIAPtr pVia = VIAPTR(pScrn); if (pVia->useEXA && !pVia->NoAccel) { mem->exa = exaOffscreenAlloc(pScrn->pScreen, size, 32, TRUE, NULL, NULL); if (mem->exa == NULL) return BadAlloc; mem->exa->save = viaExaFBSave; mem->base = mem->exa->offset; mem->pool = 1; mem->pScrn = pScrn; return Success; } mem->linear = xf86AllocateOffscreenLinear(pScrn->pScreen, (size + depth - 1) / depth, 32, NULL, NULL, NULL); if (mem->linear == NULL) return BadAlloc; mem->base = mem->linear->offset * depth; mem->pool = 1; mem->pScrn = pScrn; return Success; }
/** * Allocates a framebuffer copy of the pixmap if necessary, and then copies * any necessary pixmap data into the framebuffer copy and points the pixmap at * it. * * Note that when first allocated, a pixmap will have FALSE dirty flag. * This is intentional because pixmap data starts out undefined. So if we move * it in due to the first operation against it being accelerated, it will have * undefined framebuffer contents that we didn't have to upload. If we do * moveouts (and moveins) after the first movein, then we will only have to copy * back and forth if the pixmap was written to after the last synchronization of * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away) * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move * all the data, since it's almost surely all valid now. */ static void exaDoMoveInPixmap(ExaMigrationPtr migrate) { PixmapPtr pPixmap = migrate->pPix; ScreenPtr pScreen = pPixmap->drawable.pScreen; ExaScreenPriv(pScreen); ExaPixmapPriv(pPixmap); /* If we're VT-switched away, no touching card memory allowed. */ if (pExaScr->swappedOut) return; /* If we're not allowed to move, then fail. */ if (exaPixmapIsPinned(pPixmap)) return; /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of * fragility in EXA, and <8bpp is probably not used enough any more to care * (at least, not in acceleratd paths). */ if (pPixmap->drawable.bitsPerPixel < 8) return; if (pExaPixmap->accel_blocked) return; if (pExaPixmap->area == NULL) { pExaPixmap->area = exaOffscreenAlloc(pScreen, pExaPixmap->fb_size, pExaScr->info->pixmapOffsetAlign, FALSE, exaPixmapSave, (pointer) pPixmap); if (pExaPixmap->area == NULL) return; pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase + pExaPixmap->area->offset; } exaCopyDirtyToFb(migrate); if (exaPixmapHasGpuCopy(pPixmap)) return; DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap, (ExaGetPixmapPriv(pPixmap)->area ? ExaGetPixmapPriv(pPixmap)->area->offset : 0), pPixmap->drawable.width, pPixmap->drawable.height, exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); pExaPixmap->use_gpu_copy = TRUE; pPixmap->devKind = pExaPixmap->fb_pitch; pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; }
/* Allocates memory, either by resizing the allocation pointed to by mem_struct, * or by freeing mem_struct (if non-NULL) and allocating a new space. The size * is measured in bytes, and the offset from the beginning of card space is * returned. */ uint32_t radeon_legacy_allocate_memory(ScrnInfoPtr pScrn, void **mem_struct, int size, int align, int domain) { ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); uint32_t offset = 0; #ifdef XF86DRM_MODE if (info->cs) { struct radeon_bo *video_bo; if (*mem_struct) radeon_legacy_free_memory(pScrn, *mem_struct); video_bo = radeon_bo_open(info->bufmgr, 0, size, align, domain, 0); *mem_struct = video_bo; if (!video_bo) return 0; return (uint32_t)-1; } #endif #ifdef USE_EXA if (info->useEXA) { ExaOffscreenArea *area = *mem_struct; if (area != NULL) { if (area->size >= size) return area->offset; exaOffscreenFree(pScreen, area); } area = exaOffscreenAlloc(pScreen, size, align, TRUE, NULL, NULL); *mem_struct = area; if (area == NULL) return 0; offset = area->offset; } #endif /* USE_EXA */ #ifdef USE_XAA if (!info->useEXA) { FBLinearPtr linear = *mem_struct; int cpp = info->CurrentLayout.bitsPerPixel / 8; /* XAA allocates in units of pixels at the screen bpp, so adjust size * appropriately. */ size = (size + cpp - 1) / cpp; align = (align + cpp - 1) / cpp; if (linear) { if(linear->size >= size) return linear->offset * cpp; if(xf86ResizeOffscreenLinear(linear, size)) return linear->offset * cpp; xf86FreeOffscreenLinear(linear); } linear = xf86AllocateOffscreenLinear(pScreen, size, align, NULL, NULL, NULL); *mem_struct = linear; if (!linear) { int max_size; xf86QueryLargestOffscreenLinear(pScreen, &max_size, align, PRIORITY_EXTREME); if (max_size < size) return 0; xf86PurgeUnlockedOffscreenAreas(pScreen); linear = xf86AllocateOffscreenLinear(pScreen, size, align, NULL, NULL, NULL); *mem_struct = linear; if (!linear) return 0; } offset = linear->offset * cpp; } #endif /* USE_XAA */ return offset; }
static Bool SMI_CrtcConfigResize(ScrnInfoPtr pScrn, int width, int height) { SMIPtr pSmi = SMIPTR(pScrn); xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); int i; xf86CrtcPtr crtc; ENTER(); /* Allocate another offscreen area and use it as screen, if it really has to be resized */ if(!pSmi->NoAccel && pSmi->useEXA && ( !pSmi->fbArea || width != pScrn->virtualX || height != pScrn->virtualY )){ int aligned_pitch = (width*pSmi->Bpp + 15) & ~15; ExaOffscreenArea* fbArea = exaOffscreenAlloc(pScrn->pScreen, aligned_pitch*height, 16, TRUE, NULL, NULL); if(!fbArea){ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "SMI_CrtcConfigResize: Not enough memory to resize the framebuffer\n"); LEAVE(FALSE); } if(pSmi->fbArea) exaOffscreenFree(pScrn->pScreen, pSmi->fbArea); pSmi->fbArea = fbArea; pSmi->FBOffset = fbArea->offset; pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset); #if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0)) if(pScrn->pixmapPrivate.ptr) /* The pixmap devPrivate just set may be overwritten by xf86EnableDisableFBAccess */ pScrn->pixmapPrivate.ptr = pSmi->FBBase + pSmi->FBOffset; #endif /* Modify the screen pitch */ pScrn->displayWidth = aligned_pitch / pSmi->Bpp; pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), -1, -1, -1, -1, aligned_pitch, NULL); /* Modify the screen dimensions */ pScrn->virtualX = width; pScrn->virtualY = height; pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), width, height, -1, -1, 0, NULL); } /* Setup each crtc video processor */ for(i=0;i<crtcConf->num_crtc;i++){ crtc = crtcConf->crtc[i]; SMICRTC(crtc)->video_init(crtc); SMICRTC(crtc)->adjust_frame(crtc,crtc->x,crtc->y); } LEAVE(TRUE); }