xorg_composite.c revision 108273c5ed43b2c54a58900b7bb4528f912e2b1f
1#include "xorg_composite.h" 2 3#include "xorg_renderer.h" 4#include "xorg_exa_tgsi.h" 5 6#include "cso_cache/cso_context.h" 7#include "util/u_draw_quad.h" 8#include "util/u_math.h" 9 10#include "pipe/p_inlines.h" 11 12struct xorg_composite_blend { 13 int op:8; 14 15 unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */ 16 unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ 17 18 unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ 19 unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ 20}; 21 22#define BLEND_OP_OVER 3 23static const struct xorg_composite_blend xorg_blends[] = { 24 { PictOpClear, 25 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO, 26 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, 27 28 { PictOpSrc, 29 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE, 30 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, 31 32 { PictOpDst, 33 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO, 34 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE }, 35 36 { PictOpOver, 37 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE, 38 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 39 40 { PictOpOverReverse, 41 PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, 42 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 43 44 { PictOpIn, 45 PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ONE, 46 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 47 48 { PictOpInReverse, 49 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE, 50 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE }, 51 52 { PictOpOut, 53 PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, 54 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 55 56 { PictOpOutReverse, 57 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE, 58 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 59 60 { PictOpAtop, 61 PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ONE, 62 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 63 64 { PictOpAtopReverse, 65 PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, 66 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, 67 68 { PictOpXor, 69 PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, 70 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_ONE }, 71 72 { PictOpAdd, 73 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE, 74 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE }, 75}; 76 77 78static INLINE void 79pixel_to_float4(Pixel pixel, float *color) 80{ 81 CARD32 r, g, b, a; 82 83 a = (pixel >> 24) & 0xff; 84 r = (pixel >> 16) & 0xff; 85 g = (pixel >> 8) & 0xff; 86 b = (pixel >> 0) & 0xff; 87 color[0] = ((float)r) / 255.; 88 color[1] = ((float)g) / 255.; 89 color[2] = ((float)b) / 255.; 90 color[3] = ((float)a) / 255.; 91} 92 93struct acceleration_info { 94 int op : 16; 95 int with_mask : 1; 96 int component_alpha : 1; 97}; 98static const struct acceleration_info accelerated_ops[] = { 99 {PictOpClear, 1, 0}, 100 {PictOpSrc, 1, 0}, 101 {PictOpDst, 1, 0}, 102 {PictOpOver, 1, 0}, 103 {PictOpOverReverse, 1, 0}, 104 {PictOpIn, 1, 0}, 105 {PictOpInReverse, 1, 0}, 106 {PictOpOut, 1, 0}, 107 {PictOpOutReverse, 1, 0}, 108 {PictOpAtop, 1, 0}, 109 {PictOpAtopReverse, 1, 0}, 110 {PictOpXor, 1, 0}, 111 {PictOpAdd, 1, 0}, 112 {PictOpSaturate, 1, 0}, 113}; 114 115static struct xorg_composite_blend 116blend_for_op(int op) 117{ 118 const int num_blends = 119 sizeof(xorg_blends)/sizeof(struct xorg_composite_blend); 120 int i; 121 122 for (i = 0; i < num_blends; ++i) { 123 if (xorg_blends[i].op == op) 124 return xorg_blends[i]; 125 } 126 return xorg_blends[BLEND_OP_OVER]; 127} 128 129static INLINE int 130render_repeat_to_gallium(int mode) 131{ 132 switch(mode) { 133 case RepeatNone: 134 return PIPE_TEX_WRAP_CLAMP; 135 case RepeatNormal: 136 return PIPE_TEX_WRAP_REPEAT; 137 case RepeatReflect: 138 return PIPE_TEX_WRAP_MIRROR_REPEAT; 139 case RepeatPad: 140 return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 141 default: 142 debug_printf("Unsupported repeat mode\n"); 143 } 144 return PIPE_TEX_WRAP_REPEAT; 145} 146 147boolean xorg_composite_accelerated(int op, 148 PicturePtr pSrcPicture, 149 PicturePtr pMaskPicture, 150 PicturePtr pDstPicture) 151{ 152 ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; 153 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 154 modesettingPtr ms = modesettingPTR(pScrn); 155 unsigned i; 156 unsigned accel_ops_count = 157 sizeof(accelerated_ops)/sizeof(struct acceleration_info); 158 159 if (pSrcPicture->pSourcePict) { 160 if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill) 161 XORG_FALLBACK("gradients not enabled (haven't been well tested)"); 162 } 163 164 for (i = 0; i < accel_ops_count; ++i) { 165 if (op == accelerated_ops[i].op) { 166 /* Check for unsupported component alpha */ 167 if ((pSrcPicture->componentAlpha && 168 !accelerated_ops[i].component_alpha) || 169 (pMaskPicture && 170 (!accelerated_ops[i].with_mask || 171 (pMaskPicture->componentAlpha && 172 !accelerated_ops[i].component_alpha)))) 173 XORG_FALLBACK("component alpha unsupported (PictOpOver=%s(%d)", 174 (accelerated_ops[i].op == PictOpOver) ? "yes" : "no", 175 accelerated_ops[i].op); 176 return TRUE; 177 } 178 } 179 XORG_FALLBACK("unsupported operation"); 180} 181 182static void 183bind_blend_state(struct exa_context *exa, int op, 184 PicturePtr pSrcPicture, PicturePtr pMaskPicture) 185{ 186 struct xorg_composite_blend blend_opt; 187 struct pipe_blend_state blend; 188 189 blend_opt = blend_for_op(op); 190 191 memset(&blend, 0, sizeof(struct pipe_blend_state)); 192 blend.blend_enable = 1; 193 blend.colormask |= PIPE_MASK_RGBA; 194 195 blend.rgb_src_factor = blend_opt.rgb_src_factor; 196 blend.alpha_src_factor = blend_opt.alpha_src_factor; 197 blend.rgb_dst_factor = blend_opt.rgb_dst_factor; 198 blend.alpha_dst_factor = blend_opt.alpha_dst_factor; 199 200 cso_set_blend(exa->renderer->cso, &blend); 201} 202 203 204static void 205bind_shaders(struct exa_context *exa, int op, 206 PicturePtr pSrcPicture, PicturePtr pMaskPicture) 207{ 208 unsigned vs_traits = 0, fs_traits = 0; 209 struct xorg_shader shader; 210 211 exa->has_solid_color = FALSE; 212 213 if (pSrcPicture) { 214 if (pSrcPicture->pSourcePict) { 215 if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { 216 fs_traits |= FS_SOLID_FILL; 217 vs_traits |= VS_SOLID_FILL; 218 debug_assert(pSrcPicture->format == PICT_a8r8g8b8); 219 pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color, 220 exa->solid_color); 221 exa->has_solid_color = TRUE; 222 } else { 223 debug_assert("!gradients not supported"); 224 } 225 } else { 226 fs_traits |= FS_COMPOSITE; 227 vs_traits |= VS_COMPOSITE; 228 } 229 } 230 231 if (pMaskPicture) { 232 vs_traits |= VS_MASK; 233 fs_traits |= FS_MASK; 234 } 235 236 shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); 237 cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); 238 cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); 239} 240 241 242static void 243bind_samplers(struct exa_context *exa, int op, 244 PicturePtr pSrcPicture, PicturePtr pMaskPicture, 245 PicturePtr pDstPicture, 246 struct exa_pixmap_priv *pSrc, 247 struct exa_pixmap_priv *pMask, 248 struct exa_pixmap_priv *pDst) 249{ 250 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 251 struct pipe_sampler_state src_sampler, mask_sampler; 252 253 exa->num_bound_samplers = 0; 254 255 memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); 256 memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); 257 258 if ((pSrc && exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) & 259 PIPE_REFERENCED_FOR_WRITE) || 260 (pMask && exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) & 261 PIPE_REFERENCED_FOR_WRITE)) 262 exa->pipe->flush(exa->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 263 264 if (pSrcPicture && pSrc) { 265 unsigned src_wrap = render_repeat_to_gallium( 266 pSrcPicture->repeatType); 267 src_sampler.wrap_s = src_wrap; 268 src_sampler.wrap_t = src_wrap; 269 src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 270 src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 271 src_sampler.normalized_coords = 1; 272 samplers[0] = &src_sampler; 273 exa->bound_textures[0] = pSrc->tex; 274 ++exa->num_bound_samplers; 275 } 276 277 if (pMaskPicture && pMask) { 278 unsigned mask_wrap = render_repeat_to_gallium( 279 pMaskPicture->repeatType); 280 mask_sampler.wrap_s = mask_wrap; 281 mask_sampler.wrap_t = mask_wrap; 282 mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 283 mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 284 mask_sampler.normalized_coords = 1; 285 samplers[1] = &mask_sampler; 286 exa->bound_textures[1] = pMask->tex; 287 ++exa->num_bound_samplers; 288 } 289 290 cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers, 291 (const struct pipe_sampler_state **)samplers); 292 cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers, 293 exa->bound_textures); 294} 295 296static void 297setup_vs_constant_buffer(struct exa_context *exa, 298 int width, int height) 299{ 300 const int param_bytes = 8 * sizeof(float); 301 float vs_consts[8] = { 302 2.f/width, 2.f/height, 1, 1, 303 -1, -1, 0, 0 304 }; 305 renderer_set_constants(exa->renderer, PIPE_SHADER_VERTEX, 306 vs_consts, param_bytes); 307} 308 309 310static void 311setup_fs_constant_buffer(struct exa_context *exa) 312{ 313 const int param_bytes = 4 * sizeof(float); 314 const float fs_consts[8] = { 315 0, 0, 0, 1, 316 }; 317 renderer_set_constants(exa->renderer, PIPE_SHADER_FRAGMENT, 318 fs_consts, param_bytes); 319} 320 321static void 322setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst) 323{ 324 int width = pDst->tex->width[0]; 325 int height = pDst->tex->height[0]; 326 327 setup_vs_constant_buffer(exa, width, height); 328 setup_fs_constant_buffer(exa); 329} 330 331boolean xorg_composite_bind_state(struct exa_context *exa, 332 int op, 333 PicturePtr pSrcPicture, 334 PicturePtr pMaskPicture, 335 PicturePtr pDstPicture, 336 struct exa_pixmap_priv *pSrc, 337 struct exa_pixmap_priv *pMask, 338 struct exa_pixmap_priv *pDst) 339{ 340 renderer_bind_framebuffer(exa->renderer, pDst); 341 renderer_bind_viewport(exa->renderer, pDst); 342 bind_blend_state(exa, op, pSrcPicture, pMaskPicture); 343 renderer_bind_rasterizer(exa->renderer); 344 bind_shaders(exa, op, pSrcPicture, pMaskPicture); 345 bind_samplers(exa, op, pSrcPicture, pMaskPicture, 346 pDstPicture, pSrc, pMask, pDst); 347 setup_constant_buffers(exa, pDst); 348 349 return TRUE; 350} 351 352void xorg_composite(struct exa_context *exa, 353 struct exa_pixmap_priv *dst, 354 int srcX, int srcY, int maskX, int maskY, 355 int dstX, int dstY, int width, int height) 356{ 357 if (exa->num_bound_samplers == 0 ) { /* solid fill */ 358 renderer_draw_solid_rect(exa->renderer, 359 dstX, dstY, dstX + width, dstY + height, 360 exa->solid_color); 361 } else { 362 int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; 363 renderer_draw_textures(exa->renderer, 364 pos, width, height, 365 exa->bound_textures, 366 exa->num_bound_samplers); 367 } 368} 369 370boolean xorg_solid_bind_state(struct exa_context *exa, 371 struct exa_pixmap_priv *pixmap, 372 Pixel fg) 373{ 374 unsigned vs_traits, fs_traits; 375 struct xorg_shader shader; 376 377 pixel_to_float4(fg, exa->solid_color); 378 exa->has_solid_color = TRUE; 379 380#if 0 381 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", 382 (fg >> 24) & 0xff, (fg >> 16) & 0xff, 383 (fg >> 8) & 0xff, (fg >> 0) & 0xff, 384 exa->solid_color[0], exa->solid_color[1], 385 exa->solid_color[2], exa->solid_color[3]); 386#endif 387 388 vs_traits = VS_SOLID_FILL; 389 fs_traits = FS_SOLID_FILL; 390 391 renderer_bind_framebuffer(exa->renderer, pixmap); 392 renderer_bind_viewport(exa->renderer, pixmap); 393 renderer_bind_rasterizer(exa->renderer); 394 bind_blend_state(exa, PictOpSrc, NULL, NULL); 395 setup_constant_buffers(exa, pixmap); 396 397 shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); 398 cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); 399 cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); 400 401 return TRUE; 402} 403 404void xorg_solid(struct exa_context *exa, 405 struct exa_pixmap_priv *pixmap, 406 int x0, int y0, int x1, int y1) 407{ 408 renderer_draw_solid_rect(exa->renderer, 409 x0, y0, x1, y1, exa->solid_color); 410} 411 412