summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-09-23 06:42:24 +0100
committerAdam Jackson <ajax@redhat.com>2013-10-30 10:37:05 -0400
commitf4695af90cfe640c8de92cd9f6305bfd7a68d43e (patch)
tree7ec69d19e294205b615307f100332c7833bab92f
parentc1fa8586980f297bb0355cb60e2165e21c1e0ff0 (diff)
glamor: add initial Xv support
This does YV12 and I420 for now, not sure if we can do packed without a GL extension. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--glamor/Makefile.am1
-rw-r--r--glamor/configure.ac10
-rw-r--r--glamor/glamor.c6
-rw-r--r--glamor/glamor.h4
-rw-r--r--glamor/glamor_priv.h27
-rw-r--r--glamor/glamor_xv.c646
6 files changed, 692 insertions, 2 deletions
diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index c1759c6c5..50cfe97ea 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -53,6 +53,7 @@ libglamor_la_SOURCES = \
glamor_gl_dispatch.c\
glamor_fbo.c\
glamor_compositerects.c\
+ glamor_xv.c\
glamor_utils.h\
glamor.h\
glapi.h
diff --git a/glamor/configure.ac b/glamor/configure.ac
index 5a26e6835..bdcb4bb6d 100644
--- a/glamor/configure.ac
+++ b/glamor/configure.ac
@@ -95,7 +95,10 @@ AC_MSG_CHECKING([whether to enable DEBUG])
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Build debug version glamor (default: no)]), [DEBUG="$enableval"], [DEBUG=no])
AC_MSG_RESULT([$DEBUG])
-AM_CONDITIONAL([GLAMOR_GLES2], [test "x$GLAMOR_GLES2" = xyes])
+AC_MSG_CHECKING([whether to include GLAMOR Xv support])
+AC_ARG_ENABLE(xv, AS_HELP_STRING([--enable-xv], [Build glamor Xv (default: no)]), [GLAMOR_XV="$enableval"], [GLAMOR_XV=no])
+AC_MSG_RESULT([$GLAMOR_XV])
+AM_CONDITIONAL([GLAMOR_XV], [test "x$GLAMOR_XV" = xyes])
if test "x$DEBUG" = xyes; then
AC_DEFINE(DEBUG, 1, [Enable DEBUG])
@@ -115,6 +118,11 @@ fi
AC_SUBST([GLAMOR_GL_CFLAGS])
+AM_CONDITIONAL([GLAMOR_GLES2], [test "x$GLAMOR_GLES2" = xyes])
+if test "x$GLAMOR_XV" = xyes; then
+ AC_DEFINE(GLAMOR_XV,1,[Build Xv support])
+fi
+
PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
PKG_CHECK_MODULES(EGL, $LIBEGL, [EGL=yes], [EGL=no])
AM_CONDITIONAL([EGL], [test "x$EGL" = xyes])
diff --git a/glamor/glamor.c b/glamor/glamor.c
index d51811e5d..7637f3bfe 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -428,6 +428,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
#ifdef GLAMOR_GRADIENT_SHADER
glamor_init_gradient_shader(screen);
#endif
+#ifdef GLAMOR_XV
+ glamor_init_xv_shader(screen);
+#endif
glamor_pixmap_init(screen);
glamor_priv->flags = flags;
@@ -447,6 +450,9 @@ glamor_release_screen_priv(ScreenPtr screen)
glamor_screen_private *glamor_priv;
glamor_priv = glamor_get_screen_private(screen);
+#ifdef GLAMOR_XV
+ glamor_fini_xv_shader(screen);
+#endif
#ifdef RENDER
glamor_fini_composite_shaders(screen);
#endif
diff --git a/glamor/glamor.h b/glamor/glamor.h
index bafd543b5..c143c4dcb 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -37,7 +37,7 @@
#include <picturestr.h>
#include <fb.h>
#include <fbpict.h>
-
+#include <xf86xv.h>
/*
* glamor_pixmap_type : glamor pixmap's type.
* @MEMORY: pixmap is in memory.
@@ -348,4 +348,6 @@ extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, int
extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n,
DDXPointPtr points);
+extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen, int num_texture_ports);
+
#endif /* GLAMOR_H */
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 5437f738c..a64d86336 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -304,6 +304,9 @@ typedef struct glamor_screen_private {
int state;
unsigned int render_idle_cnt;
ScreenPtr screen;
+
+ /* xv */
+ GLint xv_prog;
} glamor_screen_private;
typedef enum glamor_access {
@@ -993,6 +996,30 @@ glamor_composite_rectangles(CARD8 op,
int num_rects,
xRectangle *rects);
+/* glamor_xv */
+typedef struct {
+ uint32_t transform_index;
+ uint32_t gamma; /* gamma value x 1000 */
+ int brightness;
+ int saturation;
+ int hue;
+ int contrast;
+
+ DrawablePtr pDraw;
+ PixmapPtr pPixmap;
+ uint32_t src_pitch;
+ uint8_t *src_addr;
+ int src_w, src_h, dst_w, dst_h;
+ int src_x, src_y, drw_x, drw_y;
+ int w, h;
+ RegionRec clip;
+ PixmapPtr src_pix[3]; /* y, u, v for planar */
+ int src_pix_w, src_pix_h;
+} glamor_port_private;
+
+void glamor_init_xv_shader(ScreenPtr screen);
+void glamor_fini_xv_shader(ScreenPtr screen);
+
#include"glamor_utils.h"
/* Dynamic pixmap upload to texture if needed.
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
new file mode 100644
index 000000000..1d77eaa65
--- /dev/null
+++ b/glamor/glamor_xv.c
@@ -0,0 +1,646 @@
+/*
+ * Copyright © 2013 Red Hat
+ *
+ * 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ * some code is derived from the xf86-video-ati radeon driver, mainly
+ * the calculations.
+ */
+
+/** @file glamor_xv.c
+ *
+ * Xv acceleration implementation
+ */
+
+#include "glamor_priv.h"
+
+#ifdef GLAMOR_XV
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "fourcc.h"
+/* Reference color space transform data */
+typedef struct tagREF_TRANSFORM
+{
+ float RefLuma;
+ float RefRCb;
+ float RefRCr;
+ float RefGCb;
+ float RefGCr;
+ float RefBCb;
+ float RefBCr;
+} REF_TRANSFORM;
+
+#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
+#define RTFBrightness(a) (((a)*1.0)/2000.0)
+#define RTFIntensity(a) (((a)*1.0)/2000.0)
+#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
+#define RTFHue(a) (((a)*3.1416)/1000.0)
+
+static const char *xv_vs= "attribute vec4 v_position;\n"
+ "attribute vec4 v_texcoord0;\n"
+ "varying vec2 tcs;\n"
+ "void main()\n" "{\n" " gl_Position = v_position;\n"
+ "tcs = v_texcoord0.xy;\n"
+ "}\n";
+
+static const char *xv_ps = GLAMOR_DEFAULT_PRECISION
+ "uniform sampler2D y_sampler;\n"
+ "uniform sampler2D u_sampler;\n"
+ "uniform sampler2D v_sampler;\n"
+ "uniform vec4 offsetyco;\n"
+ "uniform vec4 ucogamma;\n"
+ "uniform vec4 vco;\n"
+ "varying vec2 tcs;\n"
+ "float sample;\n"
+ "vec4 temp1;\n"
+ "void main()\n" "{\n"
+ "sample = texture2D(y_sampler, tcs).w;\n"
+ "temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
+ "sample = texture2D(u_sampler, tcs).w;\n"
+ "temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n"
+ "sample = texture2D(v_sampler, tcs).w;\n"
+ "temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n"
+ "temp1.w = 1.0;\n"
+ "gl_FragColor = temp1;\n"
+ "}\n";
+
+void
+glamor_init_xv_shader(ScreenPtr screen)
+{
+ glamor_screen_private *glamor_priv;
+ glamor_gl_dispatch *dispatch;
+ GLint fs_prog, vs_prog;
+ GLint sampler_loc;
+
+ glamor_priv = glamor_get_screen_private(screen);
+ dispatch = glamor_get_dispatch(glamor_priv);
+ glamor_priv->xv_prog = dispatch->glCreateProgram();
+
+ vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, xv_vs);
+ fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, xv_ps);
+ dispatch->glAttachShader(glamor_priv->xv_prog, vs_prog);
+ dispatch->glAttachShader(glamor_priv->xv_prog, fs_prog);
+
+ dispatch->glBindAttribLocation(glamor_priv->xv_prog,
+ GLAMOR_VERTEX_POS, "v_position");
+ dispatch->glBindAttribLocation(glamor_priv->xv_prog,
+ GLAMOR_VERTEX_SOURCE, "v_texcoord0");
+ glamor_link_glsl_prog(dispatch, glamor_priv->xv_prog);
+
+ glamor_put_dispatch(glamor_priv);
+}
+
+void
+glamor_fini_xv_shader(ScreenPtr screen)
+{
+ glamor_screen_private *glamor_priv;
+ glamor_gl_dispatch *dispatch;
+
+ glamor_priv = glamor_get_screen_private(screen);
+ dispatch = glamor_get_dispatch(glamor_priv);
+
+ dispatch->glDeleteProgram(glamor_priv->xv_prog);
+ glamor_put_dispatch(glamor_priv);
+}
+
+#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast, xvSaturation, xvHue, xvColorspace, xvGamma;
+
+#define NUM_ATTRIBUTES 5
+static XF86AttributeRec Attributes_glamor[NUM_ATTRIBUTES+1] =
+{
+ {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
+ {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
+ {0, 0, 0, NULL}
+ };
+
+#define NUM_FORMATS 3
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] =
+{
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+ };
+
+#define NUM_IMAGES 2
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+XVIMAGE_YV12,
+ XVIMAGE_I420,
+ };
+
+static void
+glamor_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
+{
+glamor_port_private *port_priv = (glamor_port_private *)data;
+int i;
+if (!cleanup)
+ return;
+
+for (i = 0; i < 3; i++) {
+if (port_priv->src_pix[i]) {
+glamor_destroy_pixmap(port_priv->src_pix[i]);
+port_priv->src_pix[i] = NULL;
+}
+}
+}
+
+static int
+glamor_xv_set_port_attribute(ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data)
+{
+glamor_port_private *port_priv = (glamor_port_private *)data;
+if (attribute == xvBrightness)
+ port_priv->brightness = ClipValue(value, -1000, 1000);
+else if (attribute == xvHue)
+ port_priv->hue = ClipValue(value, -1000, 1000);
+else if (attribute == xvContrast)
+ port_priv->contrast = ClipValue(value, -1000, 1000);
+else if (attribute == xvSaturation)
+ port_priv->saturation = ClipValue(value, -1000, 1000);
+else if (attribute == xvGamma)
+ port_priv->gamma = ClipValue (value, 100, 10000);
+else if(attribute == xvColorspace)
+ port_priv->transform_index = ClipValue (value, 0, 1);
+else
+ return BadMatch;
+return Success;
+}
+
+static int
+glamor_xv_get_port_attribute(ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data)
+{
+glamor_port_private *port_priv = (glamor_port_private *)data;
+if (attribute == xvBrightness)
+ *value = port_priv->brightness;
+else if (attribute == xvHue)
+ *value = port_priv->hue;
+else if (attribute == xvContrast)
+ *value = port_priv->contrast;
+else if (attribute == xvSaturation)
+ *value = port_priv->saturation;
+else if (attribute == xvGamma)
+ *value = port_priv->gamma;
+else if(attribute == xvColorspace)
+ *value = port_priv->transform_index;
+else
+ return BadMatch;
+
+return Success;
+}
+
+static void
+glamor_xv_query_best_size(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
+glamor_xv_query_image_attributes(ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets)
+{
+int size = 0, tmp;
+
+if (offsets) offsets[0] = 0;
+switch (id) {
+case FOURCC_YV12:
+case FOURCC_I420:
+*h = *h;
+*w = *w;
+size = *w;
+if (pitches) pitches[0] = size;
+size *= *h;
+if (offsets) offsets[1] = size;
+tmp = *w >> 1;
+if (pitches) pitches[1] = pitches[2] = tmp;
+tmp *= (*h >> 1);
+size += tmp;
+if (offsets) offsets[2] = size;
+size += tmp;
+break;
+}
+return size;
+}
+/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
+ note the difference to the parameters used in overlay are due
+ to 10bit vs. float calcs */
+static REF_TRANSFORM trans[2] =
+{
+ {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */
+ {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */
+ };
+
+static void
+glamor_display_textured_video(glamor_port_private *port_priv)
+{
+ScreenPtr screen = port_priv->pPixmap->drawable.pScreen;
+glamor_screen_private *glamor_priv =
+ glamor_get_screen_private(screen);
+glamor_pixmap_private *pixmap_priv =
+ glamor_get_pixmap_private(port_priv->pPixmap);
+glamor_pixmap_private *src_pixmap_priv[3];
+glamor_gl_dispatch *dispatch;
+float vertices[32], texcoords[8];
+BoxPtr box = REGION_RECTS(&port_priv->clip);
+int nBox = REGION_NUM_RECTS(&port_priv->clip);
+int dst_x_off, dst_y_off;
+GLfloat dst_xscale, dst_yscale;
+GLfloat src_xscale[3], src_yscale[3];
+int i;
+const float Loff = -0.0627;
+const float Coff = -0.502;
+float uvcosf, uvsinf;
+float yco;
+float uco[3], vco[3], off[3];
+float bright, cont, gamma;
+int ref = port_priv->transform_index;
+GLint uloc, sampler_loc;
+
+cont = RTFContrast(port_priv->contrast);
+bright = RTFBrightness(port_priv->brightness);
+gamma = (float)port_priv->gamma / 1000.0;
+uvcosf = RTFSaturation(port_priv->saturation) * cos(RTFHue(port_priv->hue));
+uvsinf = RTFSaturation(port_priv->saturation) * sin(RTFHue(port_priv->hue));
+/* overlay video also does pre-gamma contrast/sat adjust, should we? */
+
+yco = trans[ref].RefLuma * cont;
+uco[0] = -trans[ref].RefRCr * uvsinf;
+uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
+uco[2] = trans[ref].RefBCb * uvcosf;
+vco[0] = trans[ref].RefRCr * uvcosf;
+vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
+vco[2] = trans[ref].RefBCb * uvsinf;
+off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
+off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
+off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
+gamma = 1.0;
+
+pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale);
+glamor_get_drawable_deltas(port_priv->pDraw, port_priv->pPixmap, &dst_x_off,
+ &dst_y_off);
+glamor_set_destination_pixmap_priv_nc(pixmap_priv);
+
+for (i = 0; i < 3; i++) {
+if (port_priv->src_pix[i]) {
+src_pixmap_priv[i] = glamor_get_pixmap_private(port_priv->src_pix[i]);
+pixmap_priv_get_scale(src_pixmap_priv[i], &src_xscale[i], &src_yscale[i]);
+}
+}
+dispatch = glamor_get_dispatch(glamor_priv);
+dispatch->glUseProgram(glamor_priv->xv_prog);
+
+uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "offsetyco");
+dispatch->glUniform4f(uloc, off[0], off[1], off[2], yco);
+uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "ucogamma");
+dispatch->glUniform4f(uloc, uco[0], uco[1], uco[2], gamma);
+uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "vco");
+dispatch->glUniform4f(uloc, vco[0], vco[1], vco[2], 0);
+
+dispatch->glActiveTexture(GL_TEXTURE0);
+dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->base.fbo->tex);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+
+dispatch->glActiveTexture(GL_TEXTURE1);
+dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->base.fbo->tex);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+
+dispatch->glActiveTexture(GL_TEXTURE2);
+dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->base.fbo->tex);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+dispatch->glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+
+sampler_loc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "y_sampler");
+dispatch->glUniform1i(sampler_loc, 0);
+sampler_loc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "u_sampler");
+dispatch->glUniform1i(sampler_loc, 1);
+sampler_loc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "v_sampler");
+dispatch->glUniform1i(sampler_loc, 2);
+
+dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
+ GL_FLOAT, GL_FALSE,
+ 2 * sizeof(float),
+ texcoords);
+dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+
+dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+ GL_FALSE, 2 * sizeof(float),
+ vertices);
+
+dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+for (i = 0; i < nBox; i++) {
+float off_x = box[i].x1 - port_priv->drw_x;
+float off_y = box[i].y1 - port_priv->drw_y;
+float diff_x = (float)port_priv->src_w / (float)port_priv->dst_w;
+float diff_y = (float)port_priv->src_h / (float)port_priv->dst_h;
+float srcx, srcy, srcw, srch;
+int dstx, dsty, dstw, dsth;
+
+
+dstx = box[i].x1 + dst_x_off;
+dsty = box[i].y1 + dst_y_off;
+dstw = box[i].x2 - box[i].x1;
+dsth = box[i].y2 - box[i].y1;
+
+srcx = port_priv->src_x + off_x * diff_x;
+srcy = port_priv->src_y + off_y * diff_y;
+srcw = (port_priv->src_w * dstw) / (float)port_priv->dst_w;
+srch = (port_priv->src_h * dsth) / (float)port_priv->dst_h;
+
+glamor_set_normalize_vcoords(pixmap_priv,
+ dst_xscale, dst_yscale,
+ dstx,
+ dsty,
+ dstx + dstw,
+ dsty + dsth,
+ glamor_priv->yInverted,
+ vertices);
+
+glamor_set_normalize_tcoords(src_pixmap_priv[0],
+ src_xscale[0],
+ src_yscale[0],
+ srcx,
+ srcy,
+ srcx + srcw,
+ srcy + srch,
+ glamor_priv->yInverted,
+ texcoords);
+
+dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
+
+dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+
+dispatch->glUseProgram(0);
+glamor_put_dispatch(glamor_priv);
+DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
+}
+
+static int glamor_xv_put_image(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 id,
+ unsigned char *buf,
+ short width,
+ short height,
+ Bool sync,
+ RegionPtr clipBoxes,
+ pointer data,
+ DrawablePtr pDrawable)
+{
+ ScreenPtr screen = xf86ScrnToScreen(pScrn);
+ glamor_port_private *port_priv = (glamor_port_private *)data;
+ INT32 x1, x2, y1, y2;
+ int srcPitch, srcPitch2;
+ BoxRec dstBox;
+ int top, nlines;
+ int s2offset, s3offset, tmp;
+
+ s2offset = s3offset = srcPitch2 = 0;
+
+ /* 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;
+
+ if ((x1 >= x2) || (y1 >= y2))
+ return Success;
+
+ srcPitch = width;
+ srcPitch2 = width >> 1;
+
+ if (!port_priv->src_pix[0] || (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
+ int i;
+ for (i = 0; i < 2; i++)
+ if (port_priv->src_pix[i])
+ glamor_destroy_pixmap(port_priv->src_pix[i]);
+
+ port_priv->src_pix[0] = glamor_create_pixmap(screen, width, height, 8, 0);
+ port_priv->src_pix[1] = glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
+ port_priv->src_pix[2] = glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
+ port_priv->src_pix_w = width;
+ port_priv->src_pix_h = height;
+
+ if (!port_priv->src_pix[0] || !port_priv->src_pix[1] || !port_priv->src_pix[2])
+ return BadAlloc;
+ }
+
+ top = (y1 >> 16) & ~1;
+ nlines = ((y2 + 0xffff) >> 16) - top;
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ s2offset = srcPitch * height;
+ s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
+ s2offset += ((top >> 1) * srcPitch2);
+ s3offset += ((top >> 1) * srcPitch2);
+ if (id == FOURCC_YV12) {
+ tmp = s2offset;
+ s2offset = s3offset;
+ s3offset = tmp;
+ }
+ glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
+ 0, 0, srcPitch, nlines,
+ port_priv->src_pix[0]->devKind,
+ buf + (top * srcPitch), 0);
+
+ glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
+ 0, 0, srcPitch2, (nlines + 1) >> 1,
+ port_priv->src_pix[1]->devKind,
+ buf + s2offset, 0);
+
+ glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
+ 0, 0, srcPitch2, (nlines + 1) >> 1,
+ port_priv->src_pix[2]->devKind,
+ buf + s3offset, 0);
+ break;
+ default:
+ return BadMatch;
+ }
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ port_priv->pPixmap = (*screen->GetWindowPixmap)((WindowPtr)pDrawable);
+ else
+ port_priv->pPixmap = (PixmapPtr)pDrawable;
+
+ if (!RegionEqual(&port_priv->clip, clipBoxes)) {
+ RegionCopy(&port_priv->clip, clipBoxes);
+ }
+
+ port_priv->src_x = src_x;
+ port_priv->src_y = src_y;
+ port_priv->src_w = src_w;
+ port_priv->src_h = src_h;
+ port_priv->dst_w = drw_w;
+ port_priv->dst_h = drw_h;
+ port_priv->drw_x = drw_x;
+ port_priv->drw_y = drw_y;
+ port_priv->w = width;
+ port_priv->h = height;
+ port_priv->pDraw = pDrawable;
+ glamor_display_textured_video(port_priv);
+ return Success;
+}
+
+static XF86VideoEncodingRec DummyEncodingGLAMOR[1] =
+{
+ {
+ 0,
+ "XV_IMAGE",
+ 8192, 8192,
+ {1, 1}
+ }
+};
+
+XF86VideoAdaptorPtr
+glamor_xv_init(ScreenPtr screen, int num_texture_ports)
+{
+ glamor_port_private *port_priv;
+ XF86VideoAdaptorPtr adapt;
+ int i;
+
+ adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
+ (sizeof(glamor_port_private) + sizeof(DevUnion)));
+ if (adapt == NULL)
+ return NULL;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvSaturation = MAKE_ATOM("XV_SATURATION");
+ xvHue = MAKE_ATOM("XV_HUE");
+ xvGamma = MAKE_ATOM("XV_GAMMA");
+ xvColorspace = MAKE_ATOM("XV_COLORSPACE");
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = 0;
+ adapt->name = "GLAMOR Textured Video";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncodingGLAMOR;
+
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = num_texture_ports;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+ adapt->pAttributes = Attributes_glamor;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+
+ port_priv = (glamor_port_private *)(&adapt->pPortPrivates[num_texture_ports]);
+ adapt->pImages = Images;
+ adapt->nImages = NUM_IMAGES;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = glamor_xv_stop_video;
+ adapt->SetPortAttribute = glamor_xv_set_port_attribute;
+ adapt->GetPortAttribute = glamor_xv_get_port_attribute;
+ adapt->QueryBestSize = glamor_xv_query_best_size;
+ adapt->PutImage = glamor_xv_put_image;
+ adapt->ReputImage = NULL;
+ adapt->QueryImageAttributes = glamor_xv_query_image_attributes;
+
+ for (i = 0; i < num_texture_ports; i++) {
+ glamor_port_private *pPriv = &port_priv[i];
+
+ pPriv->brightness = 0;
+ pPriv->contrast = 0;
+ pPriv->saturation = 0;
+ pPriv->hue = 0;
+ pPriv->gamma = 1000;
+ pPriv->transform_index = 0;
+
+ REGION_NULL(pScreen, &pPriv->clip);
+
+ adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
+ }
+ return adapt;
+}
+#else
+XF86VideoAdaptorPtr
+glamor_xv_init(ScreenPtr screen, int num_texture_ports)
+{
+ return NULL;
+}
+#endif