diff mbox

sna: Add multiple planes support for Xv video on sprite

Message ID 1393798732-5028-1-git-send-email-zhenyuw@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zhenyu Wang March 2, 2014, 10:18 p.m. UTC
On VLV there're two sprite planes for each pipe that both can be
used simultaneously for Xv video. This one trys to expose those
capability through multiple Xv ports on sprite video adaptor.

I've tried to use this to validate new two sprite planes for
single pipe on VLV which works fine.

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
---
 src/sna/sna.h              |   5 ++-
 src/sna/sna_display.c      | 106 ++++++++++++++++++++++++++++++++++-----------
 src/sna/sna_video_sprite.c |  87 ++++++++++++++++++++-----------------
 3 files changed, 131 insertions(+), 67 deletions(-)
diff mbox

Patch

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 4651632..ce51fef 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -285,6 +285,7 @@  struct sna {
 		unsigned num_real_crtc;
 		unsigned num_real_output;
 		unsigned num_fake;
+		unsigned num_sprite;
 	} mode;
 
 	struct sna_dri {
@@ -442,9 +443,9 @@  static inline void sna_dri_close(struct sna *sna, ScreenPtr pScreen) { }
 #endif
 void sna_dri_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap);
 
-extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
+extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, XvPortPtr port, uint32_t rotation);
 extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
-extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
+extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, XvPortPtr port);
 extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
 
 CARD32 sna_format_for_depth(int depth);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index de08cb9..2e05733 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -100,13 +100,19 @@  struct rotation {
 	uint32_t current;
 };
 
+struct sna_crtc_sprite {
+	uint32_t id;
+	struct rotation sprite_rotation;
+};
+
 struct sna_crtc {
 	struct drm_mode_modeinfo kmode;
 	int dpms_mode;
 	PixmapPtr scanout_pixmap;
 	struct kgem_bo *bo, *shadow_bo;
 	uint32_t cursor;
-	uint32_t sprite;
+	int num_sprite;
+	struct sna_crtc_sprite *sprite;
 	bool shadow;
 	bool fallback_shadow;
 	bool transform;
@@ -115,7 +121,6 @@  struct sna_crtc {
 
 	uint32_t rotation;
 	struct rotation primary_rotation;
-	struct rotation sprite_rotation;
 };
 
 struct sna_property {
@@ -200,9 +205,24 @@  int sna_crtc_to_pipe(xf86CrtcPtr crtc)
 	return to_sna_crtc(crtc)->pipe;
 }
 
-uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc)
+static int sna_sprite_num(XvPortPtr port)
 {
-	return to_sna_crtc(crtc)->sprite;
+	XvAdaptorPtr adaptor = port->pAdaptor;
+	int i;
+
+	for (i = 0; i < adaptor->nPorts; i++) {
+		if (port == &adaptor->pPorts[i])
+			return i;
+	}
+	return 0;
+}
+
+uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, XvPortPtr port)
+{
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	int num = sna_sprite_num(port);
+
+	return sna_crtc->sprite[num].id;
 }
 
 #ifndef NDEBUG
@@ -674,15 +694,18 @@  rotation_reset(struct rotation *r)
 	r->current = 0;
 }
 
-bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation)
+bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, XvPortPtr port, uint32_t rotation)
 {
+	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+	int num = sna_sprite_num(port);
+
 	DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n",
 	     __FUNCTION__,
-	     to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->sprite,
+	     sna_crtc->id, sna_crtc->pipe, sna_crtc->sprite[num].id,
 	     rotation));
 
 	return rotation_set(to_sna(crtc->scrn),
-			    &to_sna_crtc(crtc)->sprite_rotation,
+			    &sna_crtc->sprite[num].sprite_rotation,
 			    rotation);
 }
 
@@ -1717,6 +1740,7 @@  sna_crtc_destroy(xf86CrtcPtr crtc)
 	sna_crtc_hide_cursor(crtc);
 	gem_close(to_sna(crtc->scrn)->kgem.fd, sna_crtc->cursor);
 
+	free(sna_crtc->sprite);
 	free(sna_crtc);
 	crtc->driver_private = NULL;
 }
