Commit f99da9c5 authored by Siarhei Siamashka's avatar Siarhei Siamashka
Browse files

Added initial XV extension support for sunxi hardware



Proper layer sharing between XV and DRI2 still needs to be implemented.
Additionally we still need NEON and/or G2D "textured overlay" as a
fallback solution for the composited desktop (NEON optimized XV is going
to be useful for a wide range of ARM devices). A bit of performance
tuning is also necessary.
Signed-off-by: default avatarSiarhei Siamashka <siarhei.siamashka@gmail.com>
parent dc478c9d
......@@ -46,7 +46,9 @@ sunxifb_drv_la_SOURCES = \
sunxi_x_g2d.c \
sunxi_x_g2d.h \
sunxi_disp_hwcursor.c \
sunxi_disp_hwcursor.h
sunxi_disp_hwcursor.h \
sunxi_video.c \
sunxi_video.h
if HAVE_LIBUMP
sunxifb_drv_la_SOURCES += \
......
......@@ -52,6 +52,7 @@
#include "sunxi_disp_hwcursor.h"
#include "sunxi_x_g2d.h"
#include "backing_store_tuner.h"
#include "sunxi_video.h"
#ifdef HAVE_LIBUMP
#include "sunxi_mali_ump_dri2.h"
......@@ -1008,7 +1009,13 @@ FBDevScreenInit(SCREEN_INIT_ARGS_DECL)
pScreen->CloseScreen = FBDevCloseScreen;
#if XV
{
if (fPtr->sunxi_disp_private) {
fPtr->SunxiVideo_private = SunxiVideo_Init(pScreen);
if (fPtr->SunxiVideo_private)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"using sunxi disp layers for X video extension\n");
}
else {
XF86VideoAdaptorPtr *ptr;
int n = xf86XVListGenericAdaptors(pScrn,&ptr);
......@@ -1087,6 +1094,14 @@ FBDevCloseScreen(CLOSE_SCREEN_ARGS_DECL)
fPtr->SunxiDispHardwareCursor_private = NULL;
}
#if XV
if (fPtr->SunxiVideo_private) {
SunxiVideo_Close(pScreen);
free(fPtr->SunxiVideo_private);
fPtr->SunxiVideo_private = NULL;
}
#endif
fbdevHWRestore(pScrn);
fbdevHWUnmapVidmem(pScrn);
if (fPtr->shadow) {
......
......@@ -60,6 +60,7 @@ typedef struct {
void *SunxiDispHardwareCursor_private;
void *SunxiMaliDRI2_private;
void *SunxiG2D_private;
void *SunxiVideo_private;
} FBDevRec, *FBDevPtr;
#define FBDEVPTR(p) ((FBDevPtr)((p)->driverPrivate))
......@@ -78,3 +79,6 @@ typedef struct {
#define SUNXI_MALI_UMP_DRI2(p) ((SunxiMaliDRI2 *) \
(FBDEVPTR(p)->SunxiMaliDRI2_private))
#define SUNXI_VIDEO(p) ((SunxiVideo *) \
(FBDEVPTR(p)->SunxiVideo_private))
/*
* Copyright © 2013 Siarhei Siamashka <siarhei.siamashka@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "xf86.h"
#include "xf86xv.h"
#include "fourcc.h"
#include <X11/extensions/Xv.h>
#include "fbdev_priv.h"
#include "sunxi_video.h"
#include "sunxi_disp.h"
/*****************************************************************************/
#define SIMD_ALIGN(s) (((s) + 15) & ~15)
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
static Atom xvColorKey;
/* Convert color key from 32bpp to the native format */
static uint32_t convert_color(ScrnInfoPtr pScrn, uint32_t color)
{
uint32_t red = ((color >> 16) & 0xFF) >> (8 - pScrn->weight.red);
uint32_t green = ((color >> 8) & 0xFF) >> (8 - pScrn->weight.green);
uint32_t blue = (color & 0xFF) >> (8 - pScrn->weight.blue);
return (red << pScrn->offset.red) | (green << pScrn->offset.green) |
(blue << pScrn->offset.blue);
}
/*****************************************************************************/
static void
xStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
{
SunxiVideo *self = SUNXI_VIDEO(pScrn);
sunxi_disp_t *disp = SUNXI_DISP(pScrn);
if (disp && cleanup) {
sunxi_layer_hide(disp);
sunxi_layer_disable_colorkey(disp);
self->colorKeyEnabled = FALSE;
}
REGION_EMPTY(pScrn->pScreen, &self->clip);
}
static int
xSetPortAttributeOverlay(ScrnInfoPtr pScrn,
Atom attribute,
INT32 value,
pointer data)
{
sunxi_disp_t *disp = SUNXI_DISP(pScrn);
SunxiVideo *self = SUNXI_VIDEO(pScrn);
if (attribute == xvColorKey && disp) {
self->colorKey = value;
sunxi_layer_set_colorkey(disp, self->colorKey);
self->colorKeyEnabled = TRUE;
REGION_EMPTY(pScrn->pScreen, &self->clip);
return Success;
}
return BadMatch;
}
static int
xGetPortAttributeOverlay(ScrnInfoPtr pScrn,
Atom attribute,
INT32 *value,
pointer data)
{
SunxiVideo *self = SUNXI_VIDEO(pScrn);
if (attribute == xvColorKey) {
*value = self->colorKey;
return Success;
}
return BadMatch;
}
static void
xQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h,
short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h,
pointer data)
{
*p_w = drw_w;
*p_h = drw_h;
}
static int
xPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y,
short src_w, short src_h, short drw_w, short drw_h, int image,
unsigned char *buf, short width, short height, Bool sync,
RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
{
sunxi_disp_t *disp = SUNXI_DISP(pScrn);
SunxiVideo *self = SUNXI_VIDEO(pScrn);
INT32 x1, x2, y1, y2;
int y_offset, u_offset, v_offset;
int y_stride, uv_stride, yuv_size;
BoxRec dstBox;
/* Clip */
x1 = src_x;
x2 = src_x + src_w;
y1 = src_y;
y2 = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
return Success;
dstBox.x1 -= pScrn->frameX0;
dstBox.x2 -= pScrn->frameX0;
dstBox.y1 -= pScrn->frameY0;
dstBox.y2 -= pScrn->frameY0;
uv_stride = SIMD_ALIGN(width >> 1);
y_stride = uv_stride * 2;
yuv_size = y_stride * height + uv_stride * height;
y_offset = 0;
if (image == FOURCC_I420) {
u_offset = y_stride * height;
v_offset = (uv_stride * (height >> 1)) + u_offset;
}
else if (image == FOURCC_YV12) {
v_offset = y_stride * height;
u_offset = (uv_stride * (height >> 1)) + v_offset;
}
else {
return BadImplementation;
}
if (disp) {
/* Try to fixup overlay offset */
if (self->overlay_data_offs < disp->gfx_layer_size ||
self->overlay_data_offs + yuv_size > disp->framebuffer_size) {
self->overlay_data_offs = disp->gfx_layer_size;
}
/* If it is still wrong (not enough offscreen memory), then fail */
if (self->overlay_data_offs + yuv_size > disp->framebuffer_size)
return BadImplementation;
y_offset += self->overlay_data_offs;
u_offset += self->overlay_data_offs;
v_offset += self->overlay_data_offs;
memcpy(disp->framebuffer_addr + self->overlay_data_offs, buf, yuv_size);
/* Enable colorkey if it has not been already enabled */
if (!self->colorKeyEnabled) {
sunxi_layer_set_colorkey(disp, self->colorKey);
self->colorKeyEnabled = TRUE;
}
sunxi_layer_set_yuv420_input_buffer(disp, y_offset, u_offset, v_offset,
width, height, y_stride);
sunxi_layer_set_output_window(disp, drw_x, drw_y, drw_w, drw_h);
sunxi_layer_show(disp);
/* Cycle through different overlay offsets (to prevent tearing) */
self->overlay_data_offs += yuv_size;
}
/* Update the areas filled with the color key */
if (!REGION_EQUAL(pScrn->pScreen, &self->clip, clipBoxes)) {
REGION_COPY(pScrn->pScreen, &self->clip, clipBoxes);
xf86XVFillKeyHelperDrawable(pDraw, convert_color(pScrn, self->colorKey), clipBoxes);
}
return Success;
}
static int
xReputImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y,
short src_w, short src_h, short drw_w, short drw_h,
RegionPtr clipBoxes, pointer data, DrawablePtr pDraw)
{
sunxi_disp_t *disp = SUNXI_DISP(pScrn);
sunxi_layer_set_output_window(disp, drw_x, drw_y, drw_w, drw_h);
return Success;
}
static int
xQueryImageAttributes(ScrnInfoPtr pScrn, int image,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets)
{
int height, width;
int y_stride, uv_stride, yuv_size;
width = *w = (*w + 1) & ~1;
height = *h = (*h + 1) & ~1;
uv_stride = SIMD_ALIGN(width >> 1);
y_stride = uv_stride * 2;
yuv_size = y_stride * height + uv_stride * height;
if (pitches) {
pitches[0] = y_stride;
pitches[1] = uv_stride;
pitches[2] = uv_stride;
}
if (offsets) {
offsets[0] = 0;
offsets[1] = y_stride * height;
offsets[2] = (uv_stride * (height >> 1)) + offsets[1];
}
return yuv_size;
}
/*****************************************************************************/
static XF86VideoEncodingRec DummyEncoding[1] =
{
{ 0, "XV_IMAGE", XV_IMAGE_MAX_WIDTH, XV_IMAGE_MAX_HEIGHT, { 1, 1 } }
};
static XF86VideoFormatRec Formats[] = {
{16, TrueColor}, {24, TrueColor}
};
static XF86ImageRec Images[] =
{
XVIMAGE_YV12,
XVIMAGE_I420
};
static XF86AttributeRec Attributes[] =
{
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
};
SunxiVideo *SunxiVideo_Init(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
SunxiVideo *self;
XF86VideoAdaptorPtr adapt;
if (!(self = calloc(1, sizeof(SunxiVideo)))) {
xf86DrvMsg(pScreen->myNum, X_INFO, "SunxiVideo_Init: calloc failed\n");
return NULL;
}
if (!(self->adapt[0] = xf86XVAllocateVideoAdaptorRec(pScrn))) {
free(self);
return NULL;
}
adapt = self->adapt[0];
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
adapt->name = "Sunxi Video Overlay";
adapt->nEncodings = 1;
adapt->pEncodings = &DummyEncoding[0];
adapt->nFormats = ARRAY_SIZE(Formats);
adapt->pFormats = Formats;
adapt->nPorts = 1;
adapt->pPortPrivates = (DevUnion *) &self->port_privates[0];
adapt->pAttributes = Attributes;
adapt->nImages = ARRAY_SIZE(Images);
adapt->nAttributes = ARRAY_SIZE(Attributes);
adapt->pImages = Images;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
adapt->StopVideo = xStopVideo;
adapt->SetPortAttribute = xSetPortAttributeOverlay;
adapt->GetPortAttribute = xGetPortAttributeOverlay;
adapt->QueryBestSize = xQueryBestSize;
adapt->PutImage = xPutImage;
adapt->ReputImage = xReputImage;
adapt->QueryImageAttributes = xQueryImageAttributes;
xf86XVScreenInit(pScreen, &self->adapt[0], 1);
xvColorKey = MAKE_ATOM("XV_COLORKEY");
self->colorKey = 0x081018;
REGION_NULL(pScreen, &self->clip);
return self;
}
void SunxiVideo_Close(ScreenPtr pScreen)
{
}
/*
* Copyright © 2013 Siarhei Siamashka <siarhei.siamashka@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef SUNXI_VIDEO_H
#define SUNXI_VIDEO_H
#include "xf86xv.h"
#define XV_IMAGE_MAX_WIDTH 2048
#define XV_IMAGE_MAX_HEIGHT 2048
typedef struct {
RegionRec clip;
uint32_t colorKey;
Bool colorKeyEnabled;
int overlay_data_offs;
XF86VideoAdaptorPtr adapt[1];
void *port_privates[1];
} SunxiVideo;
SunxiVideo *SunxiVideo_Init(ScreenPtr pScreen);
void SunxiVideo_Close(ScreenPtr pScreen);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment