static void nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, struct nouveau_dri2_vblank_state *s) { ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); NVPtr pNv = NVPTR(scrn); PixmapPtr dst_pix; PixmapPtr src_pix = nouveau_dri2_buffer(s->src)->ppix; struct nouveau_bo *dst_bo; struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix); struct nouveau_pushbuf *push = pNv->pushbuf; RegionRec reg; int type, ret; Bool front_updated, will_exchange; xf86CrtcPtr ref_crtc; REGION_INIT(0, ®, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0); REGION_TRANSLATE(0, ®, draw->x, draw->y); /* Main crtc for this drawable shall finally deliver pageflip event. */ ref_crtc = nouveau_pick_best_crtc(scrn, FALSE, draw->x, draw->y, draw->width, draw->height); /* Update frontbuffer pixmap and name: Could have changed due to * window (un)redirection as part of compositing. */ front_updated = update_front(draw, s->dst); /* Assign frontbuffer pixmap, after update in update_front() */ dst_pix = nouveau_dri2_buffer(s->dst)->ppix; dst_bo = nouveau_pixmap_bo(dst_pix); /* Throttle on the previous frame before swapping */ nouveau_bo_wait(dst_bo, NOUVEAU_BO_RD, push->client); /* Swap by buffer exchange possible? */ will_exchange = front_updated && can_exchange(draw, dst_pix, src_pix); /* Only emit a wait for vblank pushbuf here if this is a copy-swap, or * if it is a kms pageflip-swap on an old kernel. Pure exchange swaps * don't need sync to vblank. kms pageflip-swaps on Linux 3.13+ are * synced to vblank in the kms driver, so we must not sync here, or * framerate will be cut in half! */ if (can_sync_to_vblank(draw) && (!will_exchange || (!pNv->has_async_pageflip && nouveau_exa_pixmap_is_onscreen(dst_pix)))) { /* Reference the back buffer to sync it to vblank */ nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) { src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD }, 1);
static Bool NV40_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format) { NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_surface_format_t *fmt; fmt = NV40_GetPictSurfaceFormat(format); if (!fmt) { ErrorF("AIII no format\n"); return FALSE; } BEGIN_RING(chan, curie, NV40TCL_RT_FORMAT, 3); OUT_RING (chan, NV40TCL_RT_FORMAT_TYPE_LINEAR | NV40TCL_RT_FORMAT_ZETA_Z24S8 | fmt->card_fmt); OUT_RING (chan, exaGetPixmapPitch(pPix)); if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) return FALSE; return TRUE; }
static void nouveau_exa_finish_access(PixmapPtr ppix, int index) { struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); nouveau_bo_unmap(bo); }
static Bool update_front(DrawablePtr draw, DRI2BufferPtr front) { int r; PixmapPtr pixmap; struct nouveau_dri2_buffer *nvbuf = nouveau_dri2_buffer(front); if (draw->type == DRAWABLE_PIXMAP) pixmap = (PixmapPtr)draw; else pixmap = (*draw->pScreen->GetWindowPixmap)((WindowPtr)draw); pixmap->refcnt++; exaMoveInPixmap(pixmap); r = nouveau_bo_name_get(nouveau_pixmap_bo(pixmap), &front->name); if (r) { (*draw->pScreen->DestroyPixmap)(pixmap); return FALSE; } if (nvbuf->ppix) (*draw->pScreen->DestroyPixmap)(nvbuf->ppix); front->pitch = pixmap->devKind; front->cpp = pixmap->drawable.bitsPerPixel / 8; nvbuf->ppix = pixmap; return TRUE; }
static Bool nouveau_exa_download_from_screen(PixmapPtr pspix, int x, int y, int w, int h, char *dst, int dst_pitch) { ScrnInfoPtr pScrn = xf86Screens[pspix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_bo *bo; int src_pitch, cpp, offset; const char *src; Bool ret; src_pitch = exaGetPixmapPitch(pspix); cpp = pspix->drawable.bitsPerPixel >> 3; offset = (y * src_pitch) + (x * cpp); if (pNv->GART) { if (pNv->Architecture >= NV_ARCH_C0) { if (NVC0AccelDownloadM2MF(pspix, x, y, w, h, dst, dst_pitch)) return TRUE; } else { if (NVAccelDownloadM2MF(pspix, x, y, w, h, dst, dst_pitch)) return TRUE; } } bo = nouveau_pixmap_bo(pspix); if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) return FALSE; src = (char *)bo->map + offset; ret = NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp); nouveau_bo_unmap(bo); return ret; }
static Bool NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict) { NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *rankine = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_surface_format_t *fmt; fmt = NV30_GetPictSurfaceFormat(pPict->format); if (!fmt) { ErrorF("AIII no format\n"); return FALSE; } uint32_t pitch = (uint32_t)exaGetPixmapPitch(pPix); BEGIN_RING(chan, rankine, NV34TCL_RT_FORMAT, 3); OUT_RING (chan, fmt->card_fmt); /* format */ OUT_RING (chan, pitch << 16 | pitch); if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) return FALSE; return TRUE; }
bool nv50_style_tiled_pixmap(PixmapPtr ppix) { ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); return pNv->Architecture >= NV_ARCH_50 && (nouveau_pixmap_bo(ppix)->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK); }
static Bool setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap) { struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *celsius = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; long w = pict->pDrawable->width, h = pict->pDrawable->height; unsigned int txfmt = NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE | NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE | log2i(w) << 20 | log2i(h) << 16 | 1 << 12 | /* lod == 1 */ get_tex_format(pict) | 0x50 /* UNK */; BEGIN_RING(chan, celsius, NV10TCL_TX_OFFSET(unit), 1); if (OUT_RELOCl(chan, bo, 0, tex_reloc)) return FALSE; if (pict->repeat == RepeatNone) { /* NPOT_SIZE expects an even number for width, we can * round up uneven numbers here because EXA always * gives 64 byte aligned pixmaps and for all formats * we support 64 bytes represents an even number of * pixels */ w = (w + 1) &~ 1; BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_PITCH(unit), 1); OUT_RING (chan, exaGetPixmapPitch(pixmap) << 16); BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_SIZE(unit), 1); OUT_RING (chan, w << 16 | h); } BEGIN_RING(chan, celsius, NV10TCL_TX_FORMAT(unit), 1 ); if (OUT_RELOCd(chan, bo, txfmt, tex_reloc | NOUVEAU_BO_OR, NV10TCL_TX_FORMAT_DMA0, NV10TCL_TX_FORMAT_DMA1)) return FALSE; BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(unit), 1 ); OUT_RING (chan, NV10TCL_TX_ENABLE_ENABLE); BEGIN_RING(chan, celsius, NV10TCL_TX_FILTER(unit), 1); if (pict->filter == PictFilterNearest) OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_NEAREST | NV10TCL_TX_FILTER_MINIFY_NEAREST)); else OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_LINEAR | NV10TCL_TX_FILTER_MINIFY_LINEAR)); return TRUE; }
static Bool NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit) { NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *rankine = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_texture_format_t *fmt; uint32_t card_filter, card_repeat; uint32_t tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; NV30EXA_STATE; fmt = NV30_GetPictTextureFormat(pPict->format); if (!fmt) return FALSE; card_repeat = 3; /* repeatNone */ if (pPict->filter == PictFilterBilinear) card_filter = 2; else card_filter = 1; BEGIN_RING(chan, rankine, NV34TCL_TX_OFFSET(unit), 8); if (OUT_RELOCl(chan, bo, 0, tex_reloc) || OUT_RELOCd(chan, bo, NV34TCL_TX_FORMAT_DIMS_2D | (1 << 16) | 8 | (fmt->card_fmt << NV34TCL_TX_FORMAT_FORMAT_SHIFT) | (log2i(pPix->drawable.width) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT) | (log2i(pPix->drawable.height) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT), tex_reloc | NOUVEAU_BO_OR, NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1)) return FALSE; OUT_RING (chan, (card_repeat << NV34TCL_TX_WRAP_S_SHIFT) | (card_repeat << NV34TCL_TX_WRAP_T_SHIFT) | (card_repeat << NV34TCL_TX_WRAP_R_SHIFT)); OUT_RING (chan, NV34TCL_TX_ENABLE_ENABLE); OUT_RING (chan, (((uint32_t)exaGetPixmapPitch(pPix)) << NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT ) | fmt->card_swz); OUT_RING (chan, (card_filter << NV34TCL_TX_FILTER_MINIFY_SHIFT) /* min */ | (card_filter << NV34TCL_TX_FILTER_MAGNIFY_SHIFT) /* mag */ | 0x2000 /* engine lock */); OUT_RING (chan, (pPix->drawable.width << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pPix->drawable.height); OUT_RING (chan, 0); /* border ARGB */ state->unit[unit].width = (float)pPix->drawable.width; state->unit[unit].height = (float)pPix->drawable.height; state->unit[unit].transform = pPict->transform; return TRUE; }
static Bool nouveau_exa_prepare_access(PixmapPtr ppix, int index) { struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); NVPtr pNv = NVPTR(xf86Screens[ppix->drawable.pScreen->myNum]); if (nv50_style_tiled_pixmap(ppix) && !pNv->wfb_enabled) return FALSE; if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) return FALSE; ppix->devPrivate.ptr = bo->map; return TRUE; }
static Bool setup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap) { struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); BEGIN_NV04(push, NV10_3D(RT_FORMAT), 3); PUSH_DATA (push, get_rt_format(pict)); PUSH_DATA (push, (exaGetPixmapPitch(pixmap) << 16 | exaGetPixmapPitch(pixmap))); PUSH_MTHDl(push, NV10_3D(COLOR_OFFSET), bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); return TRUE; }
static Bool setup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap) { struct nouveau_channel *chan = pNv->chan; struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); BEGIN_NV04(chan, NV10_3D(RT_FORMAT), 2); OUT_RING (chan, get_rt_format(pict)); OUT_RING (chan, (exaGetPixmapPitch(pixmap) << 16 | exaGetPixmapPitch(pixmap))); BEGIN_NV04(chan, NV10_3D(COLOR_OFFSET), 1); if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) return FALSE; return TRUE; }
static Bool NV40_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_surface_format_t *fmt; fmt = NV40_GetPictSurfaceFormat(format); if (!fmt) { ErrorF("AIII no format\n"); return FALSE; } BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3); PUSH_DATA (push, NV30_3D_RT_FORMAT_TYPE_LINEAR | NV30_3D_RT_FORMAT_ZETA_Z24S8 | fmt->card_fmt); PUSH_DATA (push, exaGetPixmapPitch(pPix)); PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); return TRUE; }
static Bool NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); uint32_t pitch = exaGetPixmapPitch(pPix); nv_pict_surface_format_t *fmt; fmt = NV30_GetPictSurfaceFormat(pPict->format); if (!fmt) { ErrorF("AIII no format\n"); return FALSE; } BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3); PUSH_DATA (push, fmt->card_fmt); /* format */ PUSH_DATA (push, pitch << 16 | pitch); PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); return TRUE; }
static inline Bool NVAccelDownloadM2MF(PixmapPtr pspix, int x, int y, int w, int h, char *dst, unsigned dst_pitch) { ScrnInfoPtr pScrn = xf86Screens[pspix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *m2mf = pNv->NvMemFormat; struct nouveau_bo *bo = nouveau_pixmap_bo(pspix); unsigned cpp = pspix->drawable.bitsPerPixel / 8; unsigned line_len = w * cpp; unsigned src_offset = 0, src_pitch = 0, linear = 0; /* Maximum DMA transfer */ unsigned line_count = pNv->GART->size / line_len; if (!nv50_style_tiled_pixmap(pspix)) { linear = 1; src_pitch = exaGetPixmapPitch(pspix); src_offset += (y * src_pitch) + (x * cpp); } /* HW limitations */ if (line_count > 2047) line_count = 2047; while (h) { int i; char *src; if (line_count > h) line_count = h; if (MARK_RING(chan, 32, 6)) return FALSE; BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); if (OUT_RELOCo(chan, bo, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOCo(chan, pNv->GART, NOUVEAU_BO_GART | NOUVEAU_BO_WR)) { MARK_UNDO(chan); return FALSE; } if (pNv->Architecture >= NV_ARCH_50) { if (!linear) { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 7); OUT_RING (chan, 0); OUT_RING (chan, bo->tile_mode << 4); OUT_RING (chan, pspix->drawable.width * cpp); OUT_RING (chan, pspix->drawable.height); OUT_RING (chan, 1); OUT_RING (chan, 0); OUT_RING (chan, (y << 16) | (x * cpp)); } else { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1); OUT_RING (chan, 1); } BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1); OUT_RING (chan, 1); BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2); if (OUT_RELOCh(chan, bo, src_offset, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOCh(chan, pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR)) { MARK_UNDO(chan); return FALSE; } } BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); if (OUT_RELOCl(chan, bo, src_offset, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOCl(chan, pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR)) { MARK_UNDO(chan); return FALSE; } OUT_RING (chan, src_pitch); OUT_RING (chan, line_len); OUT_RING (chan, line_len); OUT_RING (chan, line_count); OUT_RING (chan, (1<<8)|1); OUT_RING (chan, 0); if (nouveau_bo_map(pNv->GART, NOUVEAU_BO_RD)) { MARK_UNDO(chan); return FALSE; } src = pNv->GART->map; if (dst_pitch == line_len) { memcpy(dst, src, dst_pitch * line_count); dst += dst_pitch * line_count; } else { for (i = 0; i < line_count; i++) { memcpy(dst, src, line_len); src += line_len; dst += dst_pitch; } } nouveau_bo_unmap(pNv->GART); if (linear) src_offset += line_count * src_pitch; h -= line_count; y += line_count; } return TRUE; }
static Bool nouveau_exa_upload_to_screen(PixmapPtr pdpix, int x, int y, int w, int h, char *src, int src_pitch) { ScrnInfoPtr pScrn = xf86Screens[pdpix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_bo *bo; int dst_pitch, cpp; char *dst; Bool ret; dst_pitch = exaGetPixmapPitch(pdpix); cpp = pdpix->drawable.bitsPerPixel >> 3; /* try hostdata transfer */ if (w * h * cpp < 16*1024) /* heuristic */ { if (pNv->Architecture < NV_ARCH_50) { if (NV04EXAUploadIFC(pScrn, src, src_pitch, pdpix, x, y, w, h, cpp)) { exaMarkSync(pdpix->drawable.pScreen); return TRUE; } } else if (pNv->Architecture < NV_ARCH_C0) { if (NV50EXAUploadSIFC(src, src_pitch, pdpix, x, y, w, h, cpp)) { exaMarkSync(pdpix->drawable.pScreen); return TRUE; } } else { if (NVC0EXAUploadSIFC(src, src_pitch, pdpix, x, y, w, h, cpp)) { exaMarkSync(pdpix->drawable.pScreen); return TRUE; } } } /* try gart-based transfer */ if (pNv->GART) { if (pNv->Architecture < NV_ARCH_C0) { ret = NVAccelUploadM2MF(pdpix, x, y, w, h, src, src_pitch); } else { ret = NVC0AccelUploadM2MF(pdpix, x, y, w, h, src, src_pitch); } if (ret) { exaMarkSync(pdpix->drawable.pScreen); return TRUE; } } /* fallback to memcpy-based transfer */ bo = nouveau_pixmap_bo(pdpix); if (nouveau_bo_map(bo, NOUVEAU_BO_WR)) return FALSE; dst = (char *)bo->map + (y * dst_pitch) + (x * cpp); ret = NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp); nouveau_bo_unmap(bo); return ret; }
void nouveau_dri2_copy_region2(ScreenPtr pScreen, DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) { struct nouveau_dri2_buffer *src = nouveau_dri2_buffer(pSrcBuffer); struct nouveau_dri2_buffer *dst = nouveau_dri2_buffer(pDstBuffer); NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen)); RegionPtr pCopyClip; GCPtr pGC; DrawablePtr src_draw, dst_draw; Bool translate = FALSE; int off_x = 0, off_y = 0; src_draw = &src->ppix->drawable; dst_draw = &dst->ppix->drawable; #if 0 ErrorF("attachments src %d, dst %d, drawable %p %p pDraw %p\n", src->base.attachment, dst->base.attachment, src_draw, dst_draw, pDraw); #endif if (src->base.attachment == DRI2BufferFrontLeft) src_draw = pDraw; if (dst->base.attachment == DRI2BufferFrontLeft) { #ifdef NOUVEAU_PIXMAP_SHARING if (pDraw->pScreen != pScreen) { dst_draw = DRI2UpdatePrime(pDraw, pDstBuffer); if (!dst_draw) return; } else #endif dst_draw = pDraw; if (dst_draw != pDraw) translate = TRUE; } if (translate && pDraw->type == DRAWABLE_WINDOW) { #ifdef COMPOSITE PixmapPtr pPix = get_drawable_pixmap(pDraw); off_x = -pPix->screen_x; off_y = -pPix->screen_y; #endif off_x += pDraw->x; off_y += pDraw->y; } pGC = GetScratchGC(pDraw->depth, pScreen); pCopyClip = REGION_CREATE(pScreen, NULL, 0); REGION_COPY(pScreen, pCopyClip, pRegion); if (translate) { REGION_TRANSLATE(pScreen, pCopyClip, off_x, off_y); } pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); ValidateGC(dst_draw, pGC); /* If this is a full buffer swap or frontbuffer flush, throttle on * the previous one. */ if (dst->base.attachment == DRI2BufferFrontLeft && REGION_NUM_RECTS(pRegion) == 1) { BoxPtr extents = REGION_EXTENTS(pScreen, pRegion); if (extents->x1 == 0 && extents->y1 == 0 && extents->x2 == pDraw->width && extents->y2 == pDraw->height) { PixmapPtr fpix = get_drawable_pixmap(dst_draw); struct nouveau_bo *bo = nouveau_pixmap_bo(fpix); if (bo) nouveau_bo_wait(bo, NOUVEAU_BO_RD, pNv->client); } } pGC->ops->CopyArea(src_draw, dst_draw, pGC, 0, 0, pDraw->width, pDraw->height, off_x, off_y); FreeScratchGC(pGC); }
static Bool NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_texture_format_t *fmt; unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; uint32_t pitch = exaGetPixmapPitch(pPix); uint32_t log2h = log2i(pPix->drawable.height); uint32_t log2w = log2i(pPix->drawable.width); uint32_t card_filter, card_repeat; fmt = NV30_GetPictTextureFormat(pPict->format); if (!fmt) return FALSE; card_repeat = 3; /* repeatNone */ if (pPict->filter == PictFilterBilinear) card_filter = 2; else card_filter = 1; BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8); PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), bo, 0, reloc); PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), bo, (1 << 16) | 8 | NV30_3D_TEX_FORMAT_DIMS_2D | (fmt->card_fmt << NV30_3D_TEX_FORMAT_FORMAT__SHIFT) | (log2w << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT) | (log2h << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT), reloc, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); PUSH_DATA (push, (card_repeat << NV30_3D_TEX_WRAP_S__SHIFT) | (card_repeat << NV30_3D_TEX_WRAP_T__SHIFT) | (card_repeat << NV30_3D_TEX_WRAP_R__SHIFT)); PUSH_DATA (push, NV30_3D_TEX_ENABLE_ENABLE); PUSH_DATA (push, (pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT ) | fmt->card_swz); PUSH_DATA (push, (card_filter << NV30_3D_TEX_FILTER_MIN__SHIFT) | (card_filter << NV30_3D_TEX_FILTER_MAG__SHIFT) | 0x2000 /* engine lock */); PUSH_DATA (push, (pPix->drawable.width << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | pPix->drawable.height); PUSH_DATA (push, 0x00000000); /* border ARGB */ if (pPict->transform) { BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1); PUSH_DATA (push, 1); BEGIN_NV04(push, NV30_3D(TEX_MATRIX(unit, 0)), 16); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][1])); PUSH_DATAf(push, 0.f); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][2])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][1])); PUSH_DATAf(push, 0.f); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][2])); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][1])); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][2])); } else { BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1); PUSH_DATA (push, 0); } return TRUE; }
static Bool nouveau_exa_pixmap_is_offscreen(PixmapPtr ppix) { return nouveau_pixmap_bo(ppix) != NULL; }
static Bool NV40EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit) { NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; nv_pict_texture_format_t *fmt; NV40EXA_STATE; fmt = NV40_GetPictTextureFormat(pPict->format); if (!fmt) return FALSE; BEGIN_RING(chan, curie, NV40TCL_TEX_OFFSET(unit), 8); if (OUT_RELOCl(chan, bo, 0, tex_reloc) || OUT_RELOCd(chan, bo, fmt->card_fmt | NV40TCL_TEX_FORMAT_LINEAR | NV40TCL_TEX_FORMAT_DIMS_2D | 0x8000 | NV40TCL_TEX_FORMAT_NO_BORDER | (1 << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT), tex_reloc | NOUVEAU_BO_OR, NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1)) return FALSE; if (pPict->repeat) { switch(pPict->repeatType) { case RepeatPad: OUT_RING (chan, NV40TCL_TEX_WRAP_S_CLAMP | NV40TCL_TEX_WRAP_T_CLAMP | NV40TCL_TEX_WRAP_R_CLAMP); break; case RepeatReflect: OUT_RING (chan, NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT | NV40TCL_TEX_WRAP_T_MIRRORED_REPEAT | NV40TCL_TEX_WRAP_R_MIRRORED_REPEAT); break; case RepeatNormal: default: OUT_RING (chan, NV40TCL_TEX_WRAP_S_REPEAT | NV40TCL_TEX_WRAP_T_REPEAT | NV40TCL_TEX_WRAP_R_REPEAT); break; } } else { OUT_RING (chan, NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER | NV40TCL_TEX_WRAP_T_CLAMP_TO_BORDER | NV40TCL_TEX_WRAP_R_CLAMP_TO_BORDER); } OUT_RING (chan, NV40TCL_TEX_ENABLE_ENABLE); OUT_RING (chan, fmt->card_swz); if (pPict->filter == PictFilterBilinear) { OUT_RING (chan, NV40TCL_TEX_FILTER_MIN_LINEAR | NV40TCL_TEX_FILTER_MAG_LINEAR | 0x3fd6); } else { OUT_RING (chan, NV40TCL_TEX_FILTER_MIN_NEAREST | NV40TCL_TEX_FILTER_MAG_NEAREST | 0x3fd6); } OUT_RING (chan, (pPix->drawable.width << 16) | pPix->drawable.height); OUT_RING (chan, 0); /* border ARGB */ BEGIN_RING(chan, curie, NV40TCL_TEX_SIZE1(unit), 1); OUT_RING (chan, (1 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | (uint32_t)exaGetPixmapPitch(pPix)); state->unit[unit].width = (float)pPix->drawable.width; state->unit[unit].height = (float)pPix->drawable.height; state->unit[unit].transform = pPict->transform; return TRUE; }
static Bool setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap) { struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; unsigned h = pict->pDrawable->height; unsigned w = pict->pDrawable->width; unsigned format; format = NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_EDGE | NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_EDGE | log2i(w) << 20 | log2i(h) << 16 | 1 << 12 | /* lod == 1 */ get_tex_format(pNv, pict) | 0x50 /* UNK */; /* NPOT_SIZE expects an even number for width, we can round up uneven * numbers here because EXA always gives 64 byte aligned pixmaps and * for all formats we support 64 bytes represents an even number of * pixels */ w = (w + 1) & ~1; BEGIN_NV04(push, NV10_3D(TEX_OFFSET(unit)), 1); PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(unit)), bo, 0, reloc); BEGIN_NV04(push, NV10_3D(TEX_FORMAT(unit)), 1); PUSH_MTHDs(push, NV10_3D(TEX_FORMAT(unit)), bo, format, reloc, NV10_3D_TEX_FORMAT_DMA0, NV10_3D_TEX_FORMAT_DMA1); BEGIN_NV04(push, NV10_3D(TEX_ENABLE(unit)), 1 ); PUSH_DATA (push, NV10_3D_TEX_ENABLE_ENABLE); BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(unit)), 1); PUSH_DATA (push, exaGetPixmapPitch(pixmap) << 16); BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(unit)), 1); PUSH_DATA (push, (w << 16) | h); BEGIN_NV04(push, NV10_3D(TEX_FILTER(unit)), 1); if (pict->filter == PictFilterNearest) PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_NEAREST | NV10_3D_TEX_FILTER_MINIFY_NEAREST); else PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_LINEAR | NV10_3D_TEX_FILTER_MINIFY_LINEAR); if (pict->transform) { BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1); PUSH_DATA (push, 1); BEGIN_NV04(push, NV10_3D(TEX_MATRIX(unit, 0)), 16); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][0])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][1])); PUSH_DATAf(push, 0.f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][2])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][0])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][1])); PUSH_DATAf(push, 0.f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][2])); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][0])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][1])); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][2])); } else { BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1); PUSH_DATA (push, 0); } return TRUE; }
static Bool NV40EXAPictTexture(NVPtr pNv, PixmapPtr pPix, PicturePtr pPict, int unit) { unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR; struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_texture_format_t *fmt; fmt = NV40_GetPictTextureFormat(pPict->format); if (!fmt) return FALSE; BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8); PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), bo, 0, reloc); PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), bo, fmt->card_fmt | NV40_3D_TEX_FORMAT_LINEAR | NV30_3D_TEX_FORMAT_DIMS_2D | 0x8000 | NV30_3D_TEX_FORMAT_NO_BORDER | (1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT), reloc | NOUVEAU_BO_OR, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); if (pPict->repeat) { switch(pPict->repeatType) { case RepeatPad: PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP | NV30_3D_TEX_WRAP_T_CLAMP | NV30_3D_TEX_WRAP_R_CLAMP); break; case RepeatReflect: PUSH_DATA (push, NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT | NV30_3D_TEX_WRAP_T_MIRRORED_REPEAT | NV30_3D_TEX_WRAP_R_MIRRORED_REPEAT); break; case RepeatNormal: default: PUSH_DATA (push, NV30_3D_TEX_WRAP_S_REPEAT | NV30_3D_TEX_WRAP_T_REPEAT | NV30_3D_TEX_WRAP_R_REPEAT); break; } } else { PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_BORDER | NV30_3D_TEX_WRAP_T_CLAMP_TO_BORDER | NV30_3D_TEX_WRAP_R_CLAMP_TO_BORDER); } PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE); PUSH_DATA (push, fmt->card_swz); if (pPict->filter == PictFilterBilinear) { PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR | NV30_3D_TEX_FILTER_MAG_LINEAR | 0x3fd6); } else { PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST | NV30_3D_TEX_FILTER_MAG_NEAREST | 0x3fd6); } PUSH_DATA (push, (pPix->drawable.width << 16) | pPix->drawable.height); PUSH_DATA (push, 0); /* border ARGB */ BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1); PUSH_DATA (push, (1 << NV40_3D_TEX_SIZE1_DEPTH__SHIFT) | (uint32_t)exaGetPixmapPitch(pPix)); BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 17); PUSH_DATA (push, unit * 4); if (pPict->transform) { PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][1])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][2])); PUSH_DATAf(push, 0); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][1])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][2])); PUSH_DATAf(push, 0); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][1])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][2])); PUSH_DATAf(push, 0); } else { PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); } PUSH_DATAf(push, 1.0 / pPix->drawable.width); PUSH_DATAf(push, 1.0 / pPix->drawable.height); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); return TRUE; }