static void setup_combiners(NVPtr pNv, PicturePtr src, PicturePtr mask) { struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *celsius = pNv->Nv3D; uint32_t rc_in_alpha = 0, rc_in_rgb = 0; if (PICT_FORMAT_A(src->format)) rc_in_alpha |= RC_IN_TEX(A, ALPHA, 0); else rc_in_alpha |= RC_IN_ONE(A); if (mask && PICT_FORMAT_A(mask->format)) rc_in_alpha |= RC_IN_TEX(B, ALPHA, 1); else rc_in_alpha |= RC_IN_ONE(B); if (effective_component_alpha(mask)) { if (!needs_src_alpha(pNv->alu)) { /* The alpha channels won't be used for blending. Drop * them, as our pixels only have 4 components... * output_i = src_i * mask_i */ if (PICT_FORMAT_RGB(src->format)) rc_in_rgb |= RC_IN_TEX(A, RGB, 0); } else { /* The RGB channels won't be used for blending. Drop * them. * output_i = src_alpha * mask_i */ if (PICT_FORMAT_A(src->format)) rc_in_rgb |= RC_IN_TEX(A, ALPHA, 0); else rc_in_rgb |= RC_IN_ONE(A); } rc_in_rgb |= RC_IN_TEX(B, RGB, 1); } else { if (PICT_FORMAT_RGB(src->format)) rc_in_rgb |= RC_IN_TEX(A, RGB, 0); if (mask && PICT_FORMAT_A(mask->format)) rc_in_rgb |= RC_IN_TEX(B, ALPHA, 1); else rc_in_rgb |= RC_IN_ONE(B); } BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 1); OUT_RING (chan, rc_in_alpha); BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(0), 1); OUT_RING (chan, rc_in_rgb); }
Bool NV40EXACheckComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict) { nv_pict_surface_format_t *fmt; nv_pict_op_t *opr; opr = NV40_GetPictOpRec(op); if (!opr) NOUVEAU_FALLBACK("unsupported blend op 0x%x\n", op); fmt = NV40_GetPictSurfaceFormat(pdPict->format); if (!fmt) NOUVEAU_FALLBACK("dst picture format 0x%08x not supported\n", pdPict->format); if (!NV40EXACheckCompositeTexture(psPict, pdPict, op)) NOUVEAU_FALLBACK("src picture\n"); if (pmPict) { if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format) && opr->src_alpha && opr->src_card_op != SF(ZERO)) NOUVEAU_FALLBACK("mask CA + SA\n"); if (!NV40EXACheckCompositeTexture(pmPict, pdPict, op)) NOUVEAU_FALLBACK("mask picture\n"); } return TRUE; }
static Bool NV30EXAPicture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit, uint32_t *color, uint32_t *alpha, uint32_t *solid) { uint32_t shift, source; if (pPict && pPict->pDrawable) { if (!NV30EXATexture(pScrn, pPix, pPict, unit)) return FALSE; *solid = 0x00000000; source = RCSRC_TEX(unit); } else if (pPict) { *solid = pPict->pSourcePict->solidFill.color; source = RCSRC_COL(unit); } if (pPict && PICT_FORMAT_RGB(pPict->format)) *color = RCSEL_COLOR | source; else *color = RCSEL_ALPHA | RCINP_ZERO; if (pPict && PICT_FORMAT_A(pPict->format)) *alpha = RCSEL_ALPHA | source; else *alpha = RCSEL_ALPHA | RCINP_ONE; if (unit) shift = RCINP_B__SHIFT; else shift = RCINP_A__SHIFT; *color <<= shift; *alpha <<= shift; return TRUE; }
static uint32_t i915_get_blend_cntl(int op, PicturePtr mask, uint32_t dst_format) { uint32_t sblend, dblend; sblend = i915_blend_op[op].src_blend; dblend = i915_blend_op[op].dst_blend; /* If there's no dst alpha channel, adjust the blend op so that we'll * treat it as always 1. */ if (PICT_FORMAT_A(dst_format) == 0 && i915_blend_op[op].dst_alpha) { if (sblend == BLENDFACT_DST_ALPHA) sblend = BLENDFACT_ONE; else if (sblend == BLENDFACT_INV_DST_ALPHA) sblend = BLENDFACT_ZERO; } /* i915 engine reads 8bit color buffer into green channel in cases like color buffer blending .etc, and also writes back green channel. So with dst_alpha blend we should use color factor. See spec on "8-bit rendering" */ if ((dst_format == PICT_a8) && i915_blend_op[op].dst_alpha) { if (sblend == BLENDFACT_DST_ALPHA) sblend = BLENDFACT_DST_COLR; else if (sblend == BLENDFACT_INV_DST_ALPHA) sblend = BLENDFACT_INV_DST_COLR; } /* If the source alpha is being used, then we should only be in a case * where the source blend factor is 0, and the source blend value is the * mask channels multiplied by the source picture's alpha. */ if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) && i915_blend_op[op].src_alpha) { if (dblend == BLENDFACT_SRC_ALPHA) { dblend = BLENDFACT_SRC_COLR; } else if (dblend == BLENDFACT_INV_SRC_ALPHA) { dblend = BLENDFACT_INV_SRC_COLR; } } return S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); }
static Bool i830_get_blend_cntl(ScrnInfoPtr scrn, int op, PicturePtr mask, uint32_t dst_format, uint32_t * blendctl) { uint32_t sblend, dblend; sblend = i830_blend_op[op].src_blend; dblend = i830_blend_op[op].dst_blend; /* If there's no dst alpha channel, adjust the blend op so that we'll treat * it as always 1. */ if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) { if (sblend == BLENDFACTOR_DST_ALPHA) sblend = BLENDFACTOR_ONE; else if (sblend == BLENDFACTOR_INV_DST_ALPHA) sblend = BLENDFACTOR_ZERO; } /* For blending purposes, COLR_BUF_8BIT values show up in the green * channel. So we can't use the alpha channel. */ if (dst_format == PICT_a8 && ((sblend == BLENDFACTOR_DST_ALPHA || sblend == BLENDFACTOR_INV_DST_ALPHA))) { intel_debug_fallback(scrn, "Can't do dst alpha blending with " "PICT_a8 dest.\n"); return FALSE; } /* If the source alpha is being used, then we should only be in a case * where the source blend factor is 0, and the source blend value is the * mask channels multiplied by the source picture's alpha. */ if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) && i830_blend_op[op].src_alpha) { if (dblend == BLENDFACTOR_SRC_ALPHA) { dblend = BLENDFACTOR_SRC_COLR; } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) { dblend = BLENDFACTOR_INV_SRC_COLR; } } *blendctl = (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | (dblend << S8_DST_BLEND_FACTOR_SHIFT); return TRUE; }
static boolean blend_for_op(struct xorg_composite_blend *blend, int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) { const int num_blends = sizeof(xorg_blends)/sizeof(struct xorg_composite_blend); int i; boolean supported = FALSE; /* our default in case something goes wrong */ *blend = xorg_blends[BLEND_OP_OVER]; for (i = 0; i < num_blends; ++i) { if (xorg_blends[i].op == op) { *blend = xorg_blends[i]; supported = TRUE; } } /* If there's no dst alpha channel, adjust the blend op so that we'll treat * it as always 1. */ if (pDstPicture && PICT_FORMAT_A(pDstPicture->format) == 0 && blend->alpha_dst) { if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) blend->rgb_src = PIPE_BLENDFACTOR_ONE; else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) blend->rgb_src = PIPE_BLENDFACTOR_ZERO; } /* If the source alpha is being used, then we should only be in a case where * the source blend factor is 0, and the source blend value is the mask * channels multiplied by the source picture's alpha. */ if (pMaskPicture && pMaskPicture->componentAlpha && PICT_FORMAT_RGB(pMaskPicture->format) && blend->alpha_src) { if (blend->rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) { blend->rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR; } else if (blend->rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) { blend->rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR; } } return supported; }
Bool i915_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, int width, int height) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; uint32_t tmp1; /* Check for unsupported compositing operations. */ if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) { intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", op); return FALSE; } if (mask_picture != NULL && mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { /* Check if it's component alpha that relies on a source alpha * and on the source value. We can only get one of those * into the single source value that we get to blend with. */ if (i915_blend_op[op].src_alpha && (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { if (op != PictOpOver) { intel_debug_fallback(scrn, "Component alpha not supported " "with source alpha and source " "value blending.\n"); return FALSE; } } } if (!i915_get_dest_format(dest_picture, &tmp1)) { intel_debug_fallback(scrn, "Get Color buffer format\n"); return FALSE; } if (width > 2048 || height > 2048) return FALSE; return TRUE; }
Bool i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, int width, int height) { ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen); uint32_t tmp1; /* Check for unsupported compositing operations. */ if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) { intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", op); return FALSE; } if (mask_picture != NULL && mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { /* Check if it's component alpha that relies on a source alpha and on * the source value. We can only get one of those into the single * source value that we get to blend with. */ if (i830_blend_op[op].src_alpha && (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { intel_debug_fallback(scrn, "Component alpha not " "supported with source alpha and " "source value blending.\n"); return FALSE; } } if (!i830_get_dest_format(dest_picture, &tmp1)) { intel_debug_fallback(scrn, "Get Color buffer format\n"); return FALSE; } if (width > 2048 || height > 2048) { intel_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height); return FALSE; } return TRUE; }
boolean xorg_composite_accelerated(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); struct xorg_composite_blend blend; if (!is_filter_accelerated(pSrcPicture) || !is_filter_accelerated(pMaskPicture)) { XORG_FALLBACK("Unsupported Xrender filter"); } if (pSrcPicture->pSourcePict) { if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill) XORG_FALLBACK("Gradients not enabled (haven't been well tested)"); } if (blend_for_op(&blend, op, pSrcPicture, pMaskPicture, pDstPicture)) { /* Check for component alpha */ if (pMaskPicture && pMaskPicture->componentAlpha && PICT_FORMAT_RGB(pMaskPicture->format)) { if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { XORG_FALLBACK("Component alpha not supported with source " "alpha and source value blending. (op=%d)", op); } } return TRUE; } XORG_FALLBACK("Unsupported composition operation = %d", op); }
static Bool setup_picture(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap, int unit, uint32_t *color, uint32_t *alpha) { struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t shift, source; if (pict && pict->pDrawable) { if (!setup_texture(pNv, unit, pict, pixmap)) return FALSE; source = RCSRC_TEX(unit); } else if (pict) { BEGIN_NV04(push, NV10_3D(RC_COLOR(unit)), 1); PUSH_DATA (push, pict->pSourcePict->solidFill.color); source = RCSRC_COL(unit); } if (pict && PICT_FORMAT_RGB(pict->format)) *color = RCSEL_COLOR | source; else *color = RCSEL_ALPHA | RCINP_ZERO; if (pict && PICT_FORMAT_A(pict->format)) *alpha = RCSEL_ALPHA | source; else *alpha = RCSEL_ALPHA | RCINP_ONE; if (unit) shift = RCINP_B__SHIFT; else shift = RCINP_A__SHIFT; *color <<= shift; *alpha <<= shift; return TRUE; }
Bool NV30EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *rankine = pNv->Nv3D; nv_pict_op_t *blend; int fpid = NV30EXA_FPID_PASS_COL0; NV30EXA_STATE; if (MARK_RING(chan, 128, 1 + 1 + 4)) return FALSE; blend = NV30_GetPictOpRec(op); NV30_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV30_SetupSurface(pScrn, pdPix, pdPict) || !NV30EXATexture(pScrn, psPix, psPict, 0)) { MARK_UNDO(chan); return FALSE; } #if 0 #define printformat(f) ErrorF("(%xh %s %dbpp A%dR%dG%dB%d)",f,(f>>16)&0xf==2?"ARGB":"ABGR",(f>>24),(f&0xf000)>>12,(f&0xf00)>>8,(f&0xf0)>>4,f&0xf) ErrorF("Preparecomposite src(%dx%d)",psPict->pDrawable->width,psPict->pDrawable->height); printformat((psPict->format)); ErrorF(" dst(%dx%d)",pdPict->pDrawable->width,pdPict->pDrawable->height); printformat((pdPict->format)); if (pmPict) { ErrorF(" mask(%dx%d)",pmPict->pDrawable->width,pmPict->pDrawable->height); printformat((pmPict->format)); } ErrorF("\n"); #endif if (pmPict) { if (!NV30EXATexture(pScrn, pmPix, pmPict, 1)) { MARK_UNDO(chan); return FALSE; } if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fpid = NV30EXA_FPID_COMPOSITE_MASK_SA_CA; else fpid = NV30EXA_FPID_COMPOSITE_MASK_CA; } else { fpid = NV30EXA_FPID_COMPOSITE_MASK; } state->have_mask = TRUE; } else { fpid = NV30EXA_FPID_PASS_TEX0; state->have_mask = FALSE; } if (!NV30_LoadFragProg(pScrn, (pdPict->format == PICT_a8) ? nv40_fp_map_a8[fpid] : nv40_fp_map[fpid])) { MARK_UNDO(chan); return FALSE; } BEGIN_RING(chan, rankine, 0x23c, 1); OUT_RING (chan, pmPict?3:1); pNv->alu = op; pNv->pspict = psPict; pNv->pmpict = pmPict; pNv->pdpict = pdPict; pNv->pspix = psPix; pNv->pmpix = pmPix; pNv->pdpix = pdPix; chan->flush_notify = NV30EXAStateCompositeReemit; return TRUE; }
static inline Bool effective_component_alpha(PicturePtr mask) { return mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format); }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; nv_pict_op_t *blend; int fpid = NV40EXA_FPID_PASS_COL0; NV40EXA_STATE; if (MARK_RING(chan, 128, 1 + 1 + 2*2)) return FALSE; blend = NV40_GetPictOpRec(op); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXATexture(pScrn, psPix, psPict, 0)) { MARK_UNDO(chan); return FALSE; } NV40_LoadVtxProg(pScrn, &nv40_vp_exa_render); if (pmPict) { if (!NV40EXATexture(pScrn, pmPix, pmPict, 1)) { MARK_UNDO(chan); return FALSE; } if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fpid = NV40EXA_FPID_COMPOSITE_MASK_SA_CA; else fpid = NV40EXA_FPID_COMPOSITE_MASK_CA; } else { fpid = NV40EXA_FPID_COMPOSITE_MASK; } state->have_mask = TRUE; } else { fpid = NV40EXA_FPID_PASS_TEX0; state->have_mask = FALSE; } if (!NV40_LoadFragProg(pScrn, (pdPict->format == PICT_a8) ? nv40_fp_map_a8[fpid] : nv40_fp_map[fpid])) { MARK_UNDO(chan); return FALSE; } /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); OUT_RING (chan, 2); BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); OUT_RING (chan, 1); pNv->alu = op; pNv->pspict = psPict; pNv->pmpict = pmPict; pNv->pdpict = pdPict; pNv->pspix = psPix; pNv->pmpix = pmPix; pNv->pdpix = pdPix; chan->flush_notify = NV40EXAStateCompositeReemit; return TRUE; }
Bool NV30EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV30_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t sc, sa, mc, ma, solid[2]; if (!PUSH_SPACE(push, 128)) return FALSE; PUSH_RESET(push); /* setup render target and blending */ if (!NV30_SetupSurface(pScrn, pdPix, pdPict)) return FALSE; NV30_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); /* select picture sources */ if (!NV30EXAPicture(pScrn, psPix, psPict, 0, &sc, &sa, &solid[0])) return FALSE; if (!NV30EXAPicture(pScrn, pmPix, pmPict, 1, &mc, &ma, &solid[1])) return FALSE; /* configure register combiners */ BEGIN_NV04(push, NV30_3D(RC_IN_ALPHA(0)), 6); PUSH_DATA (push, sa | ma); if (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) PUSH_DATA(push, sa | mc); else PUSH_DATA(push, sc | mc); } else { PUSH_DATA(push, sc | ma); } PUSH_DATA (push, solid[0]); PUSH_DATA (push, solid[1]); PUSH_DATA (push, 0x00000c00); PUSH_DATA (push, 0x00000c00); BEGIN_NV04(push, NV30_3D(RC_FINAL0), 3); if (pdPict->format != PICT_a8) PUSH_DATA (push, 0x0000000c); else PUSH_DATA (push, 0x0000001c); PUSH_DATA (push, 0x00001c00); PUSH_DATA (push, 0x01000101); /* select fragprog which just sources textures for combiners */ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, PFP_PASS, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1); PUSH_DATA (push, 0x0001000f); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1); PUSH_DATA (push, 3); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }
static PicturePtr uxa_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, int *out_y) { uxa_screen_t *uxa_screen = uxa_get_screen(screen); PicturePtr glyph_picture = GetGlyphPicture(glyph, screen); uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != 0]; struct uxa_glyph *priv = NULL; int size, mask, pos, s; if (glyph->info.width > GLYPH_MAX_SIZE || glyph->info.height > GLYPH_MAX_SIZE) return NULL; for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2) if (glyph->info.width <= size && glyph->info.height <= size) break; s = uxa_glyph_size_to_count(size); mask = uxa_glyph_count_to_mask(s); pos = (cache->count + s - 1) & mask; if (pos < GLYPH_CACHE_SIZE) { cache->count = pos + s; } else { for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) { int i = cache->evict & uxa_glyph_size_to_mask(s); GlyphPtr evicted = cache->glyphs[i]; if (evicted == NULL) continue; priv = uxa_glyph_get_private(evicted); if (priv->size >= s) { cache->glyphs[i] = NULL; uxa_glyph_set_private(evicted, NULL); pos = cache->evict & uxa_glyph_size_to_mask(size); } else priv = NULL; break; } if (priv == NULL) { int count = uxa_glyph_size_to_count(size); mask = uxa_glyph_count_to_mask(count); pos = cache->evict & mask; for (s = 0; s < count; s++) { GlyphPtr evicted = cache->glyphs[pos + s]; if (evicted != NULL) { if (priv != NULL) free(priv); priv = uxa_glyph_get_private(evicted); uxa_glyph_set_private(evicted, NULL); cache->glyphs[pos + s] = NULL; } } } /* And pick a new eviction position */ cache->evict = rand() % GLYPH_CACHE_SIZE; } if (priv == NULL) { priv = malloc(sizeof(struct uxa_glyph)); if (priv == NULL) return NULL; } uxa_glyph_set_private(glyph, priv); cache->glyphs[pos] = glyph; priv->cache = cache; priv->size = size; priv->pos = pos; s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE)); priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE; priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE; for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) { if (pos & 1) priv->x += s; if (pos & 2) priv->y += s; pos >>= 2; } uxa_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, priv->y); *out_x = priv->x; *out_y = priv->y; return cache->picture; }
static void i915_composite_emit_shader(intel_screen_private *intel, CARD8 op) { PicturePtr mask_picture = intel->render_mask_picture; PixmapPtr mask = intel->render_mask; int src_reg, mask_reg; Bool is_solid_src, is_solid_mask; Bool dest_is_alpha = PIXMAN_FORMAT_RGB(intel->render_dest_picture->format) == 0; int tex_unit, t; FS_LOCALS(); is_solid_src = intel->render_source_is_solid; is_solid_mask = intel->render_mask_is_solid; FS_BEGIN(); /* Declare the registers necessary for our program. */ t = 0; if (is_solid_src) { i915_fs_dcl(FS_T8); src_reg = FS_T8; } else { i915_fs_dcl(FS_T0); i915_fs_dcl(FS_S0); t++; } if (!mask) { /* No mask, so load directly to output color */ if (! is_solid_src) { if (dest_is_alpha) src_reg = FS_R0; else src_reg = FS_OC; if (intel_transform_is_affine(intel->transform[0])) i915_fs_texld(src_reg, FS_S0, FS_T0); else i915_fs_texldp(src_reg, FS_S0, FS_T0); } if (src_reg != FS_OC) { if (dest_is_alpha) i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W)); else i915_fs_mov(FS_OC, i915_fs_operand_reg(src_reg)); } } else { if (is_solid_mask) { i915_fs_dcl(FS_T9); mask_reg = FS_T9; } else { i915_fs_dcl(FS_T0 + t); i915_fs_dcl(FS_S0 + t); } tex_unit = 0; if (! is_solid_src) { /* Load the source_picture texel */ if (intel_transform_is_affine(intel->transform[tex_unit])) i915_fs_texld(FS_R0, FS_S0, FS_T0); else i915_fs_texldp(FS_R0, FS_S0, FS_T0); src_reg = FS_R0; tex_unit++; } if (! is_solid_mask) { /* Load the mask_picture texel */ if (intel_transform_is_affine(intel->transform[tex_unit])) i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t); else i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); mask_reg = FS_R1; } if (dest_is_alpha) { i915_fs_mul(FS_OC, i915_fs_operand(src_reg, W, W, W, W), i915_fs_operand(mask_reg, W, W, W, W)); } else { /* If component alpha is active in the mask and the blend * operation uses the source alpha, then we know we don't * need the source value (otherwise we would have hit a * fallback earlier), so we provide the source alpha (src.A * * mask.X) as output color. * Conversely, if CA is set and we don't need the source alpha, * then we produce the source value (src.X * mask.X) and the * source alpha is unused. Otherwise, we provide the non-CA * source value (src.X * mask.A). */ if (mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { if (i915_blend_op[op].src_alpha) { i915_fs_mul(FS_OC, i915_fs_operand(src_reg, W, W, W, W), i915_fs_operand_reg(mask_reg)); } else { i915_fs_mul(FS_OC, i915_fs_operand_reg(src_reg), i915_fs_operand_reg(mask_reg)); } } else { i915_fs_mul(FS_OC, i915_fs_operand_reg(src_reg), i915_fs_operand(mask_reg, W, W, W, W)); } } } FS_END(); }
Bool i915_prepare_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, PixmapPtr source, PixmapPtr mask, PixmapPtr dest) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ intel_get_pixmap_bo(dest), source ? intel_get_pixmap_bo(source) : NULL, mask ? intel_get_pixmap_bo(mask) : NULL, }; int tex_unit = 0; int floats_per_vertex; intel->render_source_picture = source_picture; intel->render_source = source; intel->render_mask_picture = mask_picture; intel->render_mask = mask; intel->render_dest_picture = dest_picture; intel->render_dest = dest; intel->render_source_is_solid = FALSE; if (source_picture->pSourcePict) { SourcePict *source = source_picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) { intel->render_source_is_solid = TRUE; intel->render_source_solid = source->solidFill.color; } } if (!intel->render_source_is_solid && !intel_check_pitch_3d(source)) return FALSE; intel->render_mask_is_solid = FALSE; if (mask) { if (mask_picture->pSourcePict) { SourcePict *source = mask_picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) { intel->render_mask_is_solid = TRUE; intel->render_mask_solid = source->solidFill.color; } } if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask)) return FALSE; } if (!intel_check_pitch_3d(dest)) return FALSE; if (!i915_get_dest_format(dest_picture, &intel->i915_render_state.dst_format)) return FALSE; if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; intel->needs_render_ca_pass = FALSE; if (mask_picture != NULL && mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { /* Check if it's component alpha that relies on a source alpha * and on the source value. We can only get one of those * into the single source value that we get to blend with. */ if (i915_blend_op[op].src_alpha && (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { if (op != PictOpOver) return FALSE; intel->needs_render_ca_pass = TRUE; } } intel->transform[0] = NULL; intel->scale_units[0][0] = -1; intel->scale_units[0][1] = -1; intel->transform[1] = NULL; intel->scale_units[1][0] = -1; intel->scale_units[1][1] = -1; floats_per_vertex = 2; /* dest x/y */ if (! intel->render_source_is_solid) { if (!i915_texture_setup(source_picture, source, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup src texture\n"); return FALSE; } if (intel_transform_is_affine(source_picture->transform)) floats_per_vertex += 2; /* src x/y */ else floats_per_vertex += 4; /* src x/y/z/w */ } if (mask != NULL) { if (! intel->render_mask_is_solid) { if (!i915_texture_setup(mask_picture, mask, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup mask texture\n"); return FALSE; } if (intel_transform_is_affine(mask_picture->transform)) floats_per_vertex += 2; /* mask x/y */ else floats_per_vertex += 4; /* mask x/y/z/w */ } } intel->i915_render_state.op = op; /* BUF_INFO is an implicit flush */ if (dest != intel->render_current_dest) intel_batch_do_flush(scrn); else if((source && intel_pixmap_is_dirty(source)) || (mask && intel_pixmap_is_dirty(mask))) intel_batch_emit_flush(scrn); intel->needs_render_state_emit = TRUE; intel->prim_emit = i915_emit_composite_primitive; if (!mask) { if (intel->render_source_is_solid) intel->prim_emit = i915_emit_composite_primitive_constant; else if (intel->transform[0] == NULL) intel->prim_emit = i915_emit_composite_primitive_identity_source; else if (intel_transform_is_affine(intel->transform[0])) intel->prim_emit = i915_emit_composite_primitive_affine_source; } else { if (intel->transform[0] == NULL) { if (intel->render_source_is_solid) intel->prim_emit = i915_emit_composite_primitive_constant_identity_mask; else if (intel->transform[1] == NULL) intel->prim_emit = i915_emit_composite_primitive_identity_source_mask; } } if (floats_per_vertex != intel->floats_per_vertex) { intel->floats_per_vertex = floats_per_vertex; intel->needs_render_vertex_emit = TRUE; } return TRUE; }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV40_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t fragprog; if (!PUSH_SPACE(push, 128)) NOUVEAU_FALLBACK("space\n"); PUSH_RESET(push); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXAPicture(pNv, psPix, psPict, 0)) return FALSE; if (pmPict) { if (!NV40EXAPicture(pNv, pmPix, pmPict, 1)) return FALSE; if (pdPict->format == PICT_a8) { fragprog = PFP_C_A8; } else if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fragprog = PFP_CCASA; else fragprog = PFP_CCA; } else { fragprog = PFP_C; } } else { if (pdPict->format == PICT_a8) fragprog = PFP_S_A8; else fragprog = PFP_S; } BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, fragprog, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x02000000); /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 2); BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 1); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }
Bool i830_prepare_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, PixmapPtr source, PixmapPtr mask, PixmapPtr dest) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ intel_get_pixmap_bo(source), mask ? intel_get_pixmap_bo(mask) : NULL, intel_get_pixmap_bo(dest), }; intel->render_source_picture = source_picture; intel->render_source = source; intel->render_mask_picture = mask_picture; intel->render_mask = mask; intel->render_dest_picture = dest_picture; intel->render_dest = dest; if (!intel_check_pitch_3d(source)) return FALSE; if (mask) { if (mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { /* Check if it's component alpha that relies on a source alpha and on * the source value. We can only get one of those into the single * source value that we get to blend with. */ if (i830_blend_op[op].src_alpha && (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { intel_debug_fallback(scrn, "Component alpha not " "supported with source alpha and " "source value blending.\n"); return FALSE; } } if (!intel_check_pitch_3d(mask)) return FALSE; } if (!intel_check_pitch_3d(dest)) return FALSE; if (!i830_get_dest_format(dest_picture, &intel->render_dest_format)) return FALSE; if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; if (mask) { intel->transform[1] = NULL; intel->scale_units[1][0] = -1; intel->scale_units[1][1] = -1; } { uint32_t cblend, ablend, blendctl; /* If component alpha is active in the mask and the blend operation * uses the source alpha, then we know we don't need the source * value (otherwise we would have hit a fallback earlier), so we * provide the source alpha (src.A * mask.X) as output color. * Conversely, if CA is set and we don't need the source alpha, then * we produce the source value (src.X * mask.X) and the source alpha * is unused.. Otherwise, we provide the non-CA source value * (src.X * mask.A). * * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8 * pictures, but we need to implement it for 830/845 and there's no * harm done in leaving it in. */ cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE | TB0C_OUTPUT_WRITE_CURRENT; ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | TB0A_OUTPUT_WRITE_CURRENT; /* Get the source picture's channels into TBx_ARG1 */ if ((mask_picture != NULL && mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format) && i830_blend_op[op].src_alpha) || dest_picture->format == PICT_a8) { /* Producing source alpha value, so the first set of channels * is src.A instead of src.X. We also do this if the destination * is a8, in which case src.G is what's written, and the other * channels are ignored. */ ablend |= TB0A_ARG1_SEL_TEXEL0; cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; } else { if (PICT_FORMAT_RGB(source_picture->format) != 0) cblend |= TB0C_ARG1_SEL_TEXEL0; else cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ ablend |= TB0A_ARG1_SEL_TEXEL0; } if (mask) { cblend |= TB0C_ARG2_SEL_TEXEL1; if (dest_picture->format == PICT_a8 || ! mask_picture->componentAlpha || ! PICT_FORMAT_RGB(mask_picture->format)) cblend |= TB0C_ARG2_REPLICATE_ALPHA; ablend |= TB0A_ARG2_SEL_TEXEL1; } else { cblend |= TB0C_ARG2_SEL_ONE; ablend |= TB0A_ARG2_SEL_ONE; } if (!i830_get_blend_cntl (scrn, op, mask_picture, dest_picture->format, &blendctl)) { return FALSE; } intel->cblend = cblend; intel->ablend = ablend; intel->s8_blendctl = blendctl; } if(intel_pixmap_is_dirty(source) || (mask && intel_pixmap_is_dirty(mask))) intel_batch_emit_flush(scrn); intel->needs_render_state_emit = TRUE; return TRUE; }