summaryrefslogtreecommitdiff
path: root/xserver/glamor/glamor_xv.c
diff options
context:
space:
mode:
Diffstat (limited to 'xserver/glamor/glamor_xv.c')
-rw-r--r--xserver/glamor/glamor_xv.c273
1 files changed, 145 insertions, 128 deletions
diff --git a/xserver/glamor/glamor_xv.c b/xserver/glamor/glamor_xv.c
index 83e24adb2..3bcf909b0 100644
--- a/xserver/glamor/glamor_xv.c
+++ b/xserver/glamor/glamor_xv.c
@@ -37,6 +37,8 @@
#endif
#include "glamor_priv.h"
+#include "glamor_transform.h"
+#include "glamor_transfer.h"
#include <X11/extensions/Xv.h>
#include "../hw/xfree86/common/fourcc.h"
@@ -57,36 +59,36 @@ typedef struct tagREF_TRANSFORM {
#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";
+static const glamor_facet glamor_facet_xv_planar = {
+ .name = "xv_planar",
+
+ .source_name = "v_texcoord0",
+ .vs_vars = ("attribute vec2 position;\n"
+ "attribute vec2 v_texcoord0;\n"
+ "varying vec2 tcs;\n"),
+ .vs_exec = (GLAMOR_POS(gl_Position, position)
+ " tcs = v_texcoord0;\n"),
+
+ .fs_vars = ("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"),
+ .fs_exec = (
+ " float sample;\n"
+ " vec4 temp1;\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"
+ ),
+};
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
@@ -112,23 +114,21 @@ int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images);
static void
glamor_init_xv_shader(ScreenPtr screen)
{
- glamor_screen_private *glamor_priv;
- GLint fs_prog, vs_prog;
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+ GLint sampler_loc;
+
+ glamor_build_program(screen,
+ &glamor_priv->xv_prog,
+ &glamor_facet_xv_planar, NULL, NULL, NULL);
+
+ glUseProgram(glamor_priv->xv_prog.prog);
+ sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "y_sampler");
+ glUniform1i(sampler_loc, 0);
+ sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "u_sampler");
+ glUniform1i(sampler_loc, 1);
+ sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "v_sampler");
+ glUniform1i(sampler_loc, 2);
- glamor_priv = glamor_get_screen_private(screen);
- glamor_make_current(glamor_priv);
- glamor_priv->xv_prog = glCreateProgram();
-
- vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xv_vs);
- fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xv_ps);
- glAttachShader(glamor_priv->xv_prog, vs_prog);
- glAttachShader(glamor_priv->xv_prog, fs_prog);
-
- glBindAttribLocation(glamor_priv->xv_prog,
- GLAMOR_VERTEX_POS, "v_position");
- glBindAttribLocation(glamor_priv->xv_prog,
- GLAMOR_VERTEX_SOURCE, "v_texcoord0");
- glamor_link_glsl_prog(screen, glamor_priv->xv_prog, "xv");
}
#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
@@ -241,14 +241,11 @@ glamor_xv_render(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);
+ PixmapPtr pixmap = port_priv->pPixmap;
+ glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_pixmap_private *src_pixmap_priv[3];
- 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;
@@ -258,9 +255,12 @@ glamor_xv_render(glamor_port_private *port_priv)
float uco[3], vco[3], off[3];
float bright, cont, gamma;
int ref = port_priv->transform_index;
- GLint uloc, sampler_loc;
+ GLint uloc;
+ GLfloat *v;
+ char *vbo_offset;
+ int dst_box_index;
- if (!glamor_priv->xv_prog)
+ if (!glamor_priv->xv_prog.prog)
glamor_init_xv_shader(screen);
cont = RTFContrast(port_priv->contrast);
@@ -282,10 +282,7 @@ glamor_xv_render(glamor_port_private *port_priv)
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);
+ glamor_set_alu(screen, GXcopy);
for (i = 0; i < 3; i++) {
if (port_priv->src_pix[i]) {
@@ -296,90 +293,101 @@ glamor_xv_render(glamor_port_private *port_priv)
}
}
glamor_make_current(glamor_priv);
- glUseProgram(glamor_priv->xv_prog);
+ glUseProgram(glamor_priv->xv_prog.prog);
- uloc = glGetUniformLocation(glamor_priv->xv_prog, "offsetyco");
+ uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "offsetyco");
glUniform4f(uloc, off[0], off[1], off[2], yco);
- uloc = glGetUniformLocation(glamor_priv->xv_prog, "ucogamma");
+ uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "ucogamma");
glUniform4f(uloc, uco[0], uco[1], uco[2], gamma);
- uloc = glGetUniformLocation(glamor_priv->xv_prog, "vco");
+ uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "vco");
glUniform4f(uloc, vco[0], vco[1], vco[2], 0);
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->base.fbo->tex);
+ glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->base.fbo->tex);
+ glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->base.fbo->tex);
+ glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "y_sampler");
- glUniform1i(sampler_loc, 0);
- sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "u_sampler");
- glUniform1i(sampler_loc, 1);
- sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "v_sampler");
- glUniform1i(sampler_loc, 2);
+ glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+ glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+
+ glEnable(GL_SCISSOR_TEST);
+
+ v = glamor_get_vbo_space(screen, 3 * 4 * sizeof(GLfloat), &vbo_offset);
+
+ /* Set up a single primitive covering the area being drawn. We'll
+ * clip it to port_priv->clip using GL scissors instead of just
+ * emitting a GL_QUAD per box, because this way we hopefully avoid
+ * diagonal tearing between the two trangles used to rasterize a
+ * GL_QUAD.
+ */
+ i = 0;
+ v[i++] = port_priv->drw_x;
+ v[i++] = port_priv->drw_y;
+
+ v[i++] = port_priv->drw_x + port_priv->dst_w * 2;
+ v[i++] = port_priv->drw_y;
+
+ v[i++] = port_priv->drw_x;
+ v[i++] = port_priv->drw_y + port_priv->dst_h * 2;
+
+ v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x);
+ v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y);
+
+ v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x +
+ port_priv->src_w * 2);
+ v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y);
+
+ v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x);
+ v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y +
+ port_priv->src_h * 2);
+
+ glVertexAttribPointer(GLAMOR_VERTEX_POS, 2,
+ GL_FLOAT, GL_FALSE,
+ 2 * sizeof(float), vbo_offset);
glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
GL_FLOAT, GL_FALSE,
- 2 * sizeof(float), texcoords);
- glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+ 2 * sizeof(float), vbo_offset + 6 * sizeof(GLfloat));
- glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
- GL_FALSE, 2 * sizeof(float), vertices);
+ glamor_put_vbo_space(screen);
- glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
- glEnable(GL_SCISSOR_TEST);
- 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 - dstw,
- dsty,
- dstx + dstw,
- dsty + dsth * 2,
- vertices);
-
- glamor_set_normalize_tcoords(src_pixmap_priv[0],
- src_xscale[0],
- src_yscale[0],
- srcx - srcw,
- srcy,
- srcx + srcw,
- srcy + srch * 2,
- texcoords);
-
- glScissor(dstx, dsty, dstw, dsth);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
+ /* Now draw our big triangle, clipped to each of the clip boxes. */
+ glamor_pixmap_loop(pixmap_priv, dst_box_index) {
+ int dst_off_x, dst_off_y;
+
+ glamor_set_destination_drawable(port_priv->pDraw,
+ dst_box_index,
+ FALSE, FALSE,
+ glamor_priv->xv_prog.matrix_uniform,
+ &dst_off_x, &dst_off_y);
+
+ for (i = 0; i < nBox; i++) {
+ int dstx, dsty, dstw, dsth;
+
+ dstx = box[i].x1 + dst_off_x;
+ dsty = box[i].y1 + dst_off_y;
+ dstw = box[i].x2 - box[i].x1;
+ dsth = box[i].y2 - box[i].y1;
+
+ glScissor(dstx, dsty, dstw, dsth);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
+ }
}
glDisable(GL_SCISSOR_TEST);
@@ -409,6 +417,7 @@ glamor_xv_put_image(glamor_port_private *port_priv,
int srcPitch, srcPitch2;
int top, nlines;
int s2offset, s3offset, tmp;
+ BoxRec full_box, half_box;
s2offset = s3offset = srcPitch2 = 0;
@@ -451,20 +460,28 @@ glamor_xv_put_image(glamor_port_private *port_priv,
s2offset = s3offset;
s3offset = tmp;
}
- glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
- 0, 0, width, nlines,
- srcPitch,
- buf + (top * srcPitch), 0);
-
- glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
- 0, 0, width >> 1, (nlines + 1) >> 1,
- srcPitch2,
- buf + s2offset, 0);
-
- glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
- 0, 0, width >> 1, (nlines + 1) >> 1,
- srcPitch2,
- buf + s3offset, 0);
+
+ full_box.x1 = 0;
+ full_box.y1 = 0;
+ full_box.x2 = width;
+ full_box.y2 = nlines;
+
+ half_box.x1 = 0;
+ half_box.y1 = 0;
+ half_box.x2 = width >> 1;
+ half_box.y2 = (nlines + 1) >> 1;
+
+ glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1,
+ 0, 0, 0, 0,
+ buf + (top * srcPitch), srcPitch);
+
+ glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1,
+ 0, 0, 0, 0,
+ buf + s2offset, srcPitch2);
+
+ glamor_upload_boxes(port_priv->src_pix[2], &half_box, 1,
+ 0, 0, 0, 0,
+ buf + s3offset, srcPitch2);
break;
default:
return BadMatch;
@@ -478,7 +495,7 @@ glamor_xv_put_image(glamor_port_private *port_priv,
RegionCopy(&port_priv->clip, clipBoxes);
port_priv->src_x = src_x;
- port_priv->src_y = src_y;
+ port_priv->src_y = src_y - top;
port_priv->src_w = src_w;
port_priv->src_h = src_h;
port_priv->dst_w = drw_w;