xf86-video-intel: 6 commits - src/compat-api.h src/intel_device.c src/intel_driver.h src/intel_module.c src/sna/gen2_render.c src/sna/sna_accel.c src/sna/sna_acpi.c src/sna/sna_display.c src/sna/sna_driver.c src/sna/sna.h src/sna/sna_video_textured.c src/uxa/intel_display.c src/uxa/intel_driver.c src/uxa/intel.h

Chris Wilson ickle at kemper.freedesktop.org
Wed Jul 20 10:32:23 UTC 2016


 src/compat-api.h             |   10 +
 src/intel_device.c           |   21 ++
 src/intel_driver.h           |    1 
 src/intel_module.c           |   19 ++
 src/sna/gen2_render.c        |  330 ++++++++++++++++++++++++++++++++++++++++---
 src/sna/sna.h                |    2 
 src/sna/sna_accel.c          |   16 +-
 src/sna/sna_acpi.c           |   11 +
 src/sna/sna_display.c        |    8 -
 src/sna/sna_driver.c         |   32 ++++
 src/sna/sna_video_textured.c |   16 +-
 src/uxa/intel.h              |    2 
 src/uxa/intel_display.c      |   17 +-
 src/uxa/intel_driver.c       |   27 ++-
 14 files changed, 473 insertions(+), 39 deletions(-)

New commits:
commit 4eaab17aec8ea66428087065901324f56df9020e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 20 11:26:05 2016 +0100

    Adapt to libXfont2 ABI changes
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e06cd24..c5c4b6a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -117,6 +117,11 @@
 #define RECTILINEAR	0x4
 #define OVERWRITES	0x8
 
+#if XFONT2_CLIENT_FUNCS_VERSION >= 1
+#define AllocateFontPrivateIndex() xfont2_allocate_font_private_index()
+#define FontSetPrivate(font, idx, data) xfont2_font_set_private(font, idx, data)
+#endif
+
 #if 0
 static void __sna_fallback_flush(DrawablePtr d)
 {
commit 24ab9145c7748cb344b69d70b4f8eccb0c90db76
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 20 11:16:47 2016 +0100

    Update to ABI 22 and NotifyFd
    
    ABI 22 brings in a new BlockHandler/WakeupHandler interface
    (SetNotifyFd) and throws out the current interface (albeit without
    delivering any improvements).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/compat-api.h b/src/compat-api.h
index 64e3736..05797a0 100644
--- a/src/compat-api.h
+++ b/src/compat-api.h
@@ -30,6 +30,7 @@
 
 #include <xorg-server.h>
 #include <xorgVersion.h>
+#include <xf86Module.h>
 
 #include <picturestr.h>
 #ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR
@@ -48,6 +49,10 @@
 #define xf86ScrnToScreen(s) ((s)->pScreen)
 #endif
 
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 22
+#define HAVE_NOTIFY_FD 1
+#endif
+
 #ifndef XF86_SCRN_INTERFACE
 
 #define SCRN_ARG_TYPE int
@@ -250,4 +255,9 @@ static inline void FreePixmap(PixmapPtr pixmap)
 #define PixmapSyncDirtyHelper(d, dd) PixmapSyncDirtyHelper(d)
 #endif
 
+#if !HAVE_NOTIFY_FD
+#define SetNotifyFd(fd, cb, mode, data) AddGeneralSocket(fd);
+#define RemoveNotifyFd(fd) RemoveGeneralSocket(fd)
+#endif
+
 #endif
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 64bf498..76d66cb 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -388,8 +388,10 @@ struct sna {
 	EntityInfoPtr pEnt;
 	const struct intel_device_info *info;
 
+#if !HAVE_NOTIFY_FD
 	ScreenBlockHandlerProcPtr BlockHandler;
 	ScreenWakeupHandlerProcPtr WakeupHandler;
+#endif
 	CloseScreenProcPtr CloseScreen;
 
 	PicturePtr clear;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 48dcb58..e06cd24 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -18024,6 +18024,13 @@ static bool sna_option_accel_blt(struct sna *sna)
 	return strcasecmp(s, "blt") == 0;
 }
 
+#if HAVE_NOTIFY_FD
+static void sna_accel_notify(int fd, int ready, void *data)
+{
+	sna_mode_wakeup(data);
+}
+#endif
+
 bool sna_accel_init(ScreenPtr screen, struct sna *sna)
 {
 	const char *backend;
@@ -18035,7 +18042,7 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
 	list_init(&sna->flush_pixmaps);
 	list_init(&sna->active_pixmaps);
 
-	AddGeneralSocket(sna->kgem.fd);
+	SetNotifyFd(sna->kgem.fd, sna_accel_notify, X_NOTIFY_READ, sna);
 
 #ifdef DEBUG_MEMORY
 	sna->timer_expire[DEBUG_MEMORY_TIMER] = GetTimeInMillis()+ 10 * 1000;
@@ -18214,7 +18221,7 @@ void sna_accel_close(struct sna *sna)
 	sna_pixmap_expire(sna);
 
 	DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna);
-	RemoveGeneralSocket(sna->kgem.fd);
+	RemoveNotifyFd(sna->kgem.fd);
 
 	kgem_cleanup_cache(&sna->kgem);
 }
