103b705cfSriastradh#ifndef SNA_RENDER_INLINE_H
203b705cfSriastradh#define SNA_RENDER_INLINE_H
303b705cfSriastradh
403b705cfSriastradhstatic inline bool need_tiling(struct sna *sna, int16_t width, int16_t height)
503b705cfSriastradh{
603b705cfSriastradh	/* Is the damage area too large to fit in 3D pipeline,
703b705cfSriastradh	 * and so do we need to split the operation up into tiles?
803b705cfSriastradh	 */
903b705cfSriastradh	return (width > sna->render.max_3d_size ||
1003b705cfSriastradh		height > sna->render.max_3d_size);
1103b705cfSriastradh}
1203b705cfSriastradh
1303b705cfSriastradhstatic inline bool need_redirect(struct sna *sna, PixmapPtr dst)
1403b705cfSriastradh{
1503b705cfSriastradh	/* Is the pixmap too large to render to? */
1603b705cfSriastradh	return (dst->drawable.width > sna->render.max_3d_size ||
1703b705cfSriastradh		dst->drawable.height > sna->render.max_3d_size);
1803b705cfSriastradh}
1903b705cfSriastradh
2003b705cfSriastradhstatic force_inline float pack_2s(int16_t x, int16_t y)
2103b705cfSriastradh{
2203b705cfSriastradh	union {
2303b705cfSriastradh		struct sna_coordinate p;
2403b705cfSriastradh		float f;
2503b705cfSriastradh	} u;
2603b705cfSriastradh	u.p.x = x;
2703b705cfSriastradh	u.p.y = y;
2803b705cfSriastradh	return u.f;
2903b705cfSriastradh}
3003b705cfSriastradh
3103b705cfSriastradhstatic force_inline int vertex_space(struct sna *sna)
3203b705cfSriastradh{
3303b705cfSriastradh	return sna->render.vertex_size - sna->render.vertex_used;
3403b705cfSriastradh}
3503b705cfSriastradhstatic force_inline void vertex_emit(struct sna *sna, float v)
3603b705cfSriastradh{
3703b705cfSriastradh	assert(sna->render.vertex_used < sna->render.vertex_size);
3803b705cfSriastradh	sna->render.vertices[sna->render.vertex_used++] = v;
3903b705cfSriastradh}
4003b705cfSriastradhstatic force_inline void vertex_emit_2s(struct sna *sna, int16_t x, int16_t y)
4103b705cfSriastradh{
4203b705cfSriastradh	vertex_emit(sna, pack_2s(x, y));
4303b705cfSriastradh}
4403b705cfSriastradh
4503b705cfSriastradhstatic force_inline int batch_space(struct sna *sna)
4603b705cfSriastradh{
4703b705cfSriastradh	assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
4803b705cfSriastradh	assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED <= sna->kgem.surface);
4903b705cfSriastradh	return sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED;
5003b705cfSriastradh}
5103b705cfSriastradh
5203b705cfSriastradhstatic force_inline void batch_emit(struct sna *sna, uint32_t dword)
5303b705cfSriastradh{
5403b705cfSriastradh	assert(sna->kgem.mode != KGEM_NONE);
5503b705cfSriastradh	assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface);
5603b705cfSriastradh	sna->kgem.batch[sna->kgem.nbatch++] = dword;
5703b705cfSriastradh}
5803b705cfSriastradh
59fe8aea9eSmrgstatic force_inline void batch_emit_aligned(struct sna *sna, uint32_t dword, unsigned align)
60fe8aea9eSmrg{
61fe8aea9eSmrg	assert(sna->kgem.mode != KGEM_NONE);
62fe8aea9eSmrg	assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface);
63fe8aea9eSmrg	while (sna->kgem.nbatch & (align-1))
64fe8aea9eSmrg		sna->kgem.batch[sna->kgem.nbatch++] = 0;
65fe8aea9eSmrg	sna->kgem.batch[sna->kgem.nbatch++] = dword;
66fe8aea9eSmrg}
67fe8aea9eSmrg
6842542f5fSchristosstatic force_inline void batch_emit64(struct sna *sna, uint64_t qword)
6942542f5fSchristos{
7042542f5fSchristos	assert(sna->kgem.mode != KGEM_NONE);
7142542f5fSchristos	assert(sna->kgem.nbatch + 2 + KGEM_BATCH_RESERVED < sna->kgem.surface);
7242542f5fSchristos	*(uint64_t *)(sna->kgem.batch+sna->kgem.nbatch) = qword;
7342542f5fSchristos	sna->kgem.nbatch += 2;
7442542f5fSchristos}
7542542f5fSchristos
7603b705cfSriastradhstatic force_inline void batch_emit_float(struct sna *sna, float f)
7703b705cfSriastradh{
7803b705cfSriastradh	union {
7903b705cfSriastradh		uint32_t dw;
8003b705cfSriastradh		float f;
8103b705cfSriastradh	} u;
8203b705cfSriastradh	u.f = f;
8303b705cfSriastradh	batch_emit(sna, u.dw);
8403b705cfSriastradh}
8503b705cfSriastradh
8603b705cfSriastradhstatic inline bool
8703b705cfSriastradhis_gpu(struct sna *sna, DrawablePtr drawable, unsigned prefer)
8803b705cfSriastradh{
8903b705cfSriastradh	struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable);
9003b705cfSriastradh
9103b705cfSriastradh	if (priv == NULL || priv->clear || priv->cpu)
9203b705cfSriastradh		return false;
9303b705cfSriastradh
9403b705cfSriastradh	if (priv->cpu_damage == NULL)
9503b705cfSriastradh		return true;
9603b705cfSriastradh
9703b705cfSriastradh	if (priv->gpu_damage && !priv->gpu_bo->proxy &&
9803b705cfSriastradh	    (sna->render.prefer_gpu & prefer))
9903b705cfSriastradh		return true;
10003b705cfSriastradh
10103b705cfSriastradh	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
10203b705cfSriastradh		return true;
10303b705cfSriastradh
10442542f5fSchristos	if (DAMAGE_IS_ALL(priv->cpu_damage))
10542542f5fSchristos		return false;
10642542f5fSchristos
10703b705cfSriastradh	return priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo);
10803b705cfSriastradh}
10903b705cfSriastradh
11003b705cfSriastradhstatic inline bool
11103b705cfSriastradhtoo_small(struct sna_pixmap *priv)
11203b705cfSriastradh{
11303b705cfSriastradh	assert(priv);
11403b705cfSriastradh
11503b705cfSriastradh	if (priv->gpu_bo)
11603b705cfSriastradh		return false;
11703b705cfSriastradh
11803b705cfSriastradh	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
11903b705cfSriastradh		return false;
12003b705cfSriastradh
12103b705cfSriastradh	return (priv->create & KGEM_CAN_CREATE_GPU) == 0;
12203b705cfSriastradh}
12303b705cfSriastradh
12413496ba1Ssnjstatic inline bool
12513496ba1Ssnjcan_render_to_picture(PicturePtr dst)
12613496ba1Ssnj{
12713496ba1Ssnj	if (dst->alphaMap) {
12813496ba1Ssnj		DBG(("%s(pixmap=%ld) -- no, has alphamap\n", __FUNCTION__,
12913496ba1Ssnj		     get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber));
13013496ba1Ssnj		return false;
13113496ba1Ssnj	}
13213496ba1Ssnj
13313496ba1Ssnj	switch (PICT_FORMAT_TYPE(dst->format)) {
13413496ba1Ssnj	case PICT_TYPE_COLOR:
13513496ba1Ssnj	case PICT_TYPE_GRAY:
13613496ba1Ssnj	case PICT_TYPE_OTHER:
13713496ba1Ssnj		DBG(("%s(pixmap=%ld) -- no, has palette\n", __FUNCTION__,
13813496ba1Ssnj		     get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber));
13913496ba1Ssnj		return false;
14013496ba1Ssnj	default:
14113496ba1Ssnj		break;
14213496ba1Ssnj	}
14313496ba1Ssnj
14413496ba1Ssnj	return true;
14513496ba1Ssnj}
14613496ba1Ssnj
14713496ba1Ssnj
14842542f5fSchristosstatic inline bool
14942542f5fSchristosis_gpu_dst(struct sna_pixmap *priv)
15042542f5fSchristos{
15142542f5fSchristos	assert(priv);
15242542f5fSchristos
15342542f5fSchristos	if (too_small(priv))
15442542f5fSchristos		return false;
15542542f5fSchristos
15642542f5fSchristos	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
15742542f5fSchristos		return true;
15842542f5fSchristos
15942542f5fSchristos	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
16042542f5fSchristos		return true;
16142542f5fSchristos
16242542f5fSchristos	if (DAMAGE_IS_ALL(priv->cpu_damage))
16342542f5fSchristos		return false;
16442542f5fSchristos
16542542f5fSchristos	return priv->gpu_damage != NULL || !priv->cpu;
16642542f5fSchristos}
16742542f5fSchristos
16803b705cfSriastradhstatic inline bool
16903b705cfSriastradhunattached(DrawablePtr drawable)
17003b705cfSriastradh{
17103b705cfSriastradh	struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable);
17203b705cfSriastradh	return priv == NULL || (priv->gpu_damage == NULL && priv->cpu_damage && !priv->cpu_bo);
17303b705cfSriastradh}
17403b705cfSriastradh
17503b705cfSriastradhstatic inline bool
17642542f5fSchristospicture_is_gpu(struct sna *sna, PicturePtr picture, unsigned flags)
17703b705cfSriastradh{
17842542f5fSchristos	if (!picture)
17903b705cfSriastradh		return false;
18042542f5fSchristos
18142542f5fSchristos	if (!picture->pDrawable) {
18242542f5fSchristos		switch (flags) {
18342542f5fSchristos		case PREFER_GPU_RENDER:
18442542f5fSchristos			switch (picture->pSourcePict->type) {
18542542f5fSchristos			case SourcePictTypeSolidFill:
18642542f5fSchristos			case SourcePictTypeLinear:
18742542f5fSchristos				return false;
18842542f5fSchristos			default:
18942542f5fSchristos				return true;
19042542f5fSchristos			}
19142542f5fSchristos		case PREFER_GPU_SPANS:
19242542f5fSchristos			return true;
19342542f5fSchristos		default:
19442542f5fSchristos			return false;
19542542f5fSchristos		}
19642542f5fSchristos	} else {
19742542f5fSchristos		if (picture->repeat &&
19842542f5fSchristos		    (picture->pDrawable->width | picture->pDrawable->height) == 1)
19942542f5fSchristos			return flags == PREFER_GPU_SPANS;
20042542f5fSchristos	}
20142542f5fSchristos
20242542f5fSchristos	return is_gpu(sna, picture->pDrawable, flags);
20303b705cfSriastradh}
20403b705cfSriastradh
20503b705cfSriastradhstatic inline bool
20603b705cfSriastradhpicture_is_cpu(struct sna *sna, PicturePtr picture)
20703b705cfSriastradh{
20803b705cfSriastradh	if (!picture->pDrawable)
20903b705cfSriastradh		return false;
21003b705cfSriastradh
21103b705cfSriastradh	return !is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER);
21203b705cfSriastradh}
21303b705cfSriastradh
21442542f5fSchristosstatic inline bool sna_blt_compare_depth(const DrawableRec *src, const DrawableRec *dst)
21503b705cfSriastradh{
21603b705cfSriastradh	if (src->depth == dst->depth)
21703b705cfSriastradh		return true;
21803b705cfSriastradh
21903b705cfSriastradh	/* Also allow for the alpha to be discarded on a copy */
22003b705cfSriastradh	if (src->bitsPerPixel != dst->bitsPerPixel)
22103b705cfSriastradh		return false;
22203b705cfSriastradh
22303b705cfSriastradh	if (dst->depth == 24 && src->depth == 32)
22403b705cfSriastradh		return true;
22503b705cfSriastradh
22603b705cfSriastradh	/* Note that a depth-16 pixmap is r5g6b5, not x1r5g5b5. */
22703b705cfSriastradh
22803b705cfSriastradh	return false;
22903b705cfSriastradh}
23003b705cfSriastradh
23103b705cfSriastradhstatic inline struct kgem_bo *
23203b705cfSriastradhsna_render_get_alpha_gradient(struct sna *sna)
23303b705cfSriastradh{
23403b705cfSriastradh	return kgem_bo_reference(sna->render.alpha_cache.cache_bo);
23503b705cfSriastradh}
23603b705cfSriastradh
23703b705cfSriastradhstatic inline void
23803b705cfSriastradhsna_render_picture_extents(PicturePtr p, BoxRec *box)
23903b705cfSriastradh{
24003b705cfSriastradh	box->x1 = p->pDrawable->x;
24103b705cfSriastradh	box->y1 = p->pDrawable->y;
24203b705cfSriastradh	box->x2 = bound(box->x1, p->pDrawable->width);
24303b705cfSriastradh	box->y2 = bound(box->y1, p->pDrawable->height);
24403b705cfSriastradh
24503b705cfSriastradh	if (box->x1 < p->pCompositeClip->extents.x1)
24603b705cfSriastradh		box->x1 = p->pCompositeClip->extents.x1;
24703b705cfSriastradh	if (box->y1 < p->pCompositeClip->extents.y1)
24803b705cfSriastradh		box->y1 = p->pCompositeClip->extents.y1;
24903b705cfSriastradh
25003b705cfSriastradh	if (box->x2 > p->pCompositeClip->extents.x2)
25103b705cfSriastradh		box->x2 = p->pCompositeClip->extents.x2;
25203b705cfSriastradh	if (box->y2 > p->pCompositeClip->extents.y2)
25303b705cfSriastradh		box->y2 = p->pCompositeClip->extents.y2;
25403b705cfSriastradh
25503b705cfSriastradh	assert(box->x2 > box->x1 && box->y2 > box->y1);
25603b705cfSriastradh}
25703b705cfSriastradh
25803b705cfSriastradhstatic inline void
25903b705cfSriastradhsna_render_reduce_damage(struct sna_composite_op *op,
26003b705cfSriastradh			 int dst_x, int dst_y,
26103b705cfSriastradh			 int width, int height)
26203b705cfSriastradh{
26303b705cfSriastradh	BoxRec r;
26403b705cfSriastradh
26503b705cfSriastradh	if (op->damage == NULL || *op->damage == NULL)
26603b705cfSriastradh		return;
26703b705cfSriastradh
26803b705cfSriastradh	if (DAMAGE_IS_ALL(*op->damage)) {
26903b705cfSriastradh		DBG(("%s: damage-all, dicarding damage\n",
27003b705cfSriastradh		     __FUNCTION__));
27103b705cfSriastradh		op->damage = NULL;
27203b705cfSriastradh		return;
27303b705cfSriastradh	}
27403b705cfSriastradh
27503b705cfSriastradh	if (width == 0 || height == 0)
27603b705cfSriastradh		return;
27703b705cfSriastradh
27803b705cfSriastradh	r.x1 = dst_x + op->dst.x;
27903b705cfSriastradh	r.x2 = r.x1 + width;
28003b705cfSriastradh
28103b705cfSriastradh	r.y1 = dst_y + op->dst.y;
28203b705cfSriastradh	r.y2 = r.y1 + height;
28303b705cfSriastradh
28403b705cfSriastradh	if (sna_damage_contains_box__no_reduce(*op->damage, &r)) {
28503b705cfSriastradh		DBG(("%s: damage contains render extents, dicarding damage\n",
28603b705cfSriastradh		     __FUNCTION__));
28703b705cfSriastradh		op->damage = NULL;
28803b705cfSriastradh	}
28903b705cfSriastradh}
29003b705cfSriastradh
29103b705cfSriastradhinline static uint32_t
29203b705cfSriastradhcolor_convert(uint32_t pixel,
29303b705cfSriastradh	      uint32_t src_format,
29403b705cfSriastradh	      uint32_t dst_format)
29503b705cfSriastradh{
29603b705cfSriastradh	DBG(("%s: src=%08x [%08x]\n", __FUNCTION__, pixel, src_format));
29703b705cfSriastradh
29803b705cfSriastradh	if (src_format != dst_format) {
29903b705cfSriastradh		uint16_t red, green, blue, alpha;
30003b705cfSriastradh
30103b705cfSriastradh		if (!sna_get_rgba_from_pixel(pixel,
30203b705cfSriastradh					     &red, &green, &blue, &alpha,
30303b705cfSriastradh					     src_format))
30403b705cfSriastradh			return 0;
30503b705cfSriastradh
30603b705cfSriastradh		if (!sna_get_pixel_from_rgba(&pixel,
30703b705cfSriastradh					     red, green, blue, alpha,
30803b705cfSriastradh					     dst_format))
30903b705cfSriastradh			return 0;
31003b705cfSriastradh	}
31103b705cfSriastradh
31203b705cfSriastradh	DBG(("%s: dst=%08x [%08x]\n", __FUNCTION__, pixel, dst_format));
31303b705cfSriastradh	return pixel;
31403b705cfSriastradh}
31503b705cfSriastradh
316fe8aea9eSmrginline static uint32_t
317fe8aea9eSmrgsolid_color(uint32_t format, uint32_t pixel)
318fe8aea9eSmrg{
319fe8aea9eSmrg	return color_convert(pixel, format, PICT_a8r8g8b8);
320fe8aea9eSmrg}
321fe8aea9eSmrg
32203b705cfSriastradhinline static bool dst_use_gpu(PixmapPtr pixmap)
32303b705cfSriastradh{
32403b705cfSriastradh	struct sna_pixmap *priv = sna_pixmap(pixmap);
32503b705cfSriastradh	if (priv == NULL)
32603b705cfSriastradh		return false;
32703b705cfSriastradh
32803b705cfSriastradh	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
32903b705cfSriastradh		return true;
33003b705cfSriastradh
33103b705cfSriastradh	if (priv->clear)
33203b705cfSriastradh		return false;
33303b705cfSriastradh
33403b705cfSriastradh	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
33503b705cfSriastradh		return true;
33603b705cfSriastradh
33703b705cfSriastradh	return priv->gpu_damage && (!priv->cpu || !priv->cpu_damage);
33803b705cfSriastradh}
33903b705cfSriastradh
34003b705cfSriastradhinline static bool dst_use_cpu(PixmapPtr pixmap)
34103b705cfSriastradh{
34203b705cfSriastradh	struct sna_pixmap *priv = sna_pixmap(pixmap);
34303b705cfSriastradh	if (priv == NULL || priv->shm)
34403b705cfSriastradh		return true;
34503b705cfSriastradh
34603b705cfSriastradh	return priv->cpu_damage && priv->cpu;
34703b705cfSriastradh}
34803b705cfSriastradh
34903b705cfSriastradhinline static bool dst_is_cpu(PixmapPtr pixmap)
35003b705cfSriastradh{
35103b705cfSriastradh	struct sna_pixmap *priv = sna_pixmap(pixmap);
35203b705cfSriastradh	return priv == NULL || DAMAGE_IS_ALL(priv->cpu_damage);
35303b705cfSriastradh}
35403b705cfSriastradh
35503b705cfSriastradhinline static bool
35603b705cfSriastradhuntransformed(PicturePtr p)
35703b705cfSriastradh{
35803b705cfSriastradh	return !p->transform || pixman_transform_is_int_translate(p->transform);
35903b705cfSriastradh}
36003b705cfSriastradh
36142542f5fSchristosinline static void
36242542f5fSchristosboxes_extents(const BoxRec *box, int n, BoxRec *extents)
36342542f5fSchristos{
36442542f5fSchristos	*extents = box[0];
36542542f5fSchristos	while (--n) {
36642542f5fSchristos		box++;
36742542f5fSchristos
36842542f5fSchristos		if (box->x1 < extents->x1)
36942542f5fSchristos			extents->x1 = box->x1;
37042542f5fSchristos		if (box->x2 > extents->x2)
37142542f5fSchristos			extents->x2 = box->x2;
37242542f5fSchristos
37342542f5fSchristos		if (box->y1 < extents->y1)
37442542f5fSchristos			extents->y1 = box->y1;
37542542f5fSchristos		if (box->y2 > extents->y2)
37642542f5fSchristos			extents->y2 = box->y2;
37742542f5fSchristos	}
37842542f5fSchristos}
37942542f5fSchristos
38042542f5fSchristosinline static bool
38142542f5fSchristosoverlaps(struct sna *sna,
38242542f5fSchristos	 struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
38342542f5fSchristos	 struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
38442542f5fSchristos	 const BoxRec *box, int n, unsigned flags,
38542542f5fSchristos	 BoxRec *extents)
38642542f5fSchristos{
38742542f5fSchristos	if (src_bo != dst_bo)
38842542f5fSchristos		return false;
38942542f5fSchristos
39042542f5fSchristos	if (flags & COPY_NO_OVERLAP)
39142542f5fSchristos		return false;
39242542f5fSchristos
39342542f5fSchristos	boxes_extents(box, n, extents);
39442542f5fSchristos	return (extents->x2 + src_dx > extents->x1 + dst_dx &&
39542542f5fSchristos		extents->x1 + src_dx < extents->x2 + dst_dx &&
39642542f5fSchristos		extents->y2 + src_dy > extents->y1 + dst_dy &&
39742542f5fSchristos		extents->y1 + src_dy < extents->y2 + dst_dy);
39842542f5fSchristos}
39942542f5fSchristos
40042542f5fSchristosstatic inline long get_picture_id(PicturePtr picture)
40142542f5fSchristos{
40242542f5fSchristos	return picture && picture->pDrawable ? get_drawable_pixmap(picture->pDrawable)->drawable.serialNumber : 0;
40342542f5fSchristos}
40403b705cfSriastradh
40503b705cfSriastradh#endif /* SNA_RENDER_INLINE_H */
406