1/* 2 * Copyright © 2013 Red Hat 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Dave Airlie <airlied@redhat.com> 25 * 26 * some code is derived from the xf86-video-ati radeon driver, mainly 27 * the calculations. 28 */ 29 30/** @file glamor_xv.c 31 * 32 * Xv acceleration implementation 33 */ 34 35#ifdef HAVE_DIX_CONFIG_H 36#include <dix-config.h> 37#endif 38 39#include "glamor_priv.h" 40#include "glamor_transform.h" 41#include "glamor_transfer.h" 42 43#include <X11/extensions/Xv.h> 44#include <fourcc.h> 45/* Reference color space transform data */ 46typedef struct tagREF_TRANSFORM { 47 float RefLuma; 48 float RefRCb; 49 float RefRCr; 50 float RefGCb; 51 float RefGCr; 52 float RefBCb; 53 float RefBCr; 54} REF_TRANSFORM; 55 56#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0) 57#define RTFBrightness(a) (((a)*1.0)/2000.0) 58#define RTFIntensity(a) (((a)*1.0)/2000.0) 59#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) 60#define RTFHue(a) (((a)*3.1416)/1000.0) 61 62static const glamor_facet glamor_facet_xv_planar_2 = { 63 .name = "xv_planar_2", 64 65 .version = 120, 66 67 .source_name = "v_texcoord0", 68 .vs_vars = ("attribute vec2 position;\n" 69 "attribute vec2 v_texcoord0;\n" 70 "varying vec2 tcs;\n"), 71 .vs_exec = (GLAMOR_POS(gl_Position, position) 72 " tcs = v_texcoord0;\n"), 73 74 .fs_vars = ("uniform sampler2D y_sampler;\n" 75 "uniform sampler2D u_sampler;\n" 76 "uniform vec4 offsetyco;\n" 77 "uniform vec4 ucogamma;\n" 78 "uniform vec4 vco;\n" 79 "varying vec2 tcs;\n"), 80 .fs_exec = ( 81 " float sample;\n" 82 " vec2 sample_uv;\n" 83 " vec4 temp1;\n" 84 " sample = texture2D(y_sampler, tcs).w;\n" 85 " temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n" 86 " sample_uv = texture2D(u_sampler, tcs).xy;\n" 87 " temp1.xyz = ucogamma.xyz * vec3(sample_uv.x) + temp1.xyz;\n" 88 " temp1.xyz = clamp(vco.xyz * vec3(sample_uv.y) + temp1.xyz, 0.0, 1.0);\n" 89 " temp1.w = 1.0;\n" 90 " gl_FragColor = temp1;\n" 91 ), 92}; 93 94static const glamor_facet glamor_facet_xv_planar_3 = { 95 .name = "xv_planar_3", 96 97 .version = 120, 98 99 .source_name = "v_texcoord0", 100 .vs_vars = ("attribute vec2 position;\n" 101 "attribute vec2 v_texcoord0;\n" 102 "varying vec2 tcs;\n"), 103 .vs_exec = (GLAMOR_POS(gl_Position, position) 104 " tcs = v_texcoord0;\n"), 105 106 .fs_vars = ("uniform sampler2D y_sampler;\n" 107 "uniform sampler2D u_sampler;\n" 108 "uniform sampler2D v_sampler;\n" 109 "uniform vec4 offsetyco;\n" 110 "uniform vec4 ucogamma;\n" 111 "uniform vec4 vco;\n" 112 "varying vec2 tcs;\n"), 113 .fs_exec = ( 114 " float sample;\n" 115 " vec4 temp1;\n" 116 " sample = texture2D(y_sampler, tcs).w;\n" 117 " temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n" 118 " sample = texture2D(u_sampler, tcs).w;\n" 119 " temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n" 120 " sample = texture2D(v_sampler, tcs).w;\n" 121 " temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n" 122 " temp1.w = 1.0;\n" 123 " gl_FragColor = temp1;\n" 124 ), 125}; 126 127#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 128 129XvAttributeRec glamor_xv_attributes[] = { 130 {XvSettable | XvGettable, -1000, 1000, (char *)"XV_BRIGHTNESS"}, 131 {XvSettable | XvGettable, -1000, 1000, (char *)"XV_CONTRAST"}, 132 {XvSettable | XvGettable, -1000, 1000, (char *)"XV_SATURATION"}, 133 {XvSettable | XvGettable, -1000, 1000, (char *)"XV_HUE"}, 134 {XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE"}, 135 {0, 0, 0, NULL} 136}; 137int glamor_xv_num_attributes = ARRAY_SIZE(glamor_xv_attributes) - 1; 138 139Atom glamorBrightness, glamorContrast, glamorSaturation, glamorHue, 140 glamorColorspace, glamorGamma; 141 142XvImageRec glamor_xv_images[] = { 143 XVIMAGE_YV12, 144 XVIMAGE_I420, 145 XVIMAGE_NV12 146}; 147int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images); 148 149static void 150glamor_init_xv_shader(ScreenPtr screen, int id) 151{ 152 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 153 GLint sampler_loc; 154 const glamor_facet *glamor_facet_xv_planar = NULL; 155 156 switch (id) { 157 case FOURCC_YV12: 158 case FOURCC_I420: 159 glamor_facet_xv_planar = &glamor_facet_xv_planar_3; 160 break; 161 case FOURCC_NV12: 162 glamor_facet_xv_planar = &glamor_facet_xv_planar_2; 163 break; 164 default: 165 break; 166 } 167 168 glamor_build_program(screen, 169 &glamor_priv->xv_prog, 170 glamor_facet_xv_planar, NULL, NULL, NULL); 171 172 glUseProgram(glamor_priv->xv_prog.prog); 173 sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "y_sampler"); 174 glUniform1i(sampler_loc, 0); 175 sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "u_sampler"); 176 glUniform1i(sampler_loc, 1); 177 178 switch (id) { 179 case FOURCC_YV12: 180 case FOURCC_I420: 181 sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "v_sampler"); 182 glUniform1i(sampler_loc, 2); 183 break; 184 case FOURCC_NV12: 185 break; 186 default: 187 break; 188 } 189 190} 191 192#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) 193 194void 195glamor_xv_stop_video(glamor_port_private *port_priv) 196{ 197} 198 199static void 200glamor_xv_free_port_data(glamor_port_private *port_priv) 201{ 202 int i; 203 204 for (i = 0; i < 3; i++) { 205 if (port_priv->src_pix[i]) { 206 glamor_destroy_pixmap(port_priv->src_pix[i]); 207 port_priv->src_pix[i] = NULL; 208 } 209 } 210 RegionUninit(&port_priv->clip); 211 RegionNull(&port_priv->clip); 212} 213 214int 215glamor_xv_set_port_attribute(glamor_port_private *port_priv, 216 Atom attribute, INT32 value) 217{ 218 if (attribute == glamorBrightness) 219 port_priv->brightness = ClipValue(value, -1000, 1000); 220 else if (attribute == glamorHue) 221 port_priv->hue = ClipValue(value, -1000, 1000); 222 else if (attribute == glamorContrast) 223 port_priv->contrast = ClipValue(value, -1000, 1000); 224 else if (attribute == glamorSaturation) 225 port_priv->saturation = ClipValue(value, -1000, 1000); 226 else if (attribute == glamorGamma) 227 port_priv->gamma = ClipValue(value, 100, 10000); 228 else if (attribute == glamorColorspace) 229 port_priv->transform_index = ClipValue(value, 0, 1); 230 else 231 return BadMatch; 232 return Success; 233} 234 235int 236glamor_xv_get_port_attribute(glamor_port_private *port_priv, 237 Atom attribute, INT32 *value) 238{ 239 if (attribute == glamorBrightness) 240 *value = port_priv->brightness; 241 else if (attribute == glamorHue) 242 *value = port_priv->hue; 243 else if (attribute == glamorContrast) 244 *value = port_priv->contrast; 245 else if (attribute == glamorSaturation) 246 *value = port_priv->saturation; 247 else if (attribute == glamorGamma) 248 *value = port_priv->gamma; 249 else if (attribute == glamorColorspace) 250 *value = port_priv->transform_index; 251 else 252 return BadMatch; 253 254 return Success; 255} 256 257int 258glamor_xv_query_image_attributes(int id, 259 unsigned short *w, unsigned short *h, 260 int *pitches, int *offsets) 261{ 262 int size = 0, tmp; 263 264 if (offsets) 265 offsets[0] = 0; 266 switch (id) { 267 case FOURCC_YV12: 268 case FOURCC_I420: 269 *w = ALIGN(*w, 2); 270 *h = ALIGN(*h, 2); 271 size = ALIGN(*w, 4); 272 if (pitches) 273 pitches[0] = size; 274 size *= *h; 275 if (offsets) 276 offsets[1] = size; 277 tmp = ALIGN(*w >> 1, 4); 278 if (pitches) 279 pitches[1] = pitches[2] = tmp; 280 tmp *= (*h >> 1); 281 size += tmp; 282 if (offsets) 283 offsets[2] = size; 284 size += tmp; 285 break; 286 case FOURCC_NV12: 287 *w = ALIGN(*w, 2); 288 *h = ALIGN(*h, 2); 289 size = ALIGN(*w, 4); 290 if (pitches) 291 pitches[0] = size; 292 size *= *h; 293 if (offsets) 294 offsets[1] = offsets[2] = size; 295 tmp = ALIGN(*w, 4); 296 if (pitches) 297 pitches[1] = pitches[2] = tmp; 298 tmp *= (*h >> 1); 299 size += tmp; 300 break; 301 } 302 return size; 303} 304 305/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces 306 note the difference to the parameters used in overlay are due 307 to 10bit vs. float calcs */ 308static REF_TRANSFORM trans[2] = { 309 {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */ 310 {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */ 311}; 312 313void 314glamor_xv_render(glamor_port_private *port_priv, int id) 315{ 316 ScreenPtr screen = port_priv->pPixmap->drawable.pScreen; 317 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 318 PixmapPtr pixmap = port_priv->pPixmap; 319 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 320 glamor_pixmap_private *src_pixmap_priv[3]; 321 BoxPtr box = REGION_RECTS(&port_priv->clip); 322 int nBox = REGION_NUM_RECTS(&port_priv->clip); 323 GLfloat src_xscale[3], src_yscale[3]; 324 int i; 325 const float Loff = -0.0627; 326 const float Coff = -0.502; 327 float uvcosf, uvsinf; 328 float yco; 329 float uco[3], vco[3], off[3]; 330 float bright, cont, gamma; 331 int ref = port_priv->transform_index; 332 GLint uloc; 333 GLfloat *v; 334 char *vbo_offset; 335 int dst_box_index; 336 337 if (!glamor_priv->xv_prog.prog) 338 glamor_init_xv_shader(screen, id); 339 340 cont = RTFContrast(port_priv->contrast); 341 bright = RTFBrightness(port_priv->brightness); 342 gamma = (float) port_priv->gamma / 1000.0; 343 uvcosf = RTFSaturation(port_priv->saturation) * cos(RTFHue(port_priv->hue)); 344 uvsinf = RTFSaturation(port_priv->saturation) * sin(RTFHue(port_priv->hue)); 345/* overlay video also does pre-gamma contrast/sat adjust, should we? */ 346 347 yco = trans[ref].RefLuma * cont; 348 uco[0] = -trans[ref].RefRCr * uvsinf; 349 uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf; 350 uco[2] = trans[ref].RefBCb * uvcosf; 351 vco[0] = trans[ref].RefRCr * uvcosf; 352 vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf; 353 vco[2] = trans[ref].RefBCb * uvsinf; 354 off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright; 355 off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright; 356 off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright; 357 gamma = 1.0; 358 359 glamor_set_alu(screen, GXcopy); 360 361 for (i = 0; i < 3; i++) { 362 if (port_priv->src_pix[i]) { 363 src_pixmap_priv[i] = 364 glamor_get_pixmap_private(port_priv->src_pix[i]); 365 pixmap_priv_get_scale(src_pixmap_priv[i], &src_xscale[i], 366 &src_yscale[i]); 367 } else { 368 src_pixmap_priv[i] = NULL; 369 } 370 } 371 glamor_make_current(glamor_priv); 372 glUseProgram(glamor_priv->xv_prog.prog); 373 374 uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "offsetyco"); 375 glUniform4f(uloc, off[0], off[1], off[2], yco); 376 uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "ucogamma"); 377 glUniform4f(uloc, uco[0], uco[1], uco[2], gamma); 378 uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "vco"); 379 glUniform4f(uloc, vco[0], vco[1], vco[2], 0); 380 381 glActiveTexture(GL_TEXTURE0); 382 glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->fbo->tex); 383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 387 388 glActiveTexture(GL_TEXTURE1); 389 glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->fbo->tex); 390 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 391 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 394 395 switch (id) { 396 case FOURCC_YV12: 397 case FOURCC_I420: 398 glActiveTexture(GL_TEXTURE2); 399 glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex); 400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 403 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 404 break; 405 case FOURCC_NV12: 406 break; 407 default: 408 break; 409 } 410 411 glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 412 glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); 413 414 glEnable(GL_SCISSOR_TEST); 415 416 v = glamor_get_vbo_space(screen, 3 * 4 * sizeof(GLfloat), &vbo_offset); 417 418 /* Set up a single primitive covering the area being drawn. We'll 419 * clip it to port_priv->clip using GL scissors instead of just 420 * emitting a GL_QUAD per box, because this way we hopefully avoid 421 * diagonal tearing between the two triangles used to rasterize a 422 * GL_QUAD. 423 */ 424 i = 0; 425 v[i++] = port_priv->drw_x; 426 v[i++] = port_priv->drw_y; 427 428 v[i++] = port_priv->drw_x + port_priv->dst_w * 2; 429 v[i++] = port_priv->drw_y; 430 431 v[i++] = port_priv->drw_x; 432 v[i++] = port_priv->drw_y + port_priv->dst_h * 2; 433 434 v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x); 435 v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y); 436 437 v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x + 438 port_priv->src_w * 2); 439 v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y); 440 441 v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x); 442 v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y + 443 port_priv->src_h * 2); 444 445 glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, 446 GL_FLOAT, GL_FALSE, 447 2 * sizeof(float), vbo_offset); 448 449 glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, 450 GL_FLOAT, GL_FALSE, 451 2 * sizeof(float), vbo_offset + 6 * sizeof(GLfloat)); 452 453 glamor_put_vbo_space(screen); 454 455 /* Now draw our big triangle, clipped to each of the clip boxes. */ 456 glamor_pixmap_loop(pixmap_priv, dst_box_index) { 457 int dst_off_x, dst_off_y; 458 459 glamor_set_destination_drawable(port_priv->pDraw, 460 dst_box_index, 461 FALSE, FALSE, 462 glamor_priv->xv_prog.matrix_uniform, 463 &dst_off_x, &dst_off_y); 464 465 for (i = 0; i < nBox; i++) { 466 int dstx, dsty, dstw, dsth; 467 468 dstx = box[i].x1 + dst_off_x; 469 dsty = box[i].y1 + dst_off_y; 470 dstw = box[i].x2 - box[i].x1; 471 dsth = box[i].y2 - box[i].y1; 472 473 glScissor(dstx, dsty, dstw, dsth); 474 glDrawArrays(GL_TRIANGLE_FAN, 0, 3); 475 } 476 } 477 glDisable(GL_SCISSOR_TEST); 478 479 glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 480 glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); 481 482 DamageDamageRegion(port_priv->pDraw, &port_priv->clip); 483 484 glamor_xv_free_port_data(port_priv); 485} 486 487int 488glamor_xv_put_image(glamor_port_private *port_priv, 489 DrawablePtr pDrawable, 490 short src_x, short src_y, 491 short drw_x, short drw_y, 492 short src_w, short src_h, 493 short drw_w, short drw_h, 494 int id, 495 unsigned char *buf, 496 short width, 497 short height, 498 Bool sync, 499 RegionPtr clipBoxes) 500{ 501 ScreenPtr pScreen = pDrawable->pScreen; 502 glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); 503 int srcPitch, srcPitch2; 504 int top, nlines; 505 int s2offset, s3offset, tmp; 506 BoxRec full_box, half_box; 507 508 s2offset = s3offset = srcPitch2 = 0; 509 510 if (!port_priv->src_pix[0] || 511 (width != port_priv->src_pix_w || height != port_priv->src_pix_h) || 512 (port_priv->src_pix[2] && id == FOURCC_NV12) || 513 (!port_priv->src_pix[2] && id != FOURCC_NV12)) { 514 int i; 515 516 if (glamor_priv->xv_prog.prog) { 517 glDeleteProgram(glamor_priv->xv_prog.prog); 518 glamor_priv->xv_prog.prog = 0; 519 } 520 521 for (i = 0; i < 3; i++) 522 if (port_priv->src_pix[i]) 523 glamor_destroy_pixmap(port_priv->src_pix[i]); 524 525 port_priv->src_pix[0] = 526 glamor_create_pixmap(pScreen, width, height, 8, 527 GLAMOR_CREATE_FBO_NO_FBO); 528 529 switch (id) { 530 case FOURCC_YV12: 531 case FOURCC_I420: 532 port_priv->src_pix[1] = 533 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 534 GLAMOR_CREATE_FBO_NO_FBO); 535 port_priv->src_pix[2] = 536 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 537 GLAMOR_CREATE_FBO_NO_FBO); 538 if (!port_priv->src_pix[2]) 539 return BadAlloc; 540 break; 541 case FOURCC_NV12: 542 port_priv->src_pix[1] = 543 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 16, 544 GLAMOR_CREATE_FBO_NO_FBO | 545 GLAMOR_CREATE_FORMAT_CBCR); 546 port_priv->src_pix[2] = NULL; 547 break; 548 default: 549 return BadMatch; 550 } 551 552 port_priv->src_pix_w = width; 553 port_priv->src_pix_h = height; 554 555 if (!port_priv->src_pix[0] || !port_priv->src_pix[1]) 556 return BadAlloc; 557 } 558 559 top = (src_y) & ~1; 560 nlines = (src_y + src_h) - top; 561 562 switch (id) { 563 case FOURCC_YV12: 564 case FOURCC_I420: 565 srcPitch = ALIGN(width, 4); 566 srcPitch2 = ALIGN(width >> 1, 4); 567 s2offset = srcPitch * height; 568 s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1)); 569 s2offset += ((top >> 1) * srcPitch2); 570 s3offset += ((top >> 1) * srcPitch2); 571 if (id == FOURCC_YV12) { 572 tmp = s2offset; 573 s2offset = s3offset; 574 s3offset = tmp; 575 } 576 577 full_box.x1 = 0; 578 full_box.y1 = 0; 579 full_box.x2 = width; 580 full_box.y2 = nlines; 581 582 half_box.x1 = 0; 583 half_box.y1 = 0; 584 half_box.x2 = width >> 1; 585 half_box.y2 = (nlines + 1) >> 1; 586 587 glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1, 588 0, 0, 0, 0, 589 buf + (top * srcPitch), srcPitch); 590 591 glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1, 592 0, 0, 0, 0, 593 buf + s2offset, srcPitch2); 594 595 glamor_upload_boxes(port_priv->src_pix[2], &half_box, 1, 596 0, 0, 0, 0, 597 buf + s3offset, srcPitch2); 598 break; 599 case FOURCC_NV12: 600 srcPitch = ALIGN(width, 4); 601 s2offset = srcPitch * height; 602 s2offset += ((top >> 1) * srcPitch); 603 604 full_box.x1 = 0; 605 full_box.y1 = 0; 606 full_box.x2 = width; 607 full_box.y2 = nlines; 608 609 half_box.x1 = 0; 610 half_box.y1 = 0; 611 half_box.x2 = width; 612 half_box.y2 = (nlines + 1) >> 1; 613 614 glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1, 615 0, 0, 0, 0, 616 buf + (top * srcPitch), srcPitch); 617 618 glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1, 619 0, 0, 0, 0, 620 buf + s2offset, srcPitch); 621 break; 622 default: 623 return BadMatch; 624 } 625 626 if (pDrawable->type == DRAWABLE_WINDOW) 627 port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable); 628 else 629 port_priv->pPixmap = (PixmapPtr) pDrawable; 630 631 RegionCopy(&port_priv->clip, clipBoxes); 632 633 port_priv->src_x = src_x; 634 port_priv->src_y = src_y - top; 635 port_priv->src_w = src_w; 636 port_priv->src_h = src_h; 637 port_priv->dst_w = drw_w; 638 port_priv->dst_h = drw_h; 639 port_priv->drw_x = drw_x; 640 port_priv->drw_y = drw_y; 641 port_priv->w = width; 642 port_priv->h = height; 643 port_priv->pDraw = pDrawable; 644 glamor_xv_render(port_priv, id); 645 return Success; 646} 647 648void 649glamor_xv_init_port(glamor_port_private *port_priv) 650{ 651 port_priv->brightness = 0; 652 port_priv->contrast = 0; 653 port_priv->saturation = 0; 654 port_priv->hue = 0; 655 port_priv->gamma = 1000; 656 port_priv->transform_index = 0; 657 658 REGION_NULL(pScreen, &port_priv->clip); 659} 660 661void 662glamor_xv_core_init(ScreenPtr screen) 663{ 664 glamorBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 665 glamorContrast = MAKE_ATOM("XV_CONTRAST"); 666 glamorSaturation = MAKE_ATOM("XV_SATURATION"); 667 glamorHue = MAKE_ATOM("XV_HUE"); 668 glamorGamma = MAKE_ATOM("XV_GAMMA"); 669 glamorColorspace = MAKE_ATOM("XV_COLORSPACE"); 670} 671