diff --git a/src/sna/sna_acpi.c b/src/sna/sna_acpi.c
index dcc0287..643d04a 100644
--- a/src/sna/sna_acpi.c
+++ b/src/sna/sna_acpi.c
@@ -92,7 +92,7 @@ void _sna_acpi_wakeup(struct sna *sna)
 		DBG(("%s: error [%d], detaching from acpid\n", __FUNCTION__, n));
 
 		/* XXX reattach later? */
-		RemoveGeneralSocket(sna->acpi.fd);
+		RemoveNotifyFd(sna->acpi.fd);
 		sna_acpi_fini(sna);
 		return;
 	}
@@ -136,6 +136,13 @@ void _sna_acpi_wakeup(struct sna *sna)
 	} while (n);
 }
 
+#if HAVE_NOTIFY_FD
+static void sna_acpi_notify(int fd, int read, void *data)
+{
+	_sna_acpi_wakeup(data);
+}
+#endif
+
 static int read_power_state(const char *path)
 {
 	DIR *dir;
@@ -200,7 +207,7 @@ void sna_acpi_init(struct sna *sna)
 
 	DBG(("%s: attaching to acpid\n", __FUNCTION__));
 
-	AddGeneralSocket(sna->acpi.fd);
+	SetNotifyFd(sna->acpi.fd, sna_acpi_notify, X_NOTIFY_READ, sna);
 	sna->acpi.remain = sizeof(sna->acpi.event) - 1;
 	sna->acpi.offset = 0;
 
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 10d33f2..ef29a91 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -5832,8 +5832,8 @@ static void __restore_swcursor(ScrnInfoPtr scrn)
 	enable_fb_access(scrn, FALSE);
 	enable_fb_access(scrn, TRUE);
 
-	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)__restore_swcursor,
-				     (WakeupHandlerProcPtr)NoopDDA,
+	RemoveBlockAndWakeupHandlers((void *)__restore_swcursor,
+				     (void *)NoopDDA,
 				     scrn);
 }
 
@@ -5843,8 +5843,8 @@ static void restore_swcursor(struct sna *sna)
 	FreeCursor(sna->cursor.ref, None);
 	sna->cursor.ref = NULL;
 
-	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)__restore_swcursor,
-				       (WakeupHandlerProcPtr)NoopDDA,
+	RegisterBlockAndWakeupHandlers((void *)__restore_swcursor,
+				       (void *)NoopDDA,
 				       sna->scrn);
 }
 
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 455113f..60a5a97 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -681,6 +681,7 @@ cleanup:
 	return FALSE;
 }
 
+#if !HAVE_NOTIFY_FD
 static bool has_shadow(struct sna *sna)
 {
 	if (!sna->mode.shadow_enabled)
@@ -737,6 +738,31 @@ sna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
 		FD_CLR(sna->kgem.fd, (fd_set*)read_mask);
 	}
 }
+#else
+static void
+sna_block_handler(void *data, void *_timeout)
+{
+	struct sna *sna = data;
+	int *timeout = _timeout;
+	struct timeval tv, *tvp;
+
+	DBG(("%s (timeout=%d)\n", __FUNCTION__, *timeout));
+	if (*timeout == 0)
+		return;
+
+	if (*timeout < 0) {
+		tvp = NULL;
+	} else {
+		tv.tv_sec = *timeout / 1000;
+		tv.tv_usec = (*timeout % 1000) * 1000;
+		tvp = &tv;
+	}
+
+	sna_accel_block(sna, &tvp);
+	if (tvp)
+		*timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
+}
+#endif
 
 #if HAVE_UDEV
 #include <sys/stat.h>
@@ -1141,11 +1167,17 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
 	 * later memory should be bound when allocating, e.g rotate_mem */
 	scrn->vtSema = TRUE;
 
