diff options
Diffstat (limited to 'xserver/glamor/glamor_xv.c')
-rw-r--r-- | xserver/glamor/glamor_xv.c | 273 |
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; |