예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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);
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
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;
}
예제 #9
0
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);
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
static inline Bool
effective_component_alpha(PicturePtr mask)
{
	return mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format);
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #16
0
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();
}
예제 #17
0
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;
}
예제 #18
0
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;
}
예제 #19
0
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;
}