+#if !HAVE_NOTIFY_FD
 	sna->BlockHandler = screen->BlockHandler;
 	screen->BlockHandler = sna_block_handler;
 
 	sna->WakeupHandler = screen->WakeupHandler;
 	screen->WakeupHandler = sna_wakeup_handler;
+#else
+	RegisterBlockAndWakeupHandlers(sna_block_handler,
+				       (ServerWakeupHandlerProcPtr)NoopDDA,
+				       sna);
+#endif
 
 	screen->SaveScreen = sna_save_screen;
 	screen->CreateScreenResources = sna_create_screen_resources;
diff --git a/src/uxa/intel.h b/src/uxa/intel.h
index 054b626..a5e77af 100644
--- a/src/uxa/intel.h
+++ b/src/uxa/intel.h
@@ -196,7 +196,9 @@ typedef struct intel_screen_private {
 
 	int colorKey;
 	XF86VideoAdaptorPtr adaptor;
+#if !HAVE_NOTIFY_FD
 	ScreenBlockHandlerProcPtr BlockHandler;
+#endif
 	Bool overlayOn;
 
 	struct {
diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index fa371c6..809cda1 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -2089,6 +2089,7 @@ intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
 /*
  * Check for pending DRM events and process them.
  */
+#if !HAVE_NOTIFY_FD
 static void
 drm_wakeup_handler(pointer data, int err, pointer p)
 {
@@ -2103,6 +2104,14 @@ drm_wakeup_handler(pointer data, int err, pointer p)
 	if (FD_ISSET(mode->fd, read_mask))
 		drmHandleEvent(mode->fd, &mode->event_context);
 }
+#else
+static void
+drm_notify_fd(int fd, int ready, void *data)
+{
+	struct intel_mode *mode = data;
+	drmHandleEvent(mode->fd, &mode->event_context);
+}
+#endif
 
 /*
  * If there are any available, read drm_events
@@ -2263,9 +2272,11 @@ intel_mode_init(struct intel_screen_private *intel)
 	 * registration within ScreenInit and not PreInit.
 	 */
 	mode->flip_count = 0;
-	AddGeneralSocket(mode->fd);
+	SetNotifyFd(mode->fd, drm_notify_fd, X_NOTIFY_READ, mode);
+#if !HAVE_NOTIFY_FD
 	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
 				       drm_wakeup_handler, mode);
+#endif
 }
 
 void
@@ -2289,9 +2300,11 @@ intel_mode_close(intel_screen_private *intel)
 
         intel_drm_abort_scrn(intel->scrn);
 
+#if !HAVE_NOTIFY_FD
 	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
 				     drm_wakeup_handler, mode);
-	RemoveGeneralSocket(mode->fd);
+#endif
+	RemoveNotifyFd(mode->fd);
 }
 
 void
diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c
index 62abdd2..3703c41 100644
--- a/src/uxa/intel_driver.c
+++ b/src/uxa/intel_driver.c
@@ -652,8 +652,9 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
 }
 
 static void
-intel_dirty_update(ScreenPtr screen)
+intel_dirty_update(intel_screen_private *intel)
 {
+	ScreenPtr screen = xf86ScrnToScreen(intel->scrn);
 	RegionPtr region;
 	PixmapDirtyUpdatePtr ent;
 
@@ -670,6 +671,7 @@ intel_dirty_update(ScreenPtr screen)
 }
 #endif
 
+#if !HAVE_NOTIFY_FD
 static void
 I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
 {
@@ -687,9 +689,22 @@ I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
 	intel_uxa_block_handler(intel);
 	intel_video_block_handler(intel);
 #ifdef INTEL_PIXMAP_SHARING
-	intel_dirty_update(screen);
+	intel_dirty_update(intel);
 #endif
 }
+#else
+static void
+I830BlockHandler(void *data, void *timeout)
+{
+	intel_screen_private *intel = data;
+
+	intel_uxa_block_handler(intel);
+	intel_video_block_handler(intel);
+#ifdef INTEL_PIXMAP_SHARING
+	intel_dirty_update(intel);
+#endif
+}
+#endif
 
 static Bool
 intel_init_initial_framebuffer(ScrnInfoPtr scrn)
@@ -947,8 +962,14 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL)
 			   "Hardware cursor initialization failed\n");
 	}
 
+#if !HAVE_NOTIFY_FD
 	intel->BlockHandler = screen->BlockHandler;
 	screen->BlockHandler = I830BlockHandler;
+#else
+	RegisterBlockAndWakeupHandlers(I830BlockHandler,
+				       (ServerWakeupHandlerProcPtr)NoopDDA,
+				       intel);
+#endif
 
 #ifdef INTEL_PIXMAP_SHARING
 	screen->StartPixmapTracking = PixmapStartDirtyTracking;
commit df0b2ce823e8bc9e994875ce349cf1da4cf8e402
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jul 12 11:02:15 2016 +0200

    intel: Fix fd (and mem) leak when intel_scrn_create fails
    
    The probe functions in intel_module.c call intel_open_device() before
    calling intel_scrn_create(), but if the later fails because of e.g.
    an allocation failure they were not cleaning up the resources
    claimed by intel_open_device(), esp. leaking the fd is a problem
    because this breaks the fallback to the modesetting driver.
    
    This commit fixes this by adding a intel_close_device() cleanup
    function and calling that when intel_scrn_create() fails.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/src/intel_device.c b/src/intel_device.c
index 54c1443..04ad7b6 100644
--- a/src/intel_device.c
+++ b/src/intel_device.c
@@ -643,6 +643,27 @@ err_path:
 	return -1;
 }
 
+void intel_close_device(int entity_num)
+{
+	struct intel_device *dev;
+
+	if (intel_device_key == -1)
+		return;
+
+	dev = xf86GetEntityPrivate(entity_num, intel_device_key)->ptr;
+	xf86GetEntityPrivate(entity_num, intel_device_key)->ptr = NULL;
+	if (!dev)
+		return;
+
+	if (dev->master_count == 0) /* Don't close server-fds */
+		close(dev->fd);
+
+	if (dev->render_node != dev->master_node)
+		free(dev->render_node);
+	free(dev->master_node);
+	free(dev);
+}
+
 int __intel_peek_fd(ScrnInfoPtr scrn)
 {
 	struct intel_device *dev;
diff --git a/src/intel_driver.h b/src/intel_driver.h
index fc9beaf..bece88a 100644
--- a/src/intel_driver.h
+++ b/src/intel_driver.h
@@ -124,6 +124,7 @@ int intel_entity_get_devid(int index);
 int intel_open_device(int entity_num,
 		      const struct pci_device *pci,
 		      struct xf86_platform_device *dev);
+void intel_close_device(int entity_num);
 int __intel_peek_fd(ScrnInfoPtr scrn);
 struct intel_device *intel_get_device(ScrnInfoPtr scrn, int *fd);
 int intel_has_render_node(struct intel_device *dev);
diff --git a/src/intel_module.c b/src/intel_module.c
index 60835b9..e443c9e 100644
--- a/src/intel_module.c
+++ b/src/intel_module.c
@@ -631,6 +631,8 @@ static Bool intel_pci_probe(DriverPtr		driver,
 			    struct pci_device	*pci,
 			    intptr_t		match_data)
 {
+	Bool ret;
+
 	if (intel_open_device(entity_num, pci, NULL) == -1) {
 #if UMS
 		switch (pci->device_id) {
@@ -648,7 +650,11 @@ static Bool intel_pci_probe(DriverPtr		driver,
 #endif
 	}
 
-	return intel_scrn_create(driver, entity_num, match_data, 0);
+	ret = intel_scrn_create(driver, entity_num, match_data, 0);
+	if (!ret)
+		intel_close_device(entity_num);
+
+	return ret;
 }
 
 #ifdef XSERVER_PLATFORM_BUS
@@ -671,9 +677,16 @@ intel_platform_probe(DriverPtr driver,
 
 	/* if we get any flags we don't understand fail to probe for now */
 	if (flags)
-		return FALSE;
+		goto err;
 
-	return intel_scrn_create(driver, entity_num, match_data, scrn_flags);
+	if (!intel_scrn_create(driver, entity_num, match_data, scrn_flags))
+		goto err;
+
+	return TRUE;
+
+err:
+	intel_close_device(entity_num);
+	return FALSE;
 }
 #endif
 
commit 6d8a19910a89bfa91c3029c1ec5a8c2bdefb6c25
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Jul 14 12:14:11 2016 -0400

    uxa: Don't bother with xf86GARTCloseScreen
    
    We only ever use xserver's AGP support from the i810 driver.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c
index 73d7f4f..62abdd2 100644
--- a/src/uxa/intel_driver.c
+++ b/src/uxa/intel_driver.c
@@ -1172,8 +1172,6 @@ static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
 
 	intel_sync_close(screen);
 
-	xf86GARTCloseScreen(scrn->scrnIndex);
-
 	scrn->vtSema = FALSE;
 	return TRUE;
 }
commit 1c449ffa585682b85b5581a46d7e7ca369f2ce38
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Wed Jul 22 11:59:06 2015 +0300

    sna/gen2/video: Implement textured video support
    
    Add textured video support for gen2. The hardware can only deal with
    packed YUV formats, so only those will be exposed.
    
    Modelled after the gen3 textured video code.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 33b986e..c6eceda 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -35,6 +35,7 @@
 #include "sna_reg.h"
 #include "sna_render.h"
 #include "sna_render_inline.h"
+#include "sna_video.h"
 
 #include "gen2_render.h"
 
@@ -3124,6 +3125,273 @@ gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
 }
 
 static void
+gen2_emit_video_state(struct sna *sna,
+		      struct sna_video *video,
+		      struct sna_video_frame *frame,
+		      PixmapPtr pixmap,
+		      struct kgem_bo *dst_bo,
+		      int width, int height,
+		      bool bilinear)
+{
+	uint32_t ms1, v, unwind;
+
+	gen2_emit_target(sna, dst_bo, width, height,
+			 sna_format_for_depth(pixmap->drawable.depth));
+
+	unwind = sna->kgem.nbatch;
+	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+	      I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
+	BATCH(1 << 12);
+	BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
+	BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
+	if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
+		   sna->kgem.batch + unwind + 1,
+		   3 * sizeof(uint32_t)) == 0)
+		sna->kgem.nbatch = unwind;
+	else
+		sna->render_state.gen2.ls1 = unwind;
+
+	gen2_disable_logic_op(sna);
+
+	unwind = sna->kgem.nbatch;
+	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+	      LOAD_TEXTURE_BLEND_STAGE(0) | 1);
+	BATCH(TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT |
+	      TB0C_OP_ARG1 | TB0C_ARG1_SEL_TEXEL0);
+	BATCH(TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT |
+	      TB0A_OP_ARG1 | TB0A_ARG1_SEL_ONE);
+	if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
+		   sna->kgem.batch + unwind + 1,
+		   2 * sizeof(uint32_t)) == 0)
+		sna->kgem.nbatch = unwind;
+	else
+		sna->render_state.gen2.ls2 = unwind;
+
+	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(0) | 4);
+	BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
+			     frame->bo,
+			     I915_GEM_DOMAIN_SAMPLER << 16,
+			     0));
+	ms1 = MAPSURF_422 | TM0S1_COLORSPACE_CONVERSION;
+	switch (frame->id) {
+	case FOURCC_YUY2:
+		ms1 |= MT_422_YCRCB_NORMAL;
+		break;
+	case FOURCC_UYVY:
+		ms1 |= MT_422_YCRCB_SWAPY;
+		break;
+	}
+	BATCH(((frame->height - 1) << TM0S1_HEIGHT_SHIFT) |
+	      ((frame->width - 1)  << TM0S1_WIDTH_SHIFT) |
+	      ms1 |
+	      gen2_sampler_tiling_bits(frame->bo->tiling));
+	BATCH((frame->pitch[0] / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
+	if (bilinear)
+		BATCH(FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT |
+		      FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT |
+		      MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
+	else
+		BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
+		      FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
+		      MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
+	BATCH(0);	/* default color */
+
+	BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(0) |
+	      ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | TEXCOORDTYPE_CARTESIAN |
+	      ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
+	      ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
+
+	v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D;
+	if (sna->render_state.gen2.vft != v) {
+		BATCH(v);
+		sna->render_state.gen2.vft = v;
+	}
+}
+
+static void
+gen2_video_get_batch(struct sna *sna, struct kgem_bo *bo)
+{
+	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
+
+	if (!kgem_check_batch(&sna->kgem, 120) ||
+	    !kgem_check_reloc(&sna->kgem, 4) ||
+	    !kgem_check_exec(&sna->kgem, 2)) {
+		_kgem_submit(&sna->kgem);
+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
+	}
+
+	if (sna->render_state.gen2.need_invariant)
+		gen2_emit_invariant(sna);
+}
+
+static int
+gen2_get_inline_rectangles(struct sna *sna, int want, int floats_per_vertex)
+{
+	int size = floats_per_vertex * 3;
+	int rem = batch_space(sna) - 1;
+
+	if (size * want > rem)
+		want = rem / size;
+
+	return want;
+}
+
+static bool
+gen2_render_video(struct sna *sna,
+		  struct sna_video *video,
+		  struct sna_video_frame *frame,
+		  RegionPtr dstRegion,
+		  PixmapPtr pixmap)
+{
+	struct sna_pixmap *priv = sna_pixmap(pixmap);
+	const BoxRec *pbox = region_rects(dstRegion);
+	int nbox = region_num_rects(dstRegion);
+	int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
+	int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
+	int src_width = frame->src.x2 - frame->src.x1;
+	int src_height = frame->src.y2 - frame->src.y1;
+	float src_offset_x, src_offset_y;
+	float src_scale_x, src_scale_y;
+	int pix_xoff, pix_yoff;
+	struct kgem_bo *dst_bo;
+	bool bilinear;
+	int copy = 0;
+
+	DBG(("%s: src:%dx%d (frame:%dx%d) -> dst:%dx%d\n", __FUNCTION__,
+	     src_width, src_height, frame->width, frame->height, dst_width, dst_height));
+
+	assert(priv->gpu_bo);
+	dst_bo = priv->gpu_bo;
+
+	bilinear = src_width != dst_width || src_height != dst_height;
+
+	src_scale_x = (float)src_width / dst_width / frame->width;
+	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
+
+	src_scale_y = (float)src_height / dst_height / frame->height;
+	src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
+	DBG(("%s: src offset (%f, %f), scale (%f, %f)\n",
+	     __FUNCTION__, src_offset_x, src_offset_y, src_scale_x, src_scale_y));
+
+	if (too_large(pixmap->drawable.width, pixmap->drawable.height) ||
+	    dst_bo->pitch > MAX_3D_PITCH) {
+		int bpp = pixmap->drawable.bitsPerPixel;
+
+		if (too_large(dst_width, dst_height))
+			return false;
+
+		dst_bo = kgem_create_2d(&sna->kgem,
+					dst_width, dst_height, bpp,
+					kgem_choose_tiling(&sna->kgem,
+							   I915_TILING_X,
+							   dst_width, dst_height, bpp),
+					0);
+		if (!dst_bo)
+			return false;
+
+		pix_xoff = -dstRegion->extents.x1;
+		pix_yoff = -dstRegion->extents.y1;
+		copy = 1;
+	} else {
+		/* Set up the offset for translating from the given region
+		 * (in screen coordinates) to the backing pixmap.
+		 */
+#ifdef COMPOSITE
+		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
+		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
+#else
+		pix_xoff = 0;
+		pix_yoff = 0;
+#endif
+
+		dst_width  = pixmap->drawable.width;
+		dst_height = pixmap->drawable.height;
+	}
+
+	gen2_video_get_batch(sna, dst_bo);
+	gen2_emit_video_state(sna, video, frame, pixmap,
+			      dst_bo, dst_width, dst_height, bilinear);
+	do {
+		int nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
+		if (nbox_this_time == 0) {
+			gen2_video_get_batch(sna, dst_bo);
+			gen2_emit_video_state(sna, video, frame, pixmap,
+					      dst_bo, dst_width, dst_height, bilinear);
+			nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
+			assert(nbox_this_time);
+		}
+		nbox -= nbox_this_time;
+
+		BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST |
+		      ((12 * nbox_this_time) - 1));
+		do {
+			int box_x1 = pbox->x1;
+			int box_y1 = pbox->y1;
+			int box_x2 = pbox->x2;
+			int box_y2 = pbox->y2;
+
+			pbox++;
+
+			DBG(("%s: dst (%d, %d), (%d, %d) + (%d, %d); src (%f, %f), (%f, %f)\n",
+			     __FUNCTION__, box_x1, box_y1, box_x2, box_y2, pix_xoff, pix_yoff,
+			     box_x1 * src_scale_x + src_offset_x,
+			     box_y1 * src_scale_y + src_offset_y,
+			     box_x2 * src_scale_x + src_offset_x,
+			     box_y2 * src_scale_y + src_offset_y));
+
+			/* bottom right */
+			BATCH_F(box_x2 + pix_xoff);
+			BATCH_F(box_y2 + pix_yoff);
+			BATCH_F(box_x2 * src_scale_x + src_offset_x);
+			BATCH_F(box_y2 * src_scale_y + src_offset_y);
+
+			/* bottom left */
+			BATCH_F(box_x1 + pix_xoff);
+			BATCH_F(box_y2 + pix_yoff);
+			BATCH_F(box_x1 * src_scale_x + src_offset_x);
+			BATCH_F(box_y2 * src_scale_y + src_offset_y);
+
+			/* top left */
+			BATCH_F(box_x1 + pix_xoff);
+			BATCH_F(box_y1 + pix_yoff);
+			BATCH_F(box_x1 * src_scale_x + src_offset_x);
+			BATCH_F(box_y1 * src_scale_y + src_offset_y);
+		} while (--nbox_this_time);
+	} while (nbox);
+
+	if (copy) {
+#ifdef COMPOSITE
+		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
+		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
+#else
+		pix_xoff = 0;
+		pix_yoff = 0;
+#endif
+		sna_blt_copy_boxes(sna, GXcopy,
+				   dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1,
+				   priv->gpu_bo, pix_xoff, pix_yoff,
+				   pixmap->drawable.bitsPerPixel,
+				   region_rects(dstRegion),
+				   region_num_rects(dstRegion));
+
+		kgem_bo_destroy(&sna->kgem, dst_bo);
+	}
+
+	if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
+		if ((pix_xoff | pix_yoff) == 0) {
+			sna_damage_add(&priv->gpu_damage, dstRegion);
+		} else {
+			sna_damage_add_boxes(&priv->gpu_damage,
+					     region_rects(dstRegion),
+					     region_num_rects(dstRegion),
+					     pix_xoff, pix_yoff);
+		}
+	}
+
+	return true;
+}
+
+static void
 gen2_render_copy_setup_source(struct sna_composite_channel *channel,
 			      const DrawableRec *draw,
 			      struct kgem_bo *bo)
@@ -3537,7 +3805,7 @@ const char *gen2_render_init(struct sna *sna, const char *backend)
 	render->copy = gen2_render_copy;
 	render->copy_boxes = gen2_render_copy_boxes;
 
-	/* XXX YUV color space conversion for video? */
+	render->video = gen2_render_video;
 
 	render->reset = gen2_render_reset;
 	render->flush = gen2_render_flush;
diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c
index f5b7e98..3cce5cf 100644
--- a/src/sna/sna_video_textured.c
+++ b/src/sna/sna_video_textured.c
@@ -48,7 +48,12 @@ static const XvAttributeRec Attributes[] = {
 	//{XvSettable | XvGettable, 0, 255, (char *)"XV_CONTRAST"},
 };
 
-static const XvImageRec Images[] = {
+static const XvImageRec gen2_Images[] = {
+	XVIMAGE_YUY2,
+	XVIMAGE_UYVY,
+};
+
+static const XvImageRec gen3_Images[] = {
 	XVIMAGE_YUY2,
 	XVIMAGE_YV12,
 	XVIMAGE_I420,
@@ -366,8 +371,13 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
 						 ARRAY_SIZE(Formats));
 	adaptor->nAttributes = ARRAY_SIZE(Attributes);
 	adaptor->pAttributes = (XvAttributeRec *)Attributes;
-	adaptor->nImages = ARRAY_SIZE(Images);
-	adaptor->pImages = (XvImageRec *)Images;
+	if (sna->kgem.gen < 030) {
+		adaptor->nImages = ARRAY_SIZE(gen2_Images);
+		adaptor->pImages = (XvImageRec *)gen2_Images;
+	} else {
+		adaptor->nImages = ARRAY_SIZE(gen3_Images);
+		adaptor->pImages = (XvImageRec *)gen3_Images;
+	}
 #if XORG_XV_VERSION < 2
 	adaptor->ddAllocatePort = sna_xv_alloc_port;
 	adaptor->ddFreePort = sna_xv_free_port;
commit 01e5845421bac4ed5862781c98e0f58445adf90e
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Wed Jul 22 12:04:55 2015 +0300

    sna/gen2: Don't pass sna_composite_op to gen2_emit_target()
    
    Instead of passing sna_composite_op to gen2_emit_target(), pass all the
    parameters (bo,width,height,format) directly. This makes it possible to
    use gen2_emit_target() when we don't have an sna_composite_op.
    
    This matches how gen3_emit_target() works.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 37ded24..33b986e 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -596,39 +596,43 @@ gen2_get_batch(struct sna *sna, const struct sna_composite_op *op)
 		gen2_emit_invariant(sna);
 }
 
