2 #include "xorg_renderer.h"
4 #include "xorg_exa_tgsi.h"
6 #include "cso_cache/cso_context.h"
7 #include "util/u_draw_quad.h"
8 #include "util/u_math.h"
9 #include "util/u_memory.h"
10 #include "util/u_rect.h"
12 #include "pipe/p_inlines.h"
16 #define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
17 #define floatIsZero(x) (floatsEqual((x) + 1, 1))
19 #define NUM_COMPONENTS 4
21 static INLINE boolean
is_affine(float *matrix
)
23 return floatIsZero(matrix
[2]) && floatIsZero(matrix
[5])
24 && floatsEqual(matrix
[8], 1);
26 static INLINE
void map_point(float *mat
, float x
, float y
,
27 float *out_x
, float *out_y
)
35 *out_x
= mat
[0]*x
+ mat
[3]*y
+ mat
[6];
36 *out_y
= mat
[1]*x
+ mat
[4]*y
+ mat
[7];
37 if (!is_affine(mat
)) {
38 float w
= 1/(mat
[2]*x
+ mat
[5]*y
+ mat
[8]);
44 static INLINE
struct pipe_buffer
*
45 renderer_buffer_create(struct xorg_renderer
*r
)
47 struct pipe_buffer
*buf
=
48 pipe_user_buffer_create(r
->pipe
->screen
,
58 renderer_draw(struct xorg_renderer
*r
)
60 struct pipe_context
*pipe
= r
->pipe
;
61 struct pipe_buffer
*buf
= 0;
62 int num_verts
= r
->buffer_size
/(r
->attrs_per_vertex
* NUM_COMPONENTS
);
67 buf
= renderer_buffer_create(r
);
71 util_draw_vertex_buffer(pipe
, buf
, 0,
73 num_verts
, /* verts */
74 r
->attrs_per_vertex
); /* attribs/vert */
76 pipe_buffer_reference(&buf
, NULL
);
81 renderer_draw_conditional(struct xorg_renderer
*r
,
84 if (r
->buffer_size
+ next_batch
>= BUF_SIZE
||
85 (next_batch
== 0 && r
->buffer_size
)) {
91 renderer_init_state(struct xorg_renderer
*r
)
93 struct pipe_depth_stencil_alpha_state dsa
;
94 struct pipe_rasterizer_state raster
;
96 /* set common initial clip state */
97 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
98 cso_set_depth_stencil_alpha(r
->cso
, &dsa
);
101 /* XXX: move to renderer_init_state? */
102 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
103 raster
.gl_rasterization_rules
= 1;
104 cso_set_rasterizer(r
->cso
, &raster
);
110 add_vertex_color(struct xorg_renderer
*r
,
114 float *vertex
= r
->buffer
+ r
->buffer_size
;
118 vertex
[2] = 0.f
; /*z*/
119 vertex
[3] = 1.f
; /*w*/
121 vertex
[4] = color
[0]; /*r*/
122 vertex
[5] = color
[1]; /*g*/
123 vertex
[6] = color
[2]; /*b*/
124 vertex
[7] = color
[3]; /*a*/
130 add_vertex_1tex(struct xorg_renderer
*r
,
131 float x
, float y
, float s
, float t
)
133 float *vertex
= r
->buffer
+ r
->buffer_size
;
137 vertex
[2] = 0.f
; /*z*/
138 vertex
[3] = 1.f
; /*w*/
142 vertex
[6] = 0.f
; /*r*/
143 vertex
[7] = 1.f
; /*q*/
149 add_vertex_data1(struct xorg_renderer
*r
,
150 float srcX
, float srcY
, float dstX
, float dstY
,
151 float width
, float height
,
152 struct pipe_texture
*src
, float *src_matrix
)
154 float s0
, t0
, s1
, t1
, s2
, t2
, s3
, t3
;
155 float pt0
[2], pt1
[2], pt2
[2], pt3
[2];
159 pt1
[0] = (srcX
+ width
);
161 pt2
[0] = (srcX
+ width
);
162 pt2
[1] = (srcY
+ height
);
164 pt3
[1] = (srcY
+ height
);
167 map_point(src_matrix
, pt0
[0], pt0
[1], &pt0
[0], &pt0
[1]);
168 map_point(src_matrix
, pt1
[0], pt1
[1], &pt1
[0], &pt1
[1]);
169 map_point(src_matrix
, pt2
[0], pt2
[1], &pt2
[0], &pt2
[1]);
170 map_point(src_matrix
, pt3
[0], pt3
[1], &pt3
[0], &pt3
[1]);
173 s0
= pt0
[0] / src
->width0
;
174 s1
= pt1
[0] / src
->width0
;
175 s2
= pt2
[0] / src
->width0
;
176 s3
= pt3
[0] / src
->width0
;
177 t0
= pt0
[1] / src
->height0
;
178 t1
= pt1
[1] / src
->height0
;
179 t2
= pt2
[1] / src
->height0
;
180 t3
= pt3
[1] / src
->height0
;
183 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
185 add_vertex_1tex(r
, dstX
+ width
, dstY
, s1
, t1
);
187 add_vertex_1tex(r
, dstX
+ width
, dstY
+ height
, s2
, t2
);
189 add_vertex_1tex(r
, dstX
, dstY
+ height
, s3
, t3
);
194 add_vertex_2tex(struct xorg_renderer
*r
,
196 float s0
, float t0
, float s1
, float t1
)
198 float *vertex
= r
->buffer
+ r
->buffer_size
;
202 vertex
[2] = 0.f
; /*z*/
203 vertex
[3] = 1.f
; /*w*/
205 vertex
[4] = s0
; /*s*/
206 vertex
[5] = t0
; /*t*/
207 vertex
[6] = 0.f
; /*r*/
208 vertex
[7] = 1.f
; /*q*/
210 vertex
[8] = s1
; /*s*/
211 vertex
[9] = t1
; /*t*/
212 vertex
[10] = 0.f
; /*r*/
213 vertex
[11] = 1.f
; /*q*/
215 r
->buffer_size
+= 12;
219 add_vertex_data2(struct xorg_renderer
*r
,
220 float srcX
, float srcY
, float maskX
, float maskY
,
221 float dstX
, float dstY
, float width
, float height
,
222 struct pipe_texture
*src
,
223 struct pipe_texture
*mask
,
224 float *src_matrix
, float *mask_matrix
)
226 float src_s0
, src_t0
, src_s1
, src_t1
;
227 float mask_s0
, mask_t0
, mask_s1
, mask_t1
;
228 float spt0
[2], spt1
[2];
229 float mpt0
[2], mpt1
[2];
233 spt1
[0] = srcX
+ width
;
234 spt1
[1] = srcY
+ height
;
238 mpt1
[0] = maskX
+ width
;
239 mpt1
[1] = maskY
+ height
;
242 map_point(src_matrix
, spt0
[0], spt0
[1], &spt0
[0], &spt0
[1]);
243 map_point(src_matrix
, spt1
[0], spt1
[1], &spt1
[0], &spt1
[1]);
247 map_point(mask_matrix
, mpt0
[0], mpt0
[1], &mpt0
[0], &mpt0
[1]);
248 map_point(mask_matrix
, mpt1
[0], mpt1
[1], &mpt1
[0], &mpt1
[1]);
251 src_s0
= spt0
[0] / src
->width0
;
252 src_t0
= spt0
[1] / src
->height0
;
253 src_s1
= spt1
[0] / src
->width0
;
254 src_t1
= spt1
[1] / src
->height0
;
256 mask_s0
= mpt0
[0] / mask
->width0
;
257 mask_t0
= mpt0
[1] / mask
->height0
;
258 mask_s1
= mpt1
[0] / mask
->width0
;
259 mask_t1
= mpt1
[1] / mask
->height0
;
262 add_vertex_2tex(r
, dstX
, dstY
,
263 src_s0
, src_t0
, mask_s0
, mask_t0
);
265 add_vertex_2tex(r
, dstX
+ width
, dstY
,
266 src_s1
, src_t0
, mask_s1
, mask_t0
);
268 add_vertex_2tex(r
, dstX
+ width
, dstY
+ height
,
269 src_s1
, src_t1
, mask_s1
, mask_t1
);
271 add_vertex_2tex(r
, dstX
, dstY
+ height
,
272 src_s0
, src_t1
, mask_s0
, mask_t1
);
275 static struct pipe_buffer
*
276 setup_vertex_data_yuv(struct xorg_renderer
*r
,
277 float srcX
, float srcY
, float srcW
, float srcH
,
278 float dstX
, float dstY
, float dstW
, float dstH
,
279 struct pipe_texture
**tex
)
281 float s0
, t0
, s1
, t1
;
282 float spt0
[2], spt1
[2];
286 spt1
[0] = srcX
+ srcW
;
287 spt1
[1] = srcY
+ srcH
;
289 s0
= spt0
[0] / tex
[0]->width0
;
290 t0
= spt0
[1] / tex
[0]->height0
;
291 s1
= spt1
[0] / tex
[0]->width0
;
292 t1
= spt1
[1] / tex
[0]->height0
;
295 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
297 add_vertex_1tex(r
, dstX
+ dstW
, dstY
,
300 add_vertex_1tex(r
, dstX
+ dstW
, dstY
+ dstH
,
303 add_vertex_1tex(r
, dstX
, dstY
+ dstH
,
306 return renderer_buffer_create(r
);
311 /* Set up framebuffer, viewport and vertex shader constant buffer
312 * state for a particular destinaton surface. In all our rendering,
313 * these concepts are linked.
315 void renderer_bind_destination(struct xorg_renderer
*r
,
316 struct pipe_surface
*surface
,
321 struct pipe_framebuffer_state fb
;
322 struct pipe_viewport_state viewport
;
324 /* Framebuffer uses actual surface width/height
326 memset(&fb
, 0, sizeof fb
);
327 fb
.width
= surface
->width
;
328 fb
.height
= surface
->height
;
330 fb
.cbufs
[0] = surface
;
333 /* Viewport just touches the bit we're interested in:
335 viewport
.scale
[0] = width
/ 2.f
;
336 viewport
.scale
[1] = height
/ 2.f
;
337 viewport
.scale
[2] = 1.0;
338 viewport
.scale
[3] = 1.0;
339 viewport
.translate
[0] = width
/ 2.f
;
340 viewport
.translate
[1] = height
/ 2.f
;
341 viewport
.translate
[2] = 0.0;
342 viewport
.translate
[3] = 0.0;
344 /* Constant buffer set up to match viewport dimensions:
346 if (r
->fb_width
!= width
||
347 r
->fb_height
!= height
)
349 float vs_consts
[8] = {
350 2.f
/width
, 2.f
/height
, 1, 1,
355 r
->fb_height
= height
;
357 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
358 vs_consts
, sizeof vs_consts
);
361 cso_set_framebuffer(r
->cso
, &fb
);
362 cso_set_viewport(r
->cso
, &viewport
);
366 struct xorg_renderer
* renderer_create(struct pipe_context
*pipe
)
368 struct xorg_renderer
*renderer
= CALLOC_STRUCT(xorg_renderer
);
370 renderer
->pipe
= pipe
;
371 renderer
->cso
= cso_create_context(pipe
);
372 renderer
->shaders
= xorg_shaders_create(renderer
);
374 renderer_init_state(renderer
);
379 void renderer_destroy(struct xorg_renderer
*r
)
381 struct pipe_constant_buffer
*vsbuf
= &r
->vs_const_buffer
;
382 struct pipe_constant_buffer
*fsbuf
= &r
->fs_const_buffer
;
384 if (vsbuf
&& vsbuf
->buffer
)
385 pipe_buffer_reference(&vsbuf
->buffer
, NULL
);
387 if (fsbuf
&& fsbuf
->buffer
)
388 pipe_buffer_reference(&fsbuf
->buffer
, NULL
);
391 xorg_shaders_destroy(r
->shaders
);
396 cso_release_all(r
->cso
);
397 cso_destroy_context(r
->cso
);
406 void renderer_set_constants(struct xorg_renderer
*r
,
411 struct pipe_constant_buffer
*cbuf
=
412 (shader_type
== PIPE_SHADER_VERTEX
) ? &r
->vs_const_buffer
:
415 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
416 cbuf
->buffer
= pipe_buffer_create(r
->pipe
->screen
, 16,
417 PIPE_BUFFER_USAGE_CONSTANT
,
421 pipe_buffer_write(r
->pipe
->screen
, cbuf
->buffer
,
422 0, param_bytes
, params
);
424 r
->pipe
->set_constant_buffer(r
->pipe
, shader_type
, 0, cbuf
);
428 void renderer_copy_prepare(struct xorg_renderer
*r
,
429 struct pipe_surface
*dst_surface
,
430 struct pipe_texture
*src_texture
)
432 struct pipe_context
*pipe
= r
->pipe
;
433 struct pipe_screen
*screen
= pipe
->screen
;
434 struct xorg_shader shader
;
436 assert(screen
->is_format_supported(screen
, dst_surface
->format
,
438 PIPE_TEXTURE_USAGE_RENDER_TARGET
,
442 /* set misc state we care about */
444 struct pipe_blend_state blend
;
445 memset(&blend
, 0, sizeof(blend
));
446 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
447 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
448 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
449 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
450 blend
.colormask
= PIPE_MASK_RGBA
;
451 cso_set_blend(r
->cso
, &blend
);
456 struct pipe_sampler_state sampler
;
457 memset(&sampler
, 0, sizeof(sampler
));
458 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
459 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
460 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
461 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
462 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
463 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
464 sampler
.normalized_coords
= 1;
465 cso_single_sampler(r
->cso
, 0, &sampler
);
466 cso_single_sampler_done(r
->cso
);
469 renderer_bind_destination(r
, dst_surface
,
471 dst_surface
->height
);
474 cso_set_sampler_textures(r
->cso
, 1, &src_texture
);
477 shader
= xorg_shaders_get(r
->shaders
,
480 cso_set_vertex_shader_handle(r
->cso
, shader
.vs
);
481 cso_set_fragment_shader_handle(r
->cso
, shader
.fs
);
484 r
->attrs_per_vertex
= 2;
487 struct pipe_texture
*
488 renderer_clone_texture(struct xorg_renderer
*r
,
489 struct pipe_texture
*src
)
491 enum pipe_format format
;
492 struct pipe_context
*pipe
= r
->pipe
;
493 struct pipe_screen
*screen
= pipe
->screen
;
494 struct pipe_texture
*pt
;
495 struct pipe_texture templ
;
497 if (pipe
->is_texture_referenced(pipe
, src
, 0, 0) &
498 PIPE_REFERENCED_FOR_WRITE
)
499 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
501 /* the coming in texture should already have that invariance */
502 debug_assert(screen
->is_format_supported(screen
, src
->format
,
504 PIPE_TEXTURE_USAGE_SAMPLER
, 0));
506 format
= src
->format
;
508 memset(&templ
, 0, sizeof(templ
));
509 templ
.target
= PIPE_TEXTURE_2D
;
510 templ
.format
= format
;
511 templ
.last_level
= 0;
512 templ
.width0
= src
->width0
;
513 templ
.height0
= src
->height0
;
515 pf_get_block(format
, &templ
.block
);
516 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
518 pt
= screen
->texture_create(screen
, &templ
);
520 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
526 /* copy source framebuffer surface into texture */
527 struct pipe_surface
*ps_read
= screen
->get_tex_surface(
528 screen
, src
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
529 struct pipe_surface
*ps_tex
= screen
->get_tex_surface(
530 screen
, pt
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
531 if (pipe
->surface_copy
) {
532 pipe
->surface_copy(pipe
,
536 0, 0, src
->width0
, src
->height0
);
538 util_surface_copy(pipe
, FALSE
,
542 0, 0, src
->width0
, src
->height0
);
544 pipe_surface_reference(&ps_read
, NULL
);
545 pipe_surface_reference(&ps_tex
, NULL
);
552 void renderer_copy_pixmap(struct xorg_renderer
*r
,
555 int width
, int height
,
559 float s0
, t0
, s1
, t1
;
560 float x0
, y0
, x1
, y1
;
562 <<<<<<< HEAD
:src
/gallium
/state_trackers
/xorg
/xorg_renderer
.c
563 if (r
->pipe
->is_texture_referenced(r
->pipe
, src
, 0, 0) &
564 PIPE_REFERENCED_FOR_WRITE
)
565 r
->pipe
->flush(r
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
573 dst_bounds
[2] = dst
->width0
;
574 dst_bounds
[3] = dst
->height0
;
582 src_bounds
[2] = src
->width0
;
583 src_bounds
[3] = src
->height0
;
585 bound_rect(src_loc
, src_bounds
, src_shift
);
586 bound_rect(dst_loc
, dst_bounds
, dst_shift
);
587 shift
[0] = src_shift
[0] - dst_shift
[0];
588 shift
[1] = src_shift
[1] - dst_shift
[1];
591 shift_rectx(src_loc
, src_bounds
, -shift
[0]);
593 shift_rectx(dst_loc
, dst_bounds
, shift
[0]);
596 shift_recty(src_loc
, src_bounds
, -shift
[1]);
598 shift_recty(dst_loc
, dst_bounds
, shift
[1]);
600 sync_size(src_loc
, dst_loc
);
602 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
603 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
604 struct pipe_texture
*temp_src
= src
;
607 temp_src
= create_sampler_texture(r
, src
);
609 renderer_copy_texture(r
,
613 src_loc
[0] + src_loc
[2],
614 src_loc
[1] + src_loc
[3],
618 dst_loc
[0] + dst_loc
[2],
619 dst_loc
[1] + dst_loc
[3]);
622 pipe_texture_reference(&temp_src
, NULL
);
626 /* XXX: could put the texcoord scaling calculation into the vertex
630 s1
= (sx
+ width
) / src_width
;
631 t0
= sy
/ src_height
;
632 t1
= (sy
+ height
) / src_height
;
640 renderer_draw_conditional(r
, 4*8);
641 add_vertex_1tex(r
, x0
, y0
, s0
, t0
);
642 add_vertex_1tex(r
, x1
, y0
, s1
, t0
);
643 add_vertex_1tex(r
, x1
, y1
, s1
, t1
);
644 add_vertex_1tex(r
, x0
, y1
, s0
, t1
);
645 >>>>>>> origin
/mesa_7_7_branch
:src
/gallium
/state_trackers
/xorg
/xorg_renderer
.c
651 void renderer_draw_yuv(struct xorg_renderer
*r
,
652 int src_x
, int src_y
, int src_w
, int src_h
,
653 int dst_x
, int dst_y
, int dst_w
, int dst_h
,
654 struct pipe_texture
**textures
)
656 struct pipe_context
*pipe
= r
->pipe
;
657 struct pipe_buffer
*buf
= 0;
659 buf
= setup_vertex_data_yuv(r
,
660 src_x
, src_y
, src_w
, src_h
,
661 dst_x
, dst_y
, dst_w
, dst_h
,
665 const int num_attribs
= 2; /*pos + tex coord*/
667 util_draw_vertex_buffer(pipe
, buf
, 0,
670 num_attribs
); /* attribs/vert */
672 pipe_buffer_reference(&buf
, NULL
);
676 void renderer_begin_solid(struct xorg_renderer
*r
)
679 r
->attrs_per_vertex
= 2;
682 void renderer_solid(struct xorg_renderer
*r
,
688 debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
689 x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
691 renderer_draw_conditional(r
, 4 * 8);
694 add_vertex_color(r
, x0
, y0
, color
);
696 add_vertex_color(r
, x1
, y0
, color
);
698 add_vertex_color(r
, x1
, y1
, color
);
700 add_vertex_color(r
, x0
, y1
, color
);
703 void renderer_draw_flush(struct xorg_renderer
*r
)
705 renderer_draw_conditional(r
, 0);
708 void renderer_begin_textures(struct xorg_renderer
*r
,
709 struct pipe_texture
**textures
,
712 r
->attrs_per_vertex
= 1 + num_textures
;
716 void renderer_texture(struct xorg_renderer
*r
,
718 int width
, int height
,
719 struct pipe_texture
**textures
,
727 debug_printf("src_matrix = \n");
728 debug_printf("%f, %f, %f\n", src_matrix
[0], src_matrix
[1], src_matrix
[2]);
729 debug_printf("%f, %f, %f\n", src_matrix
[3], src_matrix
[4], src_matrix
[5]);
730 debug_printf("%f, %f, %f\n", src_matrix
[6], src_matrix
[7], src_matrix
[8]);
733 debug_printf("mask_matrix = \n");
734 debug_printf("%f, %f, %f\n", mask_matrix
[0], mask_matrix
[1], mask_matrix
[2]);
735 debug_printf("%f, %f, %f\n", mask_matrix
[3], mask_matrix
[4], mask_matrix
[5]);
736 debug_printf("%f, %f, %f\n", mask_matrix
[6], mask_matrix
[7], mask_matrix
[8]);
740 switch(r
->attrs_per_vertex
) {
742 renderer_draw_conditional(r
, 4 * 8);
744 pos
[0], pos
[1], /* src */
745 pos
[4], pos
[5], /* dst */
747 textures
[0], src_matrix
);
750 renderer_draw_conditional(r
, 4 * 12);
752 pos
[0], pos
[1], /* src */
753 pos
[2], pos
[3], /* mask */
754 pos
[4], pos
[5], /* dst */
756 textures
[0], textures
[1],
757 src_matrix
, mask_matrix
);
760 debug_assert(!"Unsupported number of textures");