xorg_composite.c revision 8c37a4c8fd133f3cddc6798a0834038730acc213
1#include "xorg_composite.h" 2 3#include "xorg_exa_tgsi.h" 4 5#include "cso_cache/cso_context.h" 6#include "util/u_draw_quad.h" 7#include "util/u_math.h" 8 9#include "pipe/p_inlines.h" 10 11struct xorg_composite_blend { 12 int op:8; 13 14 unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */ 15 unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ 16 17 unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ 18 unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ 19}; 20 21#define BLEND_OP_OVER 3 22static const struct xorg_composite_blend xorg_blends[] = { 23 { PictOpClear, 24 PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA, 25 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, 26 27 { PictOpSrc, 28 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE, 29 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, 30 31 { PictOpDst, 32 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO, 33 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE }, 34 35 { PictOpOver, 36 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE, 37 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 38 39 { PictOpOverReverse, 40 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE, 41 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 42}; 43 44 45static INLINE void 46pixel_to_float4(Pixel pixel, float *color) 47{ 48 CARD32 r, g, b, a; 49 50 a = (pixel >> 24) & 0xff; 51 r = (pixel >> 16) & 0xff; 52 g = (pixel >> 8) & 0xff; 53 b = (pixel >> 0) & 0xff; 54 color[0] = ((float)r) / 255.; 55 color[1] = ((float)g) / 255.; 56 color[2] = ((float)b) / 255.; 57 color[3] = ((float)a) / 255.; 58} 59 60static INLINE void 61render_pixel_to_float4(PictFormatPtr format, 62 CARD32 pixel, float *color) 63{ 64 CARD32 r, g, b, a; 65 66 debug_assert(format->type == PictTypeDirect); 67 68 r = (pixel >> format->direct.red) & format->direct.redMask; 69 g = (pixel >> format->direct.green) & format->direct.greenMask; 70 b = (pixel >> format->direct.blue) & format->direct.blueMask; 71 a = (pixel >> format->direct.alpha) & format->direct.alphaMask; 72 color[0] = ((float)r) / ((float)format->direct.redMask); 73 color[1] = ((float)g) / ((float)format->direct.greenMask); 74 color[2] = ((float)b) / ((float)format->direct.blueMask); 75 color[3] = ((float)a) / ((float)format->direct.alphaMask); 76} 77 78struct acceleration_info { 79 int op : 16; 80 int with_mask : 1; 81 int component_alpha : 1; 82}; 83static const struct acceleration_info accelerated_ops[] = { 84 {PictOpClear, 1, 0}, 85 {PictOpSrc, 1, 0}, 86 {PictOpDst, 1, 0}, 87 {PictOpOver, 1, 0}, 88 {PictOpOverReverse, 1, 0}, 89 {PictOpIn, 1, 0}, 90 {PictOpInReverse, 1, 0}, 91 {PictOpOut, 1, 0}, 92 {PictOpOutReverse, 1, 0}, 93 {PictOpAtop, 1, 0}, 94 {PictOpAtopReverse, 1, 0}, 95 {PictOpXor, 1, 0}, 96 {PictOpAdd, 1, 0}, 97 {PictOpSaturate, 1, 0}, 98}; 99 100static struct xorg_composite_blend 101blend_for_op(int op) 102{ 103 const int num_blends = 104 sizeof(xorg_blends)/sizeof(struct xorg_composite_blend); 105 int i; 106 107 for (i = 0; i < num_blends; ++i) { 108 if (xorg_blends[i].op == op) 109 return xorg_blends[i]; 110 } 111 return xorg_blends[BLEND_OP_OVER]; 112} 113 114static INLINE int 115render_repeat_to_gallium(int mode) 116{ 117 switch(mode) { 118 case RepeatNone: 119 return PIPE_TEX_WRAP_CLAMP; 120 case RepeatNormal: 121 return PIPE_TEX_WRAP_REPEAT; 122 case RepeatReflect: 123 return PIPE_TEX_WRAP_MIRROR_REPEAT; 124 case RepeatPad: 125 return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 126 default: 127 debug_printf("Unsupported repeat mode\n"); 128 } 129 return PIPE_TEX_WRAP_REPEAT; 130} 131 132 133static INLINE void 134setup_vertex0(float vertex[2][4], float x, float y, 135 float color[4]) 136{ 137 vertex[0][0] = x; 138 vertex[0][1] = y; 139 vertex[0][2] = 0.f; /*z*/ 140 vertex[0][3] = 1.f; /*w*/ 141 142 vertex[1][0] = color[0]; /*r*/ 143 vertex[1][1] = color[1]; /*g*/ 144 vertex[1][2] = color[2]; /*b*/ 145 vertex[1][3] = color[3]; /*a*/ 146} 147 148static struct pipe_buffer * 149setup_vertex_data0(struct exa_context *ctx, 150 int srcX, int srcY, int maskX, int maskY, 151 int dstX, int dstY, int width, int height) 152{ 153 float vertices[4][2][4]; 154 155 /* 1st vertex */ 156 setup_vertex0(vertices[0], dstX, dstY, 157 ctx->solid_color); 158 /* 2nd vertex */ 159 setup_vertex0(vertices[1], dstX + width, dstY, 160 ctx->solid_color); 161 /* 3rd vertex */ 162 setup_vertex0(vertices[2], dstX + width, dstY + height, 163 ctx->solid_color); 164 /* 4th vertex */ 165 setup_vertex0(vertices[3], dstX, dstY + height, 166 ctx->solid_color); 167 168 return pipe_user_buffer_create(ctx->pipe->screen, 169 vertices, 170 sizeof(vertices)); 171} 172 173static INLINE void 174setup_vertex1(float vertex[2][4], float x, float y, float s, float t) 175{ 176 vertex[0][0] = x; 177 vertex[0][1] = y; 178 vertex[0][2] = 0.f; /*z*/ 179 vertex[0][3] = 1.f; /*w*/ 180 181 vertex[1][0] = s; /*s*/ 182 vertex[1][1] = t; /*t*/ 183 vertex[1][2] = 0.f; /*r*/ 184 vertex[1][3] = 1.f; /*q*/ 185} 186 187static struct pipe_buffer * 188setup_vertex_data1(struct exa_context *ctx, 189 int srcX, int srcY, int maskX, int maskY, 190 int dstX, int dstY, int width, int height) 191{ 192 float vertices[4][2][4]; 193 float s0, t0, s1, t1; 194 struct pipe_texture *src = ctx->bound_textures[0]; 195 196 s0 = srcX / src->width[0]; 197 s1 = srcX + width / src->width[0]; 198 t0 = srcY / src->height[0]; 199 t1 = srcY + height / src->height[0]; 200 201 /* 1st vertex */ 202 setup_vertex1(vertices[0], dstX, dstY, 203 s0, t0); 204 /* 2nd vertex */ 205 setup_vertex1(vertices[1], dstX + width, dstY, 206 s1, t0); 207 /* 3rd vertex */ 208 setup_vertex1(vertices[2], dstX + width, dstY + height, 209 s1, t1); 210 /* 4th vertex */ 211 setup_vertex1(vertices[3], dstX, dstY + height, 212 s0, t1); 213 214 return pipe_user_buffer_create(ctx->pipe->screen, 215 vertices, 216 sizeof(vertices)); 217} 218 219static struct pipe_buffer * 220setup_vertex_data_tex(struct exa_context *ctx, 221 float x0, float y0, float x1, float y1, 222 float s0, float t0, float s1, float t1, 223 float z) 224{ 225 float vertices[4][2][4]; 226 227 /* 1st vertex */ 228 setup_vertex1(vertices[0], x0, y0, 229 s0, t0); 230 /* 2nd vertex */ 231 setup_vertex1(vertices[1], x1, y0, 232 s1, t0); 233 /* 3rd vertex */ 234 setup_vertex1(vertices[2], x1, y1, 235 s1, t1); 236 /* 4th vertex */ 237 setup_vertex1(vertices[3], x0, y1, 238 s0, t1); 239 240 return pipe_user_buffer_create(ctx->pipe->screen, 241 vertices, 242 sizeof(vertices)); 243} 244 245 246 247static INLINE void 248setup_vertex2(float vertex[3][4], float x, float y, 249 float s0, float t0, float s1, float t1) 250{ 251 vertex[0][0] = x; 252 vertex[0][1] = y; 253 vertex[0][2] = 0.f; /*z*/ 254 vertex[0][3] = 1.f; /*w*/ 255 256 vertex[1][0] = s0; /*s*/ 257 vertex[1][1] = t0; /*t*/ 258 vertex[1][2] = 0.f; /*r*/ 259 vertex[1][3] = 1.f; /*q*/ 260 261 vertex[2][0] = s1; /*s*/ 262 vertex[2][1] = t1; /*t*/ 263 vertex[2][2] = 0.f; /*r*/ 264 vertex[2][3] = 1.f; /*q*/ 265} 266 267static struct pipe_buffer * 268setup_vertex_data2(struct exa_context *ctx, 269 int srcX, int srcY, int maskX, int maskY, 270 int dstX, int dstY, int width, int height) 271{ 272 float vertices[4][3][4]; 273 float st0[4], st1[4]; 274 struct pipe_texture *src = ctx->bound_textures[0]; 275 struct pipe_texture *mask = ctx->bound_textures[0]; 276 277 st0[0] = srcX / src->width[0]; 278 st0[1] = srcY / src->height[0]; 279 st0[2] = srcX + width / src->width[0]; 280 st0[3] = srcY + height / src->height[0]; 281 282 st1[0] = maskX / mask->width[0]; 283 st1[1] = maskY / mask->height[0]; 284 st1[2] = maskX + width / mask->width[0]; 285 st1[3] = maskY + height / mask->height[0]; 286 287 /* 1st vertex */ 288 setup_vertex2(vertices[0], dstX, dstY, 289 st0[0], st0[1], st1[0], st1[1]); 290 /* 2nd vertex */ 291 setup_vertex2(vertices[1], dstX + width, dstY, 292 st0[2], st0[1], st1[2], st1[1]); 293 /* 3rd vertex */ 294 setup_vertex2(vertices[2], dstX + width, dstY + height, 295 st0[2], st0[3], st1[2], st1[3]); 296 /* 4th vertex */ 297 setup_vertex2(vertices[3], dstX, dstY + height, 298 st0[0], st0[3], st1[0], st1[3]); 299 300 return pipe_user_buffer_create(ctx->pipe->screen, 301 vertices, 302 sizeof(vertices)); 303} 304 305boolean xorg_composite_accelerated(int op, 306 PicturePtr pSrcPicture, 307 PicturePtr pMaskPicture, 308 PicturePtr pDstPicture) 309{ 310 unsigned i; 311 unsigned accel_ops_count = 312 sizeof(accelerated_ops)/sizeof(struct acceleration_info); 313 314 315 /*FIXME: currently accel is disabled */ 316 return FALSE; 317 318 if (pSrcPicture) { 319 /* component alpha not supported */ 320 if (pSrcPicture->componentAlpha) 321 return FALSE; 322 /* fills not supported */ 323 if (pSrcPicture->pSourcePict) 324 return FALSE; 325 } 326 327 for (i = 0; i < accel_ops_count; ++i) { 328 if (op == accelerated_ops[i].op) { 329 if (pMaskPicture && !accelerated_ops[i].with_mask) 330 return FALSE; 331 return TRUE; 332 } 333 } 334 return FALSE; 335} 336 337static void 338bind_clip_state(struct exa_context *exa) 339{ 340} 341 342static void 343bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst) 344{ 345 unsigned i; 346 struct pipe_framebuffer_state state; 347 struct pipe_surface *surface = exa_gpu_surface(exa, pDst); 348 memset(&state, 0, sizeof(struct pipe_framebuffer_state)); 349 350 state.width = pDst->tex->width[0]; 351 state.height = pDst->tex->height[0]; 352 353 state.nr_cbufs = 1; 354 state.cbufs[0] = surface; 355 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) 356 state.cbufs[i] = 0; 357 358 /* currently we don't use depth/stencil */ 359 state.zsbuf = 0; 360 361 cso_set_framebuffer(exa->cso, &state); 362} 363 364enum AxisOrientation { 365 Y0_BOTTOM, 366 Y0_TOP 367}; 368 369static void 370set_viewport(struct exa_context *exa, int width, int height, 371 enum AxisOrientation orientation) 372{ 373 struct pipe_viewport_state viewport; 374 float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f; 375 376 viewport.scale[0] = width / 2.f; 377 viewport.scale[1] = height / y_scale; 378 viewport.scale[2] = 1.0; 379 viewport.scale[3] = 1.0; 380 viewport.translate[0] = width / 2.f; 381 viewport.translate[1] = height / 2.f; 382 viewport.translate[2] = 0.0; 383 viewport.translate[3] = 0.0; 384 385 cso_set_viewport(exa->cso, &viewport); 386} 387 388static void 389bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst) 390{ 391 int width = pDst->tex->width[0]; 392 int height = pDst->tex->height[0]; 393 394 debug_printf("Bind viewport (%d, %d)\n", width, height); 395 396 set_viewport(exa, width, height, Y0_TOP); 397} 398 399static void 400bind_blend_state(struct exa_context *exa, int op, 401 PicturePtr pSrcPicture, PicturePtr pMaskPicture) 402{ 403 boolean component_alpha = (pSrcPicture) ? 404 pSrcPicture->componentAlpha : FALSE; 405 struct xorg_composite_blend blend_opt; 406 struct pipe_blend_state blend; 407 408 if (component_alpha) { 409 op = PictOpOver; 410 } 411 blend_opt = blend_for_op(op); 412 413 memset(&blend, 0, sizeof(struct pipe_blend_state)); 414 blend.blend_enable = 1; 415 blend.colormask |= PIPE_MASK_R; 416 blend.colormask |= PIPE_MASK_G; 417 blend.colormask |= PIPE_MASK_B; 418 blend.colormask |= PIPE_MASK_A; 419 420 blend.rgb_src_factor = blend_opt.rgb_src_factor; 421 blend.alpha_src_factor = blend_opt.alpha_src_factor; 422 blend.rgb_dst_factor = blend_opt.rgb_dst_factor; 423 blend.alpha_dst_factor = blend_opt.alpha_dst_factor; 424 425 cso_set_blend(exa->cso, &blend); 426} 427 428static void 429bind_rasterizer_state(struct exa_context *exa) 430{ 431 struct pipe_rasterizer_state raster; 432 memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); 433 raster.gl_rasterization_rules = 1; 434 cso_set_rasterizer(exa->cso, &raster); 435} 436 437static void 438bind_shaders(struct exa_context *exa, int op, 439 PicturePtr pSrcPicture, PicturePtr pMaskPicture) 440{ 441 unsigned vs_traits = 0, fs_traits = 0; 442 struct xorg_shader shader; 443 444 exa->has_solid_color = FALSE; 445 446 if (pSrcPicture) { 447 if (pSrcPicture->pSourcePict) { 448 if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { 449 fs_traits |= FS_SOLID_FILL; 450 vs_traits |= VS_SOLID_FILL; 451 render_pixel_to_float4(pSrcPicture->pFormat, 452 pSrcPicture->pSourcePict->solidFill.color, 453 exa->solid_color); 454 exa->has_solid_color = TRUE; 455 } else { 456 debug_assert("!gradients not supported"); 457 } 458 } else { 459 fs_traits |= FS_COMPOSITE; 460 vs_traits |= VS_COMPOSITE; 461 } 462 } 463 464 if (pMaskPicture) { 465 vs_traits |= VS_MASK; 466 fs_traits |= FS_MASK; 467 } 468 469 shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits); 470 cso_set_vertex_shader_handle(exa->cso, shader.vs); 471 cso_set_fragment_shader_handle(exa->cso, shader.fs); 472} 473 474 475static void 476bind_samplers(struct exa_context *exa, int op, 477 PicturePtr pSrcPicture, PicturePtr pMaskPicture, 478 PicturePtr pDstPicture, 479 struct exa_pixmap_priv *pSrc, 480 struct exa_pixmap_priv *pMask, 481 struct exa_pixmap_priv *pDst) 482{ 483 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 484 struct pipe_sampler_state src_sampler, mask_sampler; 485 486 exa->num_bound_samplers = 0; 487 488 memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); 489 memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); 490 491 if (pSrcPicture && pSrc) { 492 unsigned src_wrap = render_repeat_to_gallium( 493 pSrcPicture->repeatType); 494 src_sampler.wrap_s = src_wrap; 495 src_sampler.wrap_t = src_wrap; 496 src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 497 src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 498 src_sampler.normalized_coords = 1; 499 samplers[0] = &src_sampler; 500 exa->bound_textures[0] = pSrc->tex; 501 ++exa->num_bound_samplers; 502 } 503 504 if (pMaskPicture && pMask) { 505 unsigned mask_wrap = render_repeat_to_gallium( 506 pMaskPicture->repeatType); 507 mask_sampler.wrap_s = mask_wrap; 508 mask_sampler.wrap_t = mask_wrap; 509 mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 510 mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 511 mask_sampler.normalized_coords = 1; 512 samplers[1] = &mask_sampler; 513 exa->bound_textures[1] = pMask->tex; 514 ++exa->num_bound_samplers; 515 } 516 517 cso_set_samplers(exa->cso, exa->num_bound_samplers, 518 (const struct pipe_sampler_state **)samplers); 519 cso_set_sampler_textures(exa->cso, exa->num_bound_samplers, 520 exa->bound_textures); 521} 522 523static void 524setup_vs_constant_buffer(struct exa_context *exa, 525 int width, int height) 526{ 527 const int param_bytes = 8 * sizeof(float); 528 float vs_consts[8] = { 529 2.f/width, 2.f/height, 1, 1, 530 -1, -1, 0, 0 531 }; 532 struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer; 533 534 pipe_buffer_reference(&cbuf->buffer, NULL); 535 cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16, 536 PIPE_BUFFER_USAGE_CONSTANT, 537 param_bytes); 538 539 if (cbuf->buffer) { 540 pipe_buffer_write(exa->pipe->screen, cbuf->buffer, 541 0, param_bytes, vs_consts); 542 } 543 exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf); 544} 545 546 547static void 548setup_fs_constant_buffer(struct exa_context *exa) 549{ 550 const int param_bytes = 4 * sizeof(float); 551 float fs_consts[8] = { 552 0, 0, 0, 1, 553 }; 554 struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer; 555 556 pipe_buffer_reference(&cbuf->buffer, NULL); 557 cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16, 558 PIPE_BUFFER_USAGE_CONSTANT, 559 param_bytes); 560 561 if (cbuf->buffer) { 562 pipe_buffer_write(exa->pipe->screen, cbuf->buffer, 563 0, param_bytes, fs_consts); 564 } 565 exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); 566} 567 568static void 569setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst) 570{ 571 int width = pDst->tex->width[0]; 572 int height = pDst->tex->height[0]; 573 574 setup_vs_constant_buffer(exa, width, height); 575 setup_fs_constant_buffer(exa); 576} 577 578boolean xorg_composite_bind_state(struct exa_context *exa, 579 int op, 580 PicturePtr pSrcPicture, 581 PicturePtr pMaskPicture, 582 PicturePtr pDstPicture, 583 struct exa_pixmap_priv *pSrc, 584 struct exa_pixmap_priv *pMask, 585 struct exa_pixmap_priv *pDst) 586{ 587 bind_framebuffer_state(exa, pDst); 588 bind_viewport_state(exa, pDst); 589 bind_blend_state(exa, op, pSrcPicture, pMaskPicture); 590 bind_rasterizer_state(exa); 591 bind_shaders(exa, op, pSrcPicture, pMaskPicture); 592 bind_samplers(exa, op, pSrcPicture, pMaskPicture, 593 pDstPicture, pSrc, pMask, pDst); 594 bind_clip_state(exa); 595 setup_constant_buffers(exa, pDst); 596 597 return FALSE; 598} 599 600void xorg_composite(struct exa_context *exa, 601 struct exa_pixmap_priv *dst, 602 int srcX, int srcY, int maskX, int maskY, 603 int dstX, int dstY, int width, int height) 604{ 605 struct pipe_context *pipe = exa->pipe; 606 struct pipe_buffer *buf = 0; 607 608 if (exa->num_bound_samplers == 0 ) { /* solid fill */ 609 buf = setup_vertex_data0(exa, 610 srcX, srcY, maskX, maskY, 611 dstX, dstY, width, height); 612 } else if (exa->num_bound_samplers == 1 ) /* src */ 613 buf = setup_vertex_data1(exa, 614 srcX, srcY, maskX, maskY, 615 dstX, dstY, width, height); 616 else if (exa->num_bound_samplers == 2) /* src + mask */ 617 buf = setup_vertex_data2(exa, 618 srcX, srcY, maskX, maskY, 619 dstX, dstY, width, height); 620 else if (exa->num_bound_samplers == 3) { /* src + mask + dst */ 621 debug_assert(!"src/mask/dst not handled right now"); 622#if 0 623 buf = setup_vertex_data2(exa, 624 srcX, srcY, maskX, maskY, 625 dstX, dstY, width, height); 626#endif 627 } 628 629 if (buf) { 630 int num_attribs = 1; /*pos*/ 631 num_attribs += exa->num_bound_samplers; 632 if (exa->has_solid_color) 633 ++num_attribs; 634 635 util_draw_vertex_buffer(pipe, buf, 0, 636 PIPE_PRIM_TRIANGLE_FAN, 637 4, /* verts */ 638 num_attribs); /* attribs/vert */ 639 640 pipe_buffer_reference(&buf, NULL); 641 } 642} 643 644boolean xorg_solid_bind_state(struct exa_context *exa, 645 struct exa_pixmap_priv *pixmap, 646 Pixel fg) 647{ 648 unsigned vs_traits, fs_traits; 649 struct xorg_shader shader; 650 651 pixel_to_float4(fg, exa->solid_color); 652 exa->has_solid_color = TRUE; 653 654 exa->solid_color[3] = 1.f; 655 656 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", 657 (fg >> 24) & 0xff, (fg >> 16) & 0xff, 658 (fg >> 8) & 0xff, (fg >> 0) & 0xff, 659 exa->solid_color[0], exa->solid_color[1], 660 exa->solid_color[2], exa->solid_color[3]); 661 662#if 0 663 exa->solid_color[0] = 1.f; 664 exa->solid_color[1] = 0.f; 665 exa->solid_color[2] = 0.f; 666 exa->solid_color[3] = 1.f; 667#endif 668 669 vs_traits = VS_SOLID_FILL; 670 fs_traits = FS_SOLID_FILL; 671 672 bind_framebuffer_state(exa, pixmap); 673 bind_viewport_state(exa, pixmap); 674 bind_rasterizer_state(exa); 675 bind_blend_state(exa, PictOpSrc, NULL, NULL); 676 setup_constant_buffers(exa, pixmap); 677 bind_clip_state(exa); 678 679 shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits); 680 cso_set_vertex_shader_handle(exa->cso, shader.vs); 681 cso_set_fragment_shader_handle(exa->cso, shader.fs); 682 683 return FALSE; 684} 685 686void xorg_solid(struct exa_context *exa, 687 struct exa_pixmap_priv *pixmap, 688 int x0, int y0, int x1, int y1) 689{ 690 struct pipe_context *pipe = exa->pipe; 691 struct pipe_buffer *buf = 0; 692 float vertices[4][2][4]; 693 694 x0 = 10; y0 = 10; 695 x1 = 300; y1 = 300; 696 697 /* 1st vertex */ 698 setup_vertex0(vertices[0], x0, y0, 699 exa->solid_color); 700 /* 2nd vertex */ 701 setup_vertex0(vertices[1], x1, y0, 702 exa->solid_color); 703 /* 3rd vertex */ 704 setup_vertex0(vertices[2], x1, y1, 705 exa->solid_color); 706 /* 4th vertex */ 707 setup_vertex0(vertices[3], x0, y1, 708 exa->solid_color); 709 710 buf = pipe_user_buffer_create(exa->pipe->screen, 711 vertices, 712 sizeof(vertices)); 713 714 715 if (buf) { 716 debug_printf("Drawing buf is %p\n", buf); 717 util_draw_vertex_buffer(pipe, buf, 0, 718 PIPE_PRIM_TRIANGLE_FAN, 719 4, /* verts */ 720 2); /* attribs/vert */ 721 722 pipe_buffer_reference(&buf, NULL); 723 } 724} 725 726 727static INLINE void shift_rectx(float coords[4], 728 const float *bounds, 729 const float shift) 730{ 731 coords[0] += shift; 732 coords[2] -= shift; 733 if (bounds) { 734 coords[2] = MIN2(coords[2], bounds[2]); 735 /* bound x/y + width/height */ 736 if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { 737 coords[2] = (bounds[0] + bounds[2]) - coords[0]; 738 } 739 } 740} 741 742static INLINE void shift_recty(float coords[4], 743 const float *bounds, 744 const float shift) 745{ 746 coords[1] += shift; 747 coords[3] -= shift; 748 if (bounds) { 749 coords[3] = MIN2(coords[3], bounds[3]); 750 if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { 751 coords[3] = (bounds[1] + bounds[3]) - coords[1]; 752 } 753 } 754} 755 756static INLINE void bound_rect(float coords[4], 757 const float bounds[4], 758 float shift[4]) 759{ 760 /* if outside the bounds */ 761 if (coords[0] > (bounds[0] + bounds[2]) || 762 coords[1] > (bounds[1] + bounds[3]) || 763 (coords[0] + coords[2]) < bounds[0] || 764 (coords[1] + coords[3]) < bounds[1]) { 765 coords[0] = 0.f; 766 coords[1] = 0.f; 767 coords[2] = 0.f; 768 coords[3] = 0.f; 769 shift[0] = 0.f; 770 shift[1] = 0.f; 771 return; 772 } 773 774 /* bound x */ 775 if (coords[0] < bounds[0]) { 776 shift[0] = bounds[0] - coords[0]; 777 coords[2] -= shift[0]; 778 coords[0] = bounds[0]; 779 } else 780 shift[0] = 0.f; 781 782 /* bound y */ 783 if (coords[1] < bounds[1]) { 784 shift[1] = bounds[1] - coords[1]; 785 coords[3] -= shift[1]; 786 coords[1] = bounds[1]; 787 } else 788 shift[1] = 0.f; 789 790 shift[2] = bounds[2] - coords[2]; 791 shift[3] = bounds[3] - coords[3]; 792 /* bound width/height */ 793 coords[2] = MIN2(coords[2], bounds[2]); 794 coords[3] = MIN2(coords[3], bounds[3]); 795 796 /* bound x/y + width/height */ 797 if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { 798 coords[2] = (bounds[0] + bounds[2]) - coords[0]; 799 } 800 if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { 801 coords[3] = (bounds[1] + bounds[3]) - coords[1]; 802 } 803 804 /* if outside the bounds */ 805 if ((coords[0] + coords[2]) < bounds[0] || 806 (coords[1] + coords[3]) < bounds[1]) { 807 coords[0] = 0.f; 808 coords[1] = 0.f; 809 coords[2] = 0.f; 810 coords[3] = 0.f; 811 return; 812 } 813} 814 815static INLINE void sync_size(float *src_loc, float *dst_loc) 816{ 817 src_loc[2] = MIN2(src_loc[2], dst_loc[2]); 818 src_loc[3] = MIN2(src_loc[3], dst_loc[3]); 819 dst_loc[2] = src_loc[2]; 820 dst_loc[3] = src_loc[3]; 821} 822 823 824static void renderer_copy_texture(struct exa_context *exa, 825 struct pipe_texture *src, 826 float sx1, float sy1, 827 float sx2, float sy2, 828 struct pipe_texture *dst, 829 float dx1, float dy1, 830 float dx2, float dy2) 831{ 832 struct pipe_context *pipe = exa->pipe; 833 struct pipe_screen *screen = pipe->screen; 834 struct pipe_buffer *buf; 835 struct pipe_surface *dst_surf = screen->get_tex_surface( 836 screen, dst, 0, 0, 0, 837 PIPE_BUFFER_USAGE_GPU_WRITE); 838 struct pipe_framebuffer_state fb; 839 float s0, t0, s1, t1; 840 struct xorg_shader shader; 841 842 assert(src->width[0] != 0); 843 assert(src->height[0] != 0); 844 assert(dst->width[0] != 0); 845 assert(dst->height[0] != 0); 846 847#if 0 848 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n", 849 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2); 850#endif 851 852#if 1 853 s0 = sx1 / src->width[0]; 854 s1 = sx2 / src->width[0]; 855 t0 = sy1 / src->height[0]; 856 t1 = sy2 / src->height[0]; 857#else 858 s0 = 0; 859 s1 = 1; 860 t0 = 0; 861 t1 = 1; 862#endif 863 864 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D, 865 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 866 867 /* save state (restored below) */ 868 cso_save_blend(exa->cso); 869 cso_save_samplers(exa->cso); 870 cso_save_sampler_textures(exa->cso); 871 cso_save_framebuffer(exa->cso); 872 cso_save_fragment_shader(exa->cso); 873 cso_save_vertex_shader(exa->cso); 874 875 cso_save_viewport(exa->cso); 876 877 878 /* set misc state we care about */ 879 { 880 struct pipe_blend_state blend; 881 memset(&blend, 0, sizeof(blend)); 882 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; 883 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; 884 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 885 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 886 blend.colormask = PIPE_MASK_RGBA; 887 cso_set_blend(exa->cso, &blend); 888 } 889 890 /* sampler */ 891 { 892 struct pipe_sampler_state sampler; 893 memset(&sampler, 0, sizeof(sampler)); 894 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 895 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 896 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 897 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 898 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 899 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 900 sampler.normalized_coords = 1; 901 cso_single_sampler(exa->cso, 0, &sampler); 902 cso_single_sampler_done(exa->cso); 903 } 904 905 set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP); 906 907 /* texture */ 908 cso_set_sampler_textures(exa->cso, 1, &src); 909 910 /* shaders */ 911 shader = xorg_shaders_get(exa->shaders, 912 VS_COMPOSITE, 913 FS_COMPOSITE); 914 cso_set_vertex_shader_handle(exa->cso, shader.vs); 915 cso_set_fragment_shader_handle(exa->cso, shader.fs); 916 917 /* drawing dest */ 918 memset(&fb, 0, sizeof(fb)); 919 fb.width = dst_surf->width; 920 fb.height = dst_surf->height; 921 fb.nr_cbufs = 1; 922 fb.cbufs[0] = dst_surf; 923 { 924 int i; 925 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) 926 fb.cbufs[i] = 0; 927 } 928 cso_set_framebuffer(exa->cso, &fb); 929 930 /* draw quad */ 931 buf = setup_vertex_data_tex(exa, 932 dx1, dy1, 933 dx2, dy2, 934 s0, t0, s1, t1, 935 0.0f); 936 937 if (buf) { 938 util_draw_vertex_buffer(exa->pipe, buf, 0, 939 PIPE_PRIM_TRIANGLE_FAN, 940 4, /* verts */ 941 2); /* attribs/vert */ 942 943 pipe_buffer_reference(&buf, NULL); 944 } 945 946 /* restore state we changed */ 947 cso_restore_blend(exa->cso); 948 cso_restore_samplers(exa->cso); 949 cso_restore_sampler_textures(exa->cso); 950 cso_restore_framebuffer(exa->cso); 951 cso_restore_vertex_shader(exa->cso); 952 cso_restore_fragment_shader(exa->cso); 953 cso_restore_viewport(exa->cso); 954 955 pipe_surface_reference(&dst_surf, NULL); 956} 957 958void xorg_copy_pixmap(struct exa_context *ctx, 959 struct exa_pixmap_priv *dst_priv, int dx, int dy, 960 struct exa_pixmap_priv *src_priv, int sx, int sy, 961 int width, int height) 962{ 963 float dst_loc[4], src_loc[4]; 964 float dst_bounds[4], src_bounds[4]; 965 float src_shift[4], dst_shift[4], shift[4]; 966 struct pipe_texture *dst = dst_priv->tex; 967 struct pipe_texture *src = src_priv->tex; 968 969 dst_loc[0] = dx; 970 dst_loc[1] = dy; 971 dst_loc[2] = width; 972 dst_loc[3] = height; 973 dst_bounds[0] = 0.f; 974 dst_bounds[1] = 0.f; 975 dst_bounds[2] = dst->width[0]; 976 dst_bounds[3] = dst->height[0]; 977 978 src_loc[0] = sx; 979 src_loc[1] = sy; 980 src_loc[2] = width; 981 src_loc[3] = height; 982 src_bounds[0] = 0.f; 983 src_bounds[1] = 0.f; 984 src_bounds[2] = src->width[0]; 985 src_bounds[3] = src->height[0]; 986 987 bound_rect(src_loc, src_bounds, src_shift); 988 bound_rect(dst_loc, dst_bounds, dst_shift); 989 shift[0] = src_shift[0] - dst_shift[0]; 990 shift[1] = src_shift[1] - dst_shift[1]; 991 992 if (shift[0] < 0) 993 shift_rectx(src_loc, src_bounds, -shift[0]); 994 else 995 shift_rectx(dst_loc, dst_bounds, shift[0]); 996 997 if (shift[1] < 0) 998 shift_recty(src_loc, src_bounds, -shift[1]); 999 else 1000 shift_recty(dst_loc, dst_bounds, shift[1]); 1001 1002 sync_size(src_loc, dst_loc); 1003 1004 if (src_loc[2] >= 0 && src_loc[3] >= 0 && 1005 dst_loc[2] >= 0 && dst_loc[3] >= 0) { 1006 renderer_copy_texture(ctx, 1007 src, 1008 src_loc[0], 1009 src_loc[1] + src_loc[3], 1010 src_loc[0] + src_loc[2], 1011 src_loc[1], 1012 dst, 1013 dst_loc[0], 1014 dst_loc[1] + dst_loc[3], 1015 dst_loc[0] + dst_loc[2], 1016 dst_loc[1]); 1017 } 1018} 1019 1020