-static void gen2_emit_target(struct sna *sna, const struct sna_composite_op *op)
-{
-	assert(!too_large(op->dst.width, op->dst.height));
-	assert(op->dst.bo->pitch >= 8 && op->dst.bo->pitch <= MAX_3D_PITCH);
+static void gen2_emit_target(struct sna *sna,
+			     struct kgem_bo *bo,
+			     int width,
+			     int height,
+			     int format)
+{
+	assert(!too_large(width, height));
+	assert(bo->pitch >= 8 && bo->pitch <= MAX_3D_PITCH);
 	assert(sna->render.vertex_offset == 0);
 
-	assert(op->dst.bo->unique_id);
-	if (sna->render_state.gen2.target == op->dst.bo->unique_id) {
-		kgem_bo_mark_dirty(op->dst.bo);
+	assert(bo->unique_id);
+	if (sna->render_state.gen2.target == bo->unique_id) {
+		kgem_bo_mark_dirty(bo);
 		return;
 	}
 
 	BATCH(_3DSTATE_BUF_INFO_CMD);
 	BATCH(BUF_3D_ID_COLOR_BACK |
-	      gen2_buf_tiling(op->dst.bo->tiling) |
-	      BUF_3D_PITCH(op->dst.bo->pitch));
+	      gen2_buf_tiling(bo->tiling) |
+	      BUF_3D_PITCH(bo->pitch));
 	BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
-			     op->dst.bo,
+			     bo,
 			     I915_GEM_DOMAIN_RENDER << 16 |
 			     I915_GEM_DOMAIN_RENDER,
 			     0));
 
 	BATCH(_3DSTATE_DST_BUF_VARS_CMD);