@@ -1750,32 +1774,39 @@  static const xf86CrtcFuncsRec sna_crtc_funcs = {
 #endif
 };
 
-static int
-sna_crtc_find_sprite(struct sna *sna, int pipe)
+static void
+sna_crtc_find_sprite(struct sna *sna, struct sna_crtc *sna_crtc, int pipe)
 {
 #ifdef DRM_IOCTL_MODE_GETPLANERESOURCES
 	struct drm_mode_get_plane_res r;
-	uint32_t *planes, id = 0;
+	uint32_t *planes, *id;
 	int i;
 
 	VG_CLEAR(r);
 	r.count_planes = 0;
 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &r))
-		return 0;
+		return;
 
 	if (!r.count_planes)
-		return 0;
+		return;
 
 	planes = malloc(sizeof(uint32_t)*r.count_planes);
-	if (planes == NULL)
-		return 0;
+	id = malloc(sizeof(uint32_t)*r.count_planes);
+	if (planes == NULL || id == NULL)
+		return;
 
 	r.plane_id_ptr = (uintptr_t)planes;
 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &r))
 		r.count_planes = 0;
 
+	if (!r.count_planes)
+		return;
+
+	sna->mode.num_sprite = r.count_planes;
+
 	VG(VALGRIND_MAKE_MEM_DEFINED(planes, sizeof(uint32_t)*r.count_planes));
 
+	sna_crtc->num_sprite = 0;
 	for (i = 0; i < r.count_planes; i++) {
 		struct drm_mode_get_plane p;
 
@@ -1784,35 +1815,54 @@  sna_crtc_find_sprite(struct sna *sna, int pipe)
 		p.count_format_types = 0;
 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANE, &p) == 0) {
 			if (p.possible_crtcs & (1 << pipe)) {
-				id = p.plane_id;
-				break;
+				id[sna_crtc->num_sprite++] = p.plane_id;
+				continue;
 			}
 		}
 	}
+
+	sna_crtc->sprite = malloc(sizeof(struct sna_crtc_sprite)*sna_crtc->num_sprite);
+	if (sna_crtc->sprite == NULL) {
+		free(planes);
+		free(id);
+		return;
+	}
+
+	for (i = 0; i < sna_crtc->num_sprite; i++)
+		sna_crtc->sprite[i].id = id[i];
+
 	free(planes);
+	free(id);
 
-	assert(id);
-	return id;
+	return;
 #else
-	return 0;
+	return;
 #endif
 }
 
 static void
 sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc)
 {
+	int i;
 	sna_crtc->rotation = RR_Rotate_0;
 	sna_crtc->primary_rotation.supported = RR_Rotate_0;
 	sna_crtc->primary_rotation.current = RR_Rotate_0;
-	sna_crtc->sprite_rotation = sna_crtc->primary_rotation;
 
 	rotation_init(sna, &sna_crtc->primary_rotation, sna_crtc->id, LOCAL_MODE_OBJECT_CRTC);
-	rotation_init(sna, &sna_crtc->sprite_rotation, sna_crtc->sprite, LOCAL_MODE_OBJECT_PLANE);
 
-	DBG(("%s: CRTC:%d [pipe=%d], primary: supported-rotations=%x, current-rotation=%x, sprite: supported-rotations=%x, current-rotation=%x\n",
+	DBG(("%s: CRTC:%d [pipe=%d], primary: supported-rotations=%x, current-rotation=%x\n",
 	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
-	     sna_crtc->primary_rotation.supported, sna_crtc->primary_rotation.current,
-	     sna_crtc->sprite_rotation.supported, sna_crtc->sprite_rotation.current));
+	     sna_crtc->primary_rotation.supported, sna_crtc->primary_rotation.current));
+
+	for (i = 0; i < sna_crtc->num_sprite; i++) {
+		sna_crtc->sprite[i].sprite_rotation = sna_crtc->primary_rotation;
+		rotation_init(sna, &sna_crtc->sprite[i].sprite_rotation, sna_crtc->sprite[i].id,
+			      LOCAL_MODE_OBJECT_PLANE);
+		DBG(("%s: CRTC:%d [pipe=%d], sprite[%d]: supported-rotations=%x, current-rotation=%x\n",
+		     __FUNCTION__, sna_crtc->id, sna_crtc->pipe, i,
+		     sna_crtc->sprite[i].sprite_rotation.supported,
+		     sna_crtc->sprite[i].sprite_rotation.current));
+	}
 }
 
 static bool
