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