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>
This commit is contained in:
parent
39e95cd0f5
commit
e3d1d4e3ca
|
@ -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
|
||||
|
|
|
@ -427,6 +427,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
glamor_init_finish_access_shaders(screen);
|
||||
#ifdef GLAMOR_GRADIENT_SHADER
|
||||
glamor_init_gradient_shader(screen);
|
||||
#endif
|
||||
#ifdef GLAMOR_XV
|
||||
glamor_init_xv_shader(screen);
|
||||
#endif
|
||||
glamor_pixmap_init(screen);
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
646
glamor/glamor_xv.c
Normal file
646
glamor/glamor_xv.c
Normal file
|
@ -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
|
Loading…
Reference in New Issue
Block a user