@@ -1842,16 +1892,18 @@  sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
 		return false;
 	}
 	sna_crtc->pipe = get_pipe.pipe;
-	sna_crtc->sprite = sna_crtc_find_sprite(sna, sna_crtc->pipe);
+	sna_crtc_find_sprite(sna, sna_crtc, sna_crtc->pipe);
 
 	if (xf86IsEntityShared(scrn->entityList[0]) &&
 	    scrn->confScreen->device->screen != sna_crtc->pipe) {
+		free(sna_crtc->sprite);
 		free(sna_crtc);
 		return true;
 	}
 
 	crtc = xf86CrtcCreate(scrn, &sna_crtc_funcs);
 	if (crtc == NULL) {
+		free(sna_crtc->sprite);
 		free(sna_crtc);
 		return false;
 	}
@@ -1860,6 +1912,7 @@  sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
 				      sna->mode.cursor_width*sna->mode.cursor_height*4);
 	if (!sna_crtc->cursor) {
 		xf86CrtcDestroy(crtc);
+		free(sna_crtc->sprite);
 		free(sna_crtc);
 		return false;
 	}
@@ -4093,7 +4146,8 @@  void sna_mode_reset(struct sna *sna)
 
 		/* Force the rotation property to be reset on next use */
 		rotation_reset(&sna_crtc->primary_rotation);
-		rotation_reset(&sna_crtc->sprite_rotation);
+	        for (int j = 0; j < sna_crtc->num_sprite; j++)
+			rotation_reset(&sna_crtc->sprite[i].sprite_rotation);
 	}
 
 	for (i = 0; i < config->num_output; i++) {
diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index f4dcb82..2d6794a 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -195,6 +195,7 @@  update_dst_box_to_crtc_coords(struct sna *sna, xf86CrtcPtr crtc, BoxPtr dstBox)
 
 static bool
 sna_video_sprite_show(struct sna *sna,
+		      XvPortPtr port,
 		      struct sna_video *video,
 		      struct sna_video_frame *frame,
 		      xf86CrtcPtr crtc,
@@ -205,7 +206,7 @@  sna_video_sprite_show(struct sna *sna,
 	/* XXX handle video spanning multiple CRTC */
 
 	VG_CLEAR(s);
-	s.plane_id = sna_crtc_to_sprite(crtc);
+	s.plane_id = sna_crtc_to_sprite(crtc, port);
 
 	update_dst_box_to_crtc_coords(sna, crtc, dstBox);
 	if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
@@ -383,13 +384,13 @@  static int sna_video_sprite_put_image(ClientPtr client,
 				   &clip))
 		goto invisible;
 
-	if (!crtc || sna_crtc_to_sprite(crtc) == 0)
+	if (!crtc || sna_crtc_to_sprite(crtc, port) == 0)
 		goto invisible;
 
 	/* if sprite can't handle rotation natively, store it for the copy func */
 	video->rotation = RR_Rotate_0;
-	if (!sna_crtc_set_sprite_rotation(crtc, crtc->rotation)) {
-		sna_crtc_set_sprite_rotation(crtc, RR_Rotate_0);
+	if (!sna_crtc_set_sprite_rotation(crtc, port, crtc->rotation)) {
+		sna_crtc_set_sprite_rotation(crtc, port, RR_Rotate_0);
 		video->rotation = crtc->rotation;
 	}
 
@@ -429,7 +430,7 @@  static int sna_video_sprite_put_image(ClientPtr client,
 	}
 
 	ret = Success;
-	if (!sna_video_sprite_show(sna, video, &frame, crtc, &dst_box)) {
+	if (!sna_video_sprite_show(sna, port, video, &frame, crtc, &dst_box)) {
 		DBG(("%s: failed to show video frame\n", __FUNCTION__));
 		ret = BadAlloc;
 	} else {
@@ -525,7 +526,7 @@  void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 	XvAdaptorPtr adaptor;
 	struct drm_mode_get_plane_res r;
 	struct sna_video *video;
-	XvPortPtr port;
+	int sprite_per_crtc, i;
 
 	if (sna->flags & SNA_IS_HOSTED)
 		return;
@@ -542,11 +543,13 @@  void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 	if (!adaptor)
 		return;
 
-	video = calloc(1, sizeof(*video));
-	port = calloc(1, sizeof(*port));
-	if (video == NULL || port == NULL) {
+	sprite_per_crtc = sna->mode.num_sprite / sna->mode.kmode->count_crtcs;
+
+	video = calloc(sprite_per_crtc, sizeof(struct sna_video));
+	adaptor->pPorts = calloc(sprite_per_crtc, sizeof(XvPortRec));
+	if (video == NULL || adaptor->pPorts == NULL) {
 		free(video);
-		free(port);
+		free(adaptor->pPorts);
 		sna->xv.num_adaptors--;
 		return;
 	}
@@ -586,35 +589,41 @@  void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 	adaptor->ddPutImage = sna_video_sprite_put_image;
 	adaptor->ddQueryImageAttributes = sna_video_sprite_query;
 
-	adaptor->nPorts = 1;
-	adaptor->pPorts = port;
-
-	adaptor->base_id = port->id = FakeClientID(0);
-	AddResource(port->id, XvGetRTPort(), port);
-	port->pAdaptor = adaptor;
-	port->pNotify =  NULL;
-	port->pDraw =  NULL;
-	port->client =  NULL;
-	port->grab.client =  NULL;
-	port->time = currentTime;
-	port->devPriv.ptr = video;
-
-	video->sna = sna;
-	video->alignment = 64;
-	video->color_key = sna_video_sprite_color_key(sna);
-	video->color_key_changed = true;
-	video->brightness = -19;	/* (255/219) * -16 */
-	video->contrast = 75;	/* 255/219 * 64 */
-	video->saturation = 146;	/* 128/112 * 128 */
-	video->desired_crtc = NULL;
-	video->gamma5 = 0xc0c0c0;
-	video->gamma4 = 0x808080;
-	video->gamma3 = 0x404040;
-	video->gamma2 = 0x202020;
-	video->gamma1 = 0x101010;
-	video->gamma0 = 0x080808;
-	video->rotation = RR_Rotate_0;
-	RegionNull(&video->clip);
+	for (i = 0; i < sprite_per_crtc; i++) {
+		struct sna_video *v = &video[i];
+		XvPortPtr port = &adaptor->pPorts[i];
+
+		port->id = FakeClientID(0);
+		AddResource(port->id, XvGetRTPort(), port);
+
+		port->pAdaptor = adaptor;
+		port->pNotify =  NULL;
+		port->pDraw =  NULL;
+		port->client =  NULL;
+		port->grab.client =  NULL;
+		port->time = currentTime;
+		port->devPriv.ptr = v;
+
+		v->sna = sna;
+		v->alignment = 64;
+		v->color_key = sna_video_sprite_color_key(sna);
+		v->color_key_changed = true;
+		v->brightness = -19;	/* (255/219) * -16 */
+		v->contrast = 75;	/* 255/219 * 64 */
+		v->saturation = 146;	/* 128/112 * 128 */
+		v->desired_crtc = NULL;
+		v->gamma5 = 0xc0c0c0;
+		v->gamma4 = 0x808080;
+		v->gamma3 = 0x404040;
+		v->gamma2 = 0x202020;
+		v->gamma1 = 0x101010;
+		v->gamma0 = 0x080808;
+		v->rotation = RR_Rotate_0;
+		RegionNull(&v->clip);
+	}
+
+	adaptor->base_id = adaptor->pPorts[0].id;
+	adaptor->nPorts = sprite_per_crtc;
 
 	xvColorKey = MAKE_ATOM("XV_COLORKEY");
 	xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP");