diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c index 1c420a7e..f707d39e 100644 --- a/src/sna/gen7_render.c +++ b/src/sna/gen7_render.c @@ -207,6 +207,12 @@ static const uint32_t ps_kernel_planar[][4] = { #include "exa_wm_write.g7b" }; +static const uint32_t ps_kernel_rgb[][4] = { +#include "exa_wm_src_affine.g7b" +#include "exa_wm_src_sample_argb.g7b" +#include "exa_wm_write.g7b" +}; + #define KERNEL(kernel_enum, kernel, num_surfaces) \ [GEN7_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces} #define NOKERNEL(kernel_enum, func, num_surfaces) \ @@ -216,7 +222,7 @@ static const struct wm_kernel_info { const void *data; unsigned int size; int num_surfaces; -} wm_kernels[] = { +} wm_kernels[GEN7_WM_KERNEL_COUNT] = { NOKERNEL(NOMASK, brw_wm_kernel__affine, 2), NOKERNEL(NOMASK_P, brw_wm_kernel__projective, 2), @@ -234,6 +240,7 @@ static const struct wm_kernel_info { KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7), KERNEL(VIDEO_PACKED, ps_kernel_packed, 2), + KERNEL(VIDEO_RGB, ps_kernel_rgb, 2), }; #undef KERNEL @@ -1790,7 +1797,9 @@ static void gen7_emit_video_state(struct sna *sna, frame->pitch[0]; n_src = 6; } else { - if (frame->id == FOURCC_UYVY) + if (frame->id == FOURCC_RGB888) + src_surf_format = GEN7_SURFACEFORMAT_B8G8R8X8_UNORM; + else if (frame->id == FOURCC_UYVY) src_surf_format = GEN7_SURFACEFORMAT_YCRCB_SWAPY; else src_surf_format = GEN7_SURFACEFORMAT_YCRCB_NORMAL; @@ -1824,6 +1833,23 @@ static void gen7_emit_video_state(struct sna *sna, gen7_emit_state(sna, op, offset | dirty); } +static unsigned select_video_kernel(const struct sna_video_frame *frame) +{ + switch (frame->id) { + case FOURCC_YV12: + case FOURCC_I420: + case FOURCC_XVMC: + return GEN7_WM_KERNEL_VIDEO_PLANAR; + + case FOURCC_RGB888: + case FOURCC_RGB565: + return GEN7_WM_KERNEL_VIDEO_RGB; + + default: + return GEN7_WM_KERNEL_VIDEO_PACKED; + } +} + static bool gen7_render_video(struct sna *sna, struct sna_video *video, @@ -1876,9 +1902,7 @@ gen7_render_video(struct sna *sna, GEN7_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE), NO_BLEND, - is_planar_fourcc(frame->id) ? - GEN7_WM_KERNEL_VIDEO_PLANAR : - GEN7_WM_KERNEL_VIDEO_PACKED, + select_video_kernel(frame), 2); tmp.priv = frame; diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c index 0631e0a3..0947576c 100644 --- a/src/sna/gen8_render.c +++ b/src/sna/gen8_render.c @@ -106,6 +106,12 @@ static const uint32_t ps_kernel_planar[][4] = { #include "exa_wm_yuv_rgb.g8b" #include "exa_wm_write.g8b" }; + +static const uint32_t ps_kernel_rgb[][4] = { +#include "exa_wm_src_affine.g8b" +#include "exa_wm_src_sample_argb.g8b" +#include "exa_wm_write.g8b" +}; #endif #define SURFACE_DW (64 / sizeof(uint32_t)); @@ -119,7 +125,7 @@ static const struct wm_kernel_info { const void *data; unsigned int size; int num_surfaces; -} wm_kernels[] = { +} wm_kernels[GEN8_WM_KERNEL_COUNT] = { NOKERNEL(NOMASK, gen8_wm_kernel__affine, 2), NOKERNEL(NOMASK_P, gen8_wm_kernel__projective, 2), @@ -138,6 +144,7 @@ static const struct wm_kernel_info { #if !NO_VIDEO KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7), KERNEL(VIDEO_PACKED, ps_kernel_packed, 2), + KERNEL(VIDEO_RGB, ps_kernel_rgb, 2), #endif }; #undef KERNEL @@ -3733,7 +3740,9 @@ static void gen8_emit_video_state(struct sna *sna, frame->pitch[0]; n_src = 6; } else { - if (frame->id == FOURCC_UYVY) + if (frame->id == FOURCC_RGB888) + src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM; + else if (frame->id == FOURCC_UYVY) src_surf_format = SURFACEFORMAT_YCRCB_SWAPY; else src_surf_format = SURFACEFORMAT_YCRCB_NORMAL; @@ -3765,6 +3774,23 @@ static void gen8_emit_video_state(struct sna *sna, gen8_emit_state(sna, op, offset); } +static unsigned select_video_kernel(const struct sna_video_frame *frame) +{ + switch (frame->id) { + case FOURCC_YV12: + case FOURCC_I420: + case FOURCC_XVMC: + return GEN8_WM_KERNEL_VIDEO_PLANAR; + + case FOURCC_RGB888: + case FOURCC_RGB565: + return GEN8_WM_KERNEL_VIDEO_RGB; + + default: + return GEN8_WM_KERNEL_VIDEO_PACKED; + } +} + static bool gen8_render_video(struct sna *sna, struct sna_video *video, @@ -3811,6 +3837,11 @@ gen8_render_video(struct sna *sna, tmp.floats_per_vertex = 3; tmp.floats_per_rect = 9; + DBG(("%s: scaling?=%d, planar?=%d [%x]\n", + __FUNCTION__, + src_width != dst_width || src_height != dst_height, + is_planar_fourcc(frame->id), frame->id)); + if (src_width == dst_width && src_height == dst_height) filter = SAMPLER_FILTER_NEAREST; else @@ -3820,9 +3851,7 @@ gen8_render_video(struct sna *sna, GEN8_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE), NO_BLEND, - is_planar_fourcc(frame->id) ? - GEN8_WM_KERNEL_VIDEO_PLANAR : - GEN8_WM_KERNEL_VIDEO_PACKED, + select_video_kernel(frame), 2); tmp.priv = frame; diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 6ceb5154..6cb10e61 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -166,7 +166,7 @@ struct local_mode_get_plane_res { }; #define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res) -#if 0 +#if 1 #define __DBG DBG #else #define __DBG(x) diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index 1baf9455..fa1ca8ea 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -484,6 +484,7 @@ enum { GEN7_WM_KERNEL_VIDEO_PLANAR, GEN7_WM_KERNEL_VIDEO_PACKED, + GEN7_WM_KERNEL_VIDEO_RGB, GEN7_WM_KERNEL_COUNT }; @@ -536,6 +537,7 @@ enum { GEN8_WM_KERNEL_VIDEO_PLANAR, GEN8_WM_KERNEL_VIDEO_PACKED, + GEN8_WM_KERNEL_VIDEO_RGB, GEN8_WM_KERNEL_COUNT }; diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c index ae08ef73..1498707d 100644 --- a/src/sna/sna_video_sprite.c +++ b/src/sna/sna_video_sprite.c @@ -151,7 +151,7 @@ static int sna_video_sprite_best_size(ddQueryBestSize_ARGS) struct sna_video *video = port->devPriv.ptr; struct sna *sna = video->sna; - if (sna->kgem.gen >= 075) { + if (sna->kgem.gen >= 075 && !sna->render.video) { *p_w = vid_w; *p_h = vid_h; } else { @@ -407,6 +407,7 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS) BoxRec dst; RegionRec reg; Rotation rotation; + bool cache_bo; pipe = sna_crtc_pipe(crtc); @@ -491,6 +492,8 @@ off: frame.image.y1 = 0; frame.image.x2 = frame.width; frame.image.y2 = frame.height; + + cache_bo = false; } else { frame.bo = sna_video_buffer(video, &frame); if (frame.bo == NULL) { @@ -504,6 +507,60 @@ off: ret = BadAlloc; goto err; } + + cache_bo = true; + } + + if (sna->kgem.gen >= 075 && sna->render.video && + !((frame.src.x2 - frame.src.x1) == (dst.x2 - dst.x1) && + (frame.src.y2 - frame.src.y1) == (dst.y2 - dst.y1))) { + ScreenPtr screen = to_screen_from_sna(sna); + PixmapPtr scaled; + RegionRec r; + + r.extents.x1 = r.extents.y1 = 0; + r.extents.x2 = dst.x2 - dst.x1; + r.extents.y2 = dst.y2 - dst.y1; + r.data = NULL; + + DBG(("%s: scaling from (%d, %d) to (%d, %d)\n", + __FUNCTION__, + frame.src.x2 - frame.src.x1, + frame.src.y2 - frame.src.y1, + r.extents.x2, r.extents.y2)); + + scaled = screen->CreatePixmap(screen, + r.extents.x2, + r.extents.y2, + 24, + CREATE_PIXMAP_USAGE_SCRATCH); + if (scaled == NULL) { + ret = BadAlloc; + goto err; + } + + if (!sna->render.video(sna, video, &frame, &r, scaled)) { + screen->DestroyPixmap(scaled); + ret = BadAlloc; + goto err; + } + + if (cache_bo) + sna_video_buffer_fini(video); + else + kgem_bo_destroy(&sna->kgem, frame.bo); + + frame.bo = kgem_bo_reference(__sna_pixmap_get_bo(scaled)); + kgem_bo_submit(&sna->kgem, frame.bo); + + frame.id = FOURCC_RGB888; + frame.src = frame.image = r.extents; + frame.width = frame.image.x2; + frame.height = frame.image.y2; + frame.pitch[0] = frame.bo->pitch; + + screen->DestroyPixmap(scaled); + cache_bo = false; } ret = Success; @@ -513,10 +570,10 @@ off: } frame.bo->domain = DOMAIN_NONE; - if (xvmc_passthrough(format->id)) - kgem_bo_destroy(&sna->kgem, frame.bo); - else + if (cache_bo) sna_video_buffer_fini(video); + else + kgem_bo_destroy(&sna->kgem, frame.bo); if (ret != Success) goto err;