-	BATCH(gen2_get_dst_format(op->dst.format));
+	BATCH(gen2_get_dst_format(format));
 
 	BATCH(_3DSTATE_DRAW_RECT_CMD);
 	BATCH(0);
 	BATCH(0);	/* ymin, xmin */
-	BATCH(DRAW_YMAX(op->dst.height - 1) |
-	      DRAW_XMAX(op->dst.width - 1));
+	BATCH(DRAW_YMAX(height - 1) |
+	      DRAW_XMAX(width - 1));
 	BATCH(0);	/* yorig, xorig */
 
-	sna->render_state.gen2.target = op->dst.bo->unique_id;
+	sna->render_state.gen2.target = bo->unique_id;
 }
 
 static void gen2_disable_logic_op(struct sna *sna)
@@ -701,7 +705,11 @@ static void gen2_emit_composite_state(struct sna *sna,
 		kgem_clear_dirty(&sna->kgem);
 	}
 
-	gen2_emit_target(sna, op);
+	gen2_emit_target(sna,
+			 op->dst.bo,
+			 op->dst.width,
+			 op->dst.height,
+			 op->dst.format);
 
 	unwind = sna->kgem.nbatch;
 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
@@ -2425,7 +2433,11 @@ static void gen2_emit_composite_spans_state(struct sna *sna,
 	uint32_t unwind;
 
 	gen2_get_batch(sna, &op->base);
-	gen2_emit_target(sna, &op->base);
+	gen2_emit_target(sna,
+			 op->base.dst.bo,
+			 op->base.dst.width,
+			 op->base.dst.height,
+			 op->base.dst.format);
 
 	unwind = sna->kgem.nbatch;
 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
@@ -2708,7 +2720,11 @@ static void gen2_emit_fill_composite_state(struct sna *sna,
 	uint32_t ls1;
 
 	gen2_get_batch(sna, op);
-	gen2_emit_target(sna, op);
+	gen2_emit_target(sna,
+			 op->dst.bo,
+			 op->dst.width,
+			 op->dst.height,
+			 op->dst.format);
 
 	ls1 = sna->kgem.nbatch;
 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
@@ -2870,7 +2886,11 @@ static void gen2_emit_fill_state(struct sna *sna,
 	uint32_t ls1;
 
 	gen2_get_batch(sna, op);
-	gen2_emit_target(sna, op);
+	gen2_emit_target(sna,
+			 op->dst.bo,
+			 op->dst.width,
+			 op->dst.height,
+			 op->dst.format);
 
 	ls1 = sna->kgem.nbatch;
 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
@@ -3178,7 +3198,11 @@ static void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op
 			      PIPELINE_FLUSH_TEXTURE_CACHE);
 		kgem_clear_dirty(&sna->kgem);
 	}
-	gen2_emit_target(sna, op);
+	gen2_emit_target(sna,
+			 op->dst.bo,
+			 op->dst.width,
+			 op->dst.height,
+			 op->dst.format);
 
 	ls1 = sna->kgem.nbatch;
 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |


More information about the xorg-commit mailing list