diff options
Diffstat (limited to 'src/sna')
-rw-r--r-- | src/sna/gen9_render.c | 23 | ||||
-rw-r--r-- | src/sna/sna_render.h | 3 | ||||
-rw-r--r-- | src/sna/sna_video.c | 72 | ||||
-rw-r--r-- | src/sna/sna_video.h | 19 | ||||
-rw-r--r-- | src/sna/sna_video_sprite.c | 20 | ||||
-rw-r--r-- | src/sna/sna_video_textured.c | 21 |
6 files changed, 153 insertions, 5 deletions
diff --git a/src/sna/gen9_render.c b/src/sna/gen9_render.c index eb22b642..3ed2eb3b 100644 --- a/src/sna/gen9_render.c +++ b/src/sna/gen9_render.c @@ -129,6 +129,20 @@ static const uint32_t ps_kernel_planar_bt709[][4] = { #include "exa_wm_write.g8b" }; +static const uint32_t ps_kernel_ayuv_bt601[][4] = { +#include "exa_wm_src_affine.g8b" +#include "exa_wm_src_sample_argb_ayuv.g8b" +#include "exa_wm_yuv_rgb_bt601.g8b" +#include "exa_wm_write.g8b" +}; + +static const uint32_t ps_kernel_ayuv_bt709[][4] = { +#include "exa_wm_src_affine.g8b" +#include "exa_wm_src_sample_argb_ayuv.g8b" +#include "exa_wm_yuv_rgb_bt709.g8b" +#include "exa_wm_write.g8b" +}; + static const uint32_t ps_kernel_nv12_bt709[][4] = { #include "exa_wm_src_affine.g8b" #include "exa_wm_src_sample_nv12.g8b" @@ -177,6 +191,8 @@ static const struct wm_kernel_info { KERNEL(VIDEO_PLANAR_BT709, ps_kernel_planar_bt709, 7), KERNEL(VIDEO_NV12_BT709, ps_kernel_nv12_bt709, 7), KERNEL(VIDEO_PACKED_BT709, ps_kernel_packed_bt709, 2), + KERNEL(VIDEO_AYUV_BT601, ps_kernel_ayuv_bt601, 2), + KERNEL(VIDEO_AYUV_BT709, ps_kernel_ayuv_bt709, 2), KERNEL(VIDEO_RGB, ps_kernel_rgb, 2), #endif }; @@ -3853,6 +3869,8 @@ static void gen9_emit_video_state(struct sna *sna, src_surf_format[0] = SURFACEFORMAT_B8G8R8X8_UNORM; else if (frame->id == FOURCC_UYVY) src_surf_format[0] = SURFACEFORMAT_YCRCB_SWAPY; + else if (is_ayuv_fourcc(frame->id)) + src_surf_format[0] = SURFACEFORMAT_B8G8R8X8_UNORM; else src_surf_format[0] = SURFACEFORMAT_YCRCB_NORMAL; @@ -3903,6 +3921,11 @@ static unsigned select_video_kernel(const struct sna_video *video, case FOURCC_RGB565: return GEN9_WM_KERNEL_VIDEO_RGB; + case FOURCC_AYUV: + return video->colorspace ? + GEN9_WM_KERNEL_VIDEO_AYUV_BT709 : + GEN9_WM_KERNEL_VIDEO_AYUV_BT601; + default: return video->colorspace ? GEN9_WM_KERNEL_VIDEO_PACKED_BT709 : diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index a4e5b56a..891fc905 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -617,6 +617,9 @@ enum { GEN9_WM_KERNEL_VIDEO_NV12_BT709, GEN9_WM_KERNEL_VIDEO_PACKED_BT709, + GEN9_WM_KERNEL_VIDEO_AYUV_BT601, + GEN9_WM_KERNEL_VIDEO_AYUV_BT709, + GEN9_WM_KERNEL_VIDEO_RGB, GEN9_WM_KERNEL_COUNT }; diff --git a/src/sna/sna_video.c b/src/sna/sna_video.c index 55405f81..cf284975 100644 --- a/src/sna/sna_video.c +++ b/src/sna/sna_video.c @@ -59,6 +59,7 @@ #include "intel_options.h" #include <xf86xv.h> +#include <byteswap.h> #ifdef SNA_XVMC #define _SNA_XVMC_SERVER_ @@ -281,6 +282,7 @@ sna_video_frame_set_rotation(struct sna_video *video, } else { switch (frame->id) { case FOURCC_RGB888: + case FOURCC_AYUV: if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { frame->pitch[0] = ALIGN((height << 2), align); frame->size = (int)frame->pitch[0] * width; @@ -584,6 +586,72 @@ sna_copy_packed_data(struct sna_video *video, } } +static void +sna_copy_ayuv_data(struct sna_video *video, + const struct sna_video_frame *frame, + const uint8_t *buf, + uint8_t *dst) +{ + int pitch = frame->width << 2; + const uint32_t *src_dw; + const uint8_t *src; + uint32_t *dst_dw = (uint32_t *)dst; + int x, y, w, h; + int i, j; + + if (video->textured) { + /* XXX support copying cropped extents */ + x = y = 0; + w = frame->width; + h = frame->height; + } else { + x = frame->image.x1; + y = frame->image.y1; + w = frame->image.x2 - frame->image.x1; + h = frame->image.y2 - frame->image.y1; + } + + src = buf + (y * pitch) + (x << 2); + src_dw = (uint32_t *)src; + + switch (frame->rotation) { + case RR_Rotate_0: + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* + * Have to reverse bytes order, because the only + * player which supports AYUV format currently is + * Gstreamer and it supports in bad way, even though + * spec says MSB:AYUV, we get the bytes opposite way. + */ + dst_dw[i * w + j] = bswap_32(src_dw[i * w + j]); + } + } + break; + case RR_Rotate_90: + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + dst_dw[(w - j - 1) * h + i] = bswap_32(src_dw[i * w + j]); + } + } + break; + case RR_Rotate_180: + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + dst_dw[(h - i - 1) * w + w - j - 1] = bswap_32(src_dw[i * w + j]); + } + } + break; + case RR_Rotate_270: + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + dst_dw[(w - j - 1) * h + i] = bswap_32(src_dw[i * w + j]); + } + } + break; + } +} + bool sna_video_copy_data(struct sna_video *video, struct sna_video_frame *frame, @@ -604,7 +672,7 @@ sna_video_copy_data(struct sna_video *video, assert(frame->size); /* In the common case, we can simply the upload in a single pwrite */ - if (frame->rotation == RR_Rotate_0 && !video->tiled) { + if (frame->rotation == RR_Rotate_0 && !video->tiled && !is_ayuv_fourcc(frame->id)) { DBG(("%s: unrotated, untiled fast paths: is-planar?=%d\n", __FUNCTION__, is_planar_fourcc(frame->id))); if (is_nv12_fourcc(frame->id)) { @@ -709,6 +777,8 @@ use_gtt: /* copy data, must use GTT so that we keep the overlay uncached */ sna_copy_nv12_data(video, frame, buf, dst); else if (is_planar_fourcc(frame->id)) sna_copy_planar_data(video, frame, buf, dst); + else if (is_ayuv_fourcc(frame->id)) + sna_copy_ayuv_data(video, frame, buf, dst); else sna_copy_packed_data(video, frame, buf, dst); diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h index bbd3f0fd..06d43796 100644 --- a/src/sna/sna_video.h +++ b/src/sna/sna_video.h @@ -39,6 +39,7 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FOURCC_RGB565 ((16 << 24) + ('B' << 16) + ('G' << 8) + 'R') #define FOURCC_RGB888 ((24 << 24) + ('B' << 16) + ('G' << 8) + 'R') #define FOURCC_NV12 (('2' << 24) + ('1' << 16) + ('V' << 8) + 'N') +#define FOURCC_AYUV (('V' << 24) + ('U' << 16) + ('Y' << 8) + 'A') /* * Below, a dummy picture type that is used in XvPutImage @@ -79,6 +80,14 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. XvTopToBottom \ } +#define XVIMAGE_AYUV { \ + FOURCC_AYUV, XvYUV, LSBFirst, \ + {'A', 'Y', 'U', 'V', 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}, \ + 32, XvPacked, 1, 0, 0, 0, 0, 8, 8, 8, 1, 1, 1, 1, 1, 1, \ + {'A', 'Y', 'U', 'V', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \ + XvTopToBottom \ +} + struct sna_video { struct sna *sna; @@ -189,6 +198,16 @@ static inline int is_nv12_fourcc(int id) } } +static inline int is_ayuv_fourcc(int id) +{ + switch (id) { + case FOURCC_AYUV: + return 1; + default: + return 0; + } +} + bool sna_video_clip_helper(struct sna_video *video, struct sna_video_frame *frame, diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c index d3d722d4..da676ad6 100644 --- a/src/sna/sna_video_sprite.c +++ b/src/sna/sna_video_sprite.c @@ -47,11 +47,11 @@ #define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ #define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ #define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ +#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] x:Y:U:V 8:8:8:8 little endian */ #define has_hw_scaling(sna, video) ((sna)->kgem.gen < 071 || \ (sna)->kgem.gen >= 0110) - #define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane) struct local_mode_set_plane { uint32_t plane_id; @@ -79,6 +79,8 @@ static const XvImageRec images_rgb565[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_RGB888, XVMC_RGB565 }; static const XvImageRec images_nv12[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_NV12, XVMC_RGB888, XVMC_RGB565 }; +static const XvImageRec images_ayuv[] = { XVIMAGE_AYUV, XVIMAGE_YUY2, XVIMAGE_UYVY, + XVIMAGE_NV12, XVMC_RGB888, XVMC_RGB565 }; static const XvAttributeRec attribs[] = { { XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE" }, /* BT.601, BT.709 */ { XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_COLORKEY" }, @@ -410,6 +412,10 @@ sna_video_sprite_show(struct sna *sna, case FOURCC_UYVY: f.pixel_format = DRM_FORMAT_UYVY; break; + case FOURCC_AYUV: + /* i915 doesn't support alpha, so we use XYUV */ + f.pixel_format = DRM_FORMAT_XYUV8888; + break; case FOURCC_YUY2: default: f.pixel_format = DRM_FORMAT_YUYV; @@ -751,7 +757,12 @@ static int sna_video_sprite_query(ddQueryImageAttributes_ARGS) tmp *= (*h >> 1); size += tmp; break; - + case FOURCC_AYUV: + tmp = *w << 2; + if (pitches) + pitches[0] = tmp; + size = *h * tmp; + break; default: *w = (*w + 1) & ~1; *h = (*h + 1) & ~1; @@ -851,7 +862,10 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen) adaptor->nAttributes = ARRAY_SIZE(attribs); adaptor->pAttributes = (XvAttributeRec *)attribs; - if (sna_has_sprite_format(sna, DRM_FORMAT_NV12)) { + if (sna_has_sprite_format(sna, DRM_FORMAT_XYUV8888)) { + adaptor->pImages = (XvImageRec *)images_ayuv; + adaptor->nImages = ARRAY_SIZE(images_ayuv); + } else if (sna_has_sprite_format(sna, DRM_FORMAT_NV12)) { adaptor->pImages = (XvImageRec *)images_nv12; adaptor->nImages = ARRAY_SIZE(images_nv12); } else if (sna_has_sprite_format(sna, DRM_FORMAT_RGB565)) { diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c index 115cbea4..06da36d0 100644 --- a/src/sna/sna_video_textured.c +++ b/src/sna/sna_video_textured.c @@ -71,6 +71,16 @@ static const XvImageRec gen4_Images[] = { XVMC_YUV, }; +static const XvImageRec gen9_Images[] = { + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_NV12, + XVIMAGE_UYVY, + XVIMAGE_AYUV, + XVMC_YUV, +}; + static int sna_video_textured_stop(ddStopVideo_ARGS) { struct sna_video *video = port->devPriv.ptr; @@ -337,6 +347,12 @@ sna_video_textured_query(ddQueryImageAttributes_ARGS) pitches[0] = size; size *= *h; break; + case FOURCC_AYUV: + size = *w << 2; + if (pitches) + pitches[0] = size; + size *= *h; + break; case FOURCC_XVMC: *h = (*h + 1) & ~1; size = sizeof(uint32_t); @@ -414,9 +430,12 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen) } else if (sna->kgem.gen < 040) { adaptor->nImages = ARRAY_SIZE(gen3_Images); adaptor->pImages = (XvImageRec *)gen3_Images; - } else { + } else if (sna->kgem.gen < 0110) { adaptor->nImages = ARRAY_SIZE(gen4_Images); adaptor->pImages = (XvImageRec *)gen4_Images; + } else { + adaptor->nImages = ARRAY_SIZE(gen9_Images); + adaptor->pImages = (XvImageRec *)gen9_Images; } #if XORG_XV_VERSION < 2 adaptor->ddAllocatePort = sna_xv_alloc_port; |