diff options
-rw-r--r-- | src/sna/sna_video.c | 56 | ||||
-rw-r--r-- | src/sna/sna_video.h | 33 | ||||
-rw-r--r-- | src/sna/sna_video_overlay.c | 13 | ||||
-rw-r--r-- | src/sna/sna_video_sprite.c | 39 |
4 files changed, 105 insertions, 36 deletions
diff --git a/src/sna/sna_video.c b/src/sna/sna_video.c index 833e6f23..2f4a7e4f 100644 --- a/src/sna/sna_video.c +++ b/src/sna/sna_video.c @@ -226,26 +226,50 @@ sna_video_frame_init(struct sna_video *video, } frame->size *= frame->pitch[0] + frame->pitch[1]; } else { - if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - frame->pitch[0] = ALIGN((height << 1), align); - frame->size = (int)frame->pitch[0] * width; - } else { - frame->pitch[0] = ALIGN((width << 1), align); - frame->size = (int)frame->pitch[0] * height; + switch (frame->id) { + case FOURCC_RGB888: + if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + frame->pitch[0] = ALIGN((height << 2), align); + frame->size = (int)frame->pitch[0] * width; + } else { + frame->pitch[0] = ALIGN((width << 2), align); + frame->size = (int)frame->pitch[0] * height; + } + frame->UBufOffset = frame->VBufOffset = 0; + break; + case FOURCC_RGB565: + if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + frame->pitch[0] = ALIGN((height << 1), align); + frame->size = (int)frame->pitch[0] * width; + } else { + frame->pitch[0] = ALIGN((width << 1), align); + frame->size = (int)frame->pitch[0] * height; + } + frame->UBufOffset = frame->VBufOffset = 0; + break; + + default: + if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + frame->pitch[0] = ALIGN((height << 1), align); + frame->size = (int)frame->pitch[0] * width; + } else { + frame->pitch[0] = ALIGN((width << 1), align); + frame->size = (int)frame->pitch[0] * height; + } + if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + frame->UBufOffset = (int)frame->pitch[1] * width; + frame->VBufOffset = + frame->UBufOffset + (int)frame->pitch[0] * width / 2; + } else { + frame->UBufOffset = (int)frame->pitch[1] * height; + frame->VBufOffset = + frame->UBufOffset + (int)frame->pitch[0] * height / 2; + } + break; } frame->pitch[1] = 0; } - if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - frame->UBufOffset = (int)frame->pitch[1] * width; - frame->VBufOffset = - frame->UBufOffset + (int)frame->pitch[0] * width / 2; - } else { - frame->UBufOffset = (int)frame->pitch[1] * height; - frame->VBufOffset = - frame->UBufOffset + (int)frame->pitch[0] * height / 2; - } - assert(frame->size); } diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h index f0ad28f4..f3978f84 100644 --- a/src/sna/sna_video.h +++ b/src/sna/sna_video.h @@ -35,6 +35,10 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SNA_XVMC 1 #endif +#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X') +#define FOURCC_RGB565 ((16 << 24) + ('B' << 16) + ('G' << 8) + 'R') +#define FOURCC_RGB888 ((24 << 24) + ('B' << 16) + ('G' << 8) + 'R') + /* * Below, a dummy picture type that is used in XvPutImage * only to do an overlay update. @@ -49,6 +53,22 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. XvTopToBottom \ } +#define XVMC_RGB565 { \ + FOURCC_RGB565, XvRGB, LSBFirst, \ + {'P', 'A', 'S', 'S', 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'R', 'G', 'B', '1', '6'}, \ + 16, XvPacked, 1, 16, 0x1f<<11, 0x3f<<5, 0x1f<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'B', 'G', 'R', 'X', 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 \ +} + +#define XVMC_RGB888 { \ + FOURCC_RGB888, XvRGB, LSBFirst, \ + {'P', 'A', 'S', 'S', 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'R', 'G', 'B', '2', '4'}, \ + 32, XvPacked, 1, 24, 0xff<<16, 0xff<<8, 0xff<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'B', 'G', 'R', 'X', 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; @@ -116,11 +136,16 @@ int sna_xv_fixup_formats(ScreenPtr screen, int sna_xv_alloc_port(unsigned long port, XvPortPtr in, XvPortPtr *out); int sna_xv_free_port(XvPortPtr port); -#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X') - static inline int xvmc_passthrough(int id) { - return id == FOURCC_XVMC; + switch (id) { + case FOURCC_XVMC: + case FOURCC_RGB565: + case FOURCC_RGB888: + return true; + default: + return false; + } } static inline int is_planar_fourcc(int id) @@ -130,8 +155,6 @@ static inline int is_planar_fourcc(int id) case FOURCC_I420: case FOURCC_XVMC: return 1; - case FOURCC_UYVY: - case FOURCC_YUY2: default: return 0; } diff --git a/src/sna/sna_video_overlay.c b/src/sna/sna_video_overlay.c index 434d11f4..7a5b5dbf 100644 --- a/src/sna/sna_video_overlay.c +++ b/src/sna/sna_video_overlay.c @@ -600,6 +600,7 @@ sna_video_overlay_query(ClientPtr client, int *offsets) { struct sna_video *video = port->devPriv.ptr; + struct sna_video_frame frame; struct sna *sna = video->sna; int size, tmp; @@ -624,9 +625,17 @@ sna_video_overlay_query(ClientPtr client, switch (format->id) { case FOURCC_XVMC: *h = (*h + 1) & ~1; + sna_video_frame_init(video, format->id, *w, *h, &frame); size = sizeof(uint32_t); - if (pitches) - pitches[0] = size; + if (pitches) { + pitches[0] = frame.pitch[1]; + pitches[1] = frame.pitch[0]; + pitches[2] = frame.pitch[0]; + } + if (offsets) { + offsets[1] = frame.UBufOffset; + offsets[2] = frame.VBufOffset; + } break; /* IA44 is for XvMC only */ diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c index a20e9b9c..221ba793 100644 --- a/src/sna/sna_video_sprite.c +++ b/src/sna/sna_video_sprite.c @@ -51,7 +51,7 @@ static Atom xvColorKey, xvAlwaysOnTop; static XvFormatRec formats[] = { {15}, {16}, {24} }; -static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_YUV }; +static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_RGB888, XVMC_RGB565 }; static const XvAttributeRec attribs[] = { { XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_COLORKEY" }, }; @@ -232,7 +232,17 @@ sna_video_sprite_show(struct sna *sna, uint32_t offsets[4], pitches[4], handles[4]; uint32_t pixel_format; + handles[0] = frame->bo->handle; + pitches[0] = frame->pitch[0]; + offsets[0] = 0; + switch (frame->id) { + case FOURCC_RGB565: + pixel_format = DRM_FORMAT_RGB565; + break; + case FOURCC_RGB888: + pixel_format = DRM_FORMAT_XRGB8888; + break; case FOURCC_UYVY: pixel_format = DRM_FORMAT_UYVY; break; @@ -242,13 +252,9 @@ sna_video_sprite_show(struct sna *sna, break; } - handles[0] = frame->bo->handle; - pitches[0] = frame->pitch[0]; - offsets[0] = 0; - DBG(("%s: creating new fb for handle=%d, width=%d, height=%d, stride=%d\n", __FUNCTION__, frame->bo->handle, - frame->width, frame->height, frame->pitch[0])); + frame->width, frame->height, pitches[0])); if (drmModeAddFB2(sna->kgem.fd, frame->width, frame->height, pixel_format, @@ -420,6 +426,8 @@ static int sna_video_sprite_query(ClientPtr client, int *pitches, int *offsets) { + struct sna_video *video = port->devPriv.ptr; + struct sna_video_frame frame; int size; if (*w > IMAGE_MAX_WIDTH) @@ -427,20 +435,22 @@ static int sna_video_sprite_query(ClientPtr client, if (*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; - *w = (*w + 1) & ~1; if (offsets) offsets[0] = 0; switch (format->id) { - case FOURCC_XVMC: - *h = (*h + 1) & ~1; - size = sizeof(uint32_t); + case FOURCC_RGB888: + case FOURCC_RGB565: + sna_video_frame_init(video, format->id, *w, *h, &frame); if (pitches) - pitches[0] = size; + pitches[0] = frame.pitch[0]; + size = 4; break; - case FOURCC_YUY2: default: + *w = (*w + 1) & ~1; + *h = (*h + 1) & ~1; + size = *w << 1; if (pitches) pitches[0] = size; @@ -518,8 +528,11 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen) ARRAY_SIZE(formats)); adaptor->nAttributes = ARRAY_SIZE(attribs); adaptor->pAttributes = (XvAttributeRec *)attribs; - adaptor->nImages = ARRAY_SIZE(images); adaptor->pImages = (XvImageRec *)images; + adaptor->nImages = 3; + if (sna->kgem.gen == 071) + adaptor->nImages = 4; + adaptor->ddAllocatePort = sna_xv_alloc_port; adaptor->ddFreePort = sna_xv_free_port; adaptor->ddPutVideo = NULL; |