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