2 #include "vl_basic_csc.h"
5 #include <pipe/p_context.h>
6 #include <pipe/p_winsys.h>
7 #include <pipe/p_state.h>
8 #include <tgsi/tgsi_parse.h>
9 #include <tgsi/tgsi_build.h>
11 #include "vl_surface.h"
12 #include "vl_shader_build.h"
15 struct vlVertexShaderConsts
17 struct vlVertex4f src_scale
;
18 struct vlVertex4f src_trans
;
21 struct vlFragmentShaderConsts
23 struct vlVertex4f bias
;
31 struct pipe_context
*pipe
;
32 struct pipe_viewport_state viewport
;
33 struct pipe_framebuffer_state framebuffer
;
35 void *vertex_shader
, *fragment_shader
;
36 struct pipe_vertex_buffer vertex_bufs
[2];
37 struct pipe_vertex_element vertex_elems
[2];
38 struct pipe_constant_buffer vs_const_buf
, fs_const_buf
;
41 static int vlResizeFrameBuffer
48 struct vlBasicCSC
*basic_csc
;
49 struct pipe_context
*pipe
;
53 basic_csc
= (struct vlBasicCSC
*)csc
;
54 pipe
= basic_csc
->pipe
;
56 if (basic_csc
->framebuffer
.width
== width
&& basic_csc
->framebuffer
.height
== height
)
59 if (basic_csc
->framebuffer
.cbufs
[0])
60 pipe
->winsys
->surface_release
63 &basic_csc
->framebuffer
.cbufs
[0]
66 basic_csc
->viewport
.scale
[0] = width
;
67 basic_csc
->viewport
.scale
[1] = height
;
68 basic_csc
->viewport
.scale
[2] = 1;
69 basic_csc
->viewport
.scale
[3] = 1;
70 basic_csc
->viewport
.translate
[0] = 0;
71 basic_csc
->viewport
.translate
[1] = 0;
72 basic_csc
->viewport
.translate
[2] = 0;
73 basic_csc
->viewport
.translate
[3] = 0;
75 basic_csc
->framebuffer
.width
= width
;
76 basic_csc
->framebuffer
.height
= height
;
77 basic_csc
->framebuffer
.cbufs
[0] = pipe
->winsys
->surface_alloc(pipe
->winsys
);
78 pipe
->winsys
->surface_alloc_storage
81 basic_csc
->framebuffer
.cbufs
[0],
84 PIPE_FORMAT_A8R8G8B8_UNORM
,
85 /* XXX: SoftPipe doesn't change GPU usage to CPU like it does for textures */
86 PIPE_BUFFER_USAGE_CPU_READ
| PIPE_BUFFER_USAGE_CPU_WRITE
,
98 struct vlBasicCSC
*basic_csc
;
99 struct pipe_context
*pipe
;
103 basic_csc
= (struct vlBasicCSC
*)csc
;
104 pipe
= basic_csc
->pipe
;
106 pipe
->set_framebuffer_state(pipe
, &basic_csc
->framebuffer
);
107 pipe
->set_viewport_state(pipe
, &basic_csc
->viewport
);
108 pipe
->bind_sampler_states(pipe
, 1, (void**)&basic_csc
->sampler
);
109 /* Source texture set in vlPutSurface() */
110 pipe
->bind_vs_state(pipe
, basic_csc
->vertex_shader
);
111 pipe
->bind_fs_state(pipe
, basic_csc
->fragment_shader
);
112 pipe
->set_vertex_buffers(pipe
, 2, basic_csc
->vertex_bufs
);
113 pipe
->set_vertex_elements(pipe
, 2, basic_csc
->vertex_elems
);
114 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &basic_csc
->vs_const_buf
);
115 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &basic_csc
->fs_const_buf
);
120 static int vlPutPictureCSC
123 struct vlSurface
*surface
,
132 enum vlPictureType picture_type
135 struct vlBasicCSC
*basic_csc
;
136 struct pipe_context
*pipe
;
137 struct vlVertexShaderConsts
*vs_consts
;
142 basic_csc
= (struct vlBasicCSC
*)csc
;
143 pipe
= basic_csc
->pipe
;
145 vs_consts
= pipe
->winsys
->buffer_map
148 basic_csc
->vs_const_buf
.buffer
,
149 PIPE_BUFFER_USAGE_CPU_WRITE
152 vs_consts
->src_scale
.x
= srcw
/ (float)surface
->texture
->width
[0];
153 vs_consts
->src_scale
.y
= srch
/ (float)surface
->texture
->height
[0];
154 vs_consts
->src_scale
.z
= 1;
155 vs_consts
->src_scale
.w
= 1;
156 vs_consts
->src_trans
.x
= srcx
/ (float)surface
->texture
->width
[0];
157 vs_consts
->src_trans
.y
= srcy
/ (float)surface
->texture
->height
[0];
158 vs_consts
->src_trans
.z
= 0;
159 vs_consts
->src_trans
.w
= 0;
161 pipe
->winsys
->buffer_unmap(pipe
->winsys
, basic_csc
->vs_const_buf
.buffer
);
163 pipe
->set_sampler_textures(pipe
, 1, &surface
->texture
);
164 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLE_STRIP
, 0, 4);
179 static struct pipe_surface
* vlGetFrameBuffer
184 struct vlBasicCSC
*basic_csc
;
188 basic_csc
= (struct vlBasicCSC
*)csc
;
190 return basic_csc
->framebuffer
.cbufs
[0];
198 struct vlBasicCSC
*basic_csc
;
199 struct pipe_context
*pipe
;
204 basic_csc
= (struct vlBasicCSC
*)csc
;
205 pipe
= basic_csc
->pipe
;
207 if (basic_csc
->framebuffer
.cbufs
[0])
208 pipe
->winsys
->surface_release
211 &basic_csc
->framebuffer
.cbufs
[0]
214 pipe
->delete_sampler_state(pipe
, basic_csc
->sampler
);
215 pipe
->delete_vs_state(pipe
, basic_csc
->vertex_shader
);
216 pipe
->delete_fs_state(pipe
, basic_csc
->fragment_shader
);
218 for (i
= 0; i
< 2; ++i
)
219 pipe
->winsys
->buffer_destroy(pipe
->winsys
, basic_csc
->vertex_bufs
[i
].buffer
);
221 pipe
->winsys
->buffer_destroy(pipe
->winsys
, basic_csc
->vs_const_buf
.buffer
);
222 pipe
->winsys
->buffer_destroy(pipe
->winsys
, basic_csc
->fs_const_buf
.buffer
);
230 * Represents 2 triangles in a strip in normalized coords.
231 * Used to render the surface onto the frame buffer.
233 static const struct vlVertex2f surface_verts
[4] =
242 * Represents texcoords for the above. We can use the position values directly.
243 * TODO: Duplicate these in the shader, no need to create a buffer.
245 static const struct vlVertex2f
*surface_texcoords
= surface_verts
;
248 * Identity color conversion constants, for debugging
250 static const struct vlFragmentShaderConsts identity
=
253 0.0f
, 0.0f
, 0.0f
, 0.0f
256 1.0f
, 0.0f
, 0.0f
, 0.0f
,
257 0.0f
, 1.0f
, 0.0f
, 0.0f
,
258 0.0f
, 0.0f
, 1.0f
, 0.0f
,
259 0.0f
, 0.0f
, 0.0f
, 1.0f
264 * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
265 * Y is in [16,235], Cb and Cr are in [16,240]
266 * R, G, and B are in [16,235]
268 static const struct vlFragmentShaderConsts bt_601
=
271 0.0f
, 0.501960784f
, 0.501960784f
, 0.0f
274 1.0f
, 0.0f
, 1.371f
, 0.0f
,
275 1.0f
, -0.336f
, -0.698f
, 0.0f
,
276 1.0f
, 1.732f
, 0.0f
, 0.0f
,
277 0.0f
, 0.0f
, 0.0f
, 1.0f
282 * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
283 * Y is in [16,235], Cb and Cr are in [16,240]
284 * R, G, and B are in [0,255]
286 static const struct vlFragmentShaderConsts bt_601_full
=
289 0.062745098f
, 0.501960784f
, 0.501960784f
, 0.0f
292 1.164f
, 0.0f
, 1.596f
, 0.0f
,
293 1.164f
, -0.391f
, -0.813f
, 0.0f
,
294 1.164f
, 2.018f
, 0.0f
, 0.0f
,
295 0.0f
, 0.0f
, 0.0f
, 1.0f
300 * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
301 * Y is in [16,235], Cb and Cr are in [16,240]
302 * R, G, and B are in [16,235]
304 static const struct vlFragmentShaderConsts bt_709
=
307 0.0f
, 0.501960784f
, 0.501960784f
, 0.0f
310 1.0f
, 0.0f
, 1.540f
, 0.0f
,
311 1.0f
, -0.183f
, -0.459f
, 0.0f
,
312 1.0f
, 1.816f
, 0.0f
, 0.0f
,
313 0.0f
, 0.0f
, 0.0f
, 1.0f
318 * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
319 * Y is in [16,235], Cb and Cr are in [16,240]
320 * R, G, and B are in [0,255]
322 const struct vlFragmentShaderConsts bt_709_full
=
325 0.062745098f
, 0.501960784f
, 0.501960784f
, 0.0f
328 1.164f
, 0.0f
, 1.793f
, 0.0f
,
329 1.164f
, -0.213f
, -0.534f
, 0.0f
,
330 1.164f
, 2.115f
, 0.0f
, 0.0f
,
331 0.0f
, 0.0f
, 0.0f
, 1.0f
335 static int vlCreateVertexShader
337 struct vlBasicCSC
*csc
340 const unsigned int max_tokens
= 50;
342 struct pipe_context
*pipe
;
343 struct pipe_shader_state vs
;
344 struct tgsi_token
*tokens
;
345 struct tgsi_header
*header
;
347 struct tgsi_full_declaration decl
;
348 struct tgsi_full_instruction inst
;
356 tokens
= (struct tgsi_token
*)malloc(max_tokens
* sizeof(struct tgsi_token
));
359 *(struct tgsi_version
*)&tokens
[0] = tgsi_build_version();
361 header
= (struct tgsi_header
*)&tokens
[1];
362 *header
= tgsi_build_header();
364 *(struct tgsi_processor
*)&tokens
[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX
, header
);
369 * decl i0 ; Vertex pos
370 * decl i1 ; Vertex texcoords
372 for (i
= 0; i
< 2; i
++)
374 decl
= vl_decl_input(i
== 0 ? TGSI_SEMANTIC_POSITION
: TGSI_SEMANTIC_GENERIC
, i
, i
, i
);
375 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
379 * decl c0 ; Scaling vector to scale texcoord rect to source size
380 * decl c1 ; Translation vector to move texcoord rect into position
382 decl
= vl_decl_constants(TGSI_SEMANTIC_GENERIC
, 0, 0, 1);
383 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
386 * decl o0 ; Vertex pos
387 * decl o1 ; Vertex texcoords
389 for (i
= 0; i
< 2; i
++)
391 decl
= vl_decl_output(i
== 0 ? TGSI_SEMANTIC_POSITION
: TGSI_SEMANTIC_GENERIC
, i
, i
, i
);
392 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
396 decl
= vl_decl_temps(0, 0);
397 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
399 /* mov o0, i0 ; Move pos in to pos out */
400 inst
= vl_inst2(TGSI_OPCODE_MOV
, TGSI_FILE_OUTPUT
, 0, TGSI_FILE_INPUT
, 0);
401 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
403 /* mul t0, i1, c0 ; Scale unit texcoord rect to source size */
404 inst
= vl_inst3(TGSI_OPCODE_MUL
, TGSI_FILE_TEMPORARY
, 0, TGSI_FILE_INPUT
, 1, TGSI_FILE_CONSTANT
, 0);
405 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
407 /* add o1, t0, c1 ; Translate texcoord rect into position */
408 inst
= vl_inst3(TGSI_OPCODE_ADD
, TGSI_FILE_OUTPUT
, 1, TGSI_FILE_TEMPORARY
, 0, TGSI_FILE_CONSTANT
, 1);
409 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
413 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
416 csc
->vertex_shader
= pipe
->create_vs_state(pipe
, &vs
);
422 static int vlCreateFragmentShader
424 struct vlBasicCSC
*csc
427 const unsigned int max_tokens
= 50;
429 struct pipe_context
*pipe
;
430 struct pipe_shader_state fs
;
431 struct tgsi_token
*tokens
;
432 struct tgsi_header
*header
;
434 struct tgsi_full_declaration decl
;
435 struct tgsi_full_instruction inst
;
443 tokens
= (struct tgsi_token
*)malloc(max_tokens
* sizeof(struct tgsi_token
));
446 *(struct tgsi_version
*)&tokens
[0] = tgsi_build_version();
448 header
= (struct tgsi_header
*)&tokens
[1];
449 *header
= tgsi_build_header();
451 *(struct tgsi_processor
*)&tokens
[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT
, header
);
455 /* decl i0 ; Texcoords for s0 */
456 decl
= vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC
, 1, 0, 0, TGSI_INTERPOLATE_LINEAR
);
457 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
460 * decl c0 ; Bias vector for CSC
461 * decl c1-c4 ; CSC matrix c1-c4
463 decl
= vl_decl_constants(TGSI_SEMANTIC_GENERIC
, 0, 0, 4);
464 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
466 /* decl o0 ; Fragment color */
467 decl
= vl_decl_output(TGSI_SEMANTIC_COLOR
, 0, 0, 0);
468 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
471 decl
= vl_decl_temps(0, 0);
472 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
474 /* decl s0 ; Sampler for tex containing picture to display */
475 decl
= vl_decl_samplers(0, 0);
476 ti
+= tgsi_build_full_declaration(&decl
, &tokens
[ti
], header
, max_tokens
- ti
);
478 /* tex2d t0, i0, s0 ; Read src pixel */
479 inst
= vl_tex(TGSI_TEXTURE_2D
, TGSI_FILE_TEMPORARY
, 0, TGSI_FILE_INPUT
, 0, TGSI_FILE_SAMPLER
, 0);
480 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
482 /* sub t0, t0, c0 ; Subtract bias vector from pixel */
483 inst
= vl_inst3(TGSI_OPCODE_SUB
, TGSI_FILE_TEMPORARY
, 0, TGSI_FILE_TEMPORARY
, 0, TGSI_FILE_CONSTANT
, 0);
484 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
487 * dp4 o0.x, t0, c1 ; Multiply pixel by the color conversion matrix
490 * dp4 o0.w, t0, c4 ; XXX: Don't need 4th coefficient
492 for (i
= 0; i
< 4; ++i
)
494 inst
= vl_inst3(TGSI_OPCODE_DP4
, TGSI_FILE_OUTPUT
, 0, TGSI_FILE_TEMPORARY
, 0, TGSI_FILE_CONSTANT
, i
+ 1);
495 inst
.FullDstRegisters
[0].DstRegister
.WriteMask
= TGSI_WRITEMASK_X
<< i
;
496 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
501 ti
+= tgsi_build_full_instruction(&inst
, &tokens
[ti
], header
, max_tokens
- ti
);
504 csc
->fragment_shader
= pipe
->create_fs_state(pipe
, &fs
);
510 static int vlCreateDataBufs
512 struct vlBasicCSC
*csc
515 struct pipe_context
*pipe
;
522 Create our vertex buffer and vertex buffer element
523 VB contains 4 vertices that render a quad covering the entire window
524 to display a rendered surface
525 Quad is rendered as a tri strip
527 csc
->vertex_bufs
[0].pitch
= sizeof(struct vlVertex2f
);
528 csc
->vertex_bufs
[0].max_index
= 3;
529 csc
->vertex_bufs
[0].buffer_offset
= 0;
530 csc
->vertex_bufs
[0].buffer
= pipe
->winsys
->buffer_create
534 PIPE_BUFFER_USAGE_VERTEX
,
535 sizeof(struct vlVertex2f
) * 4
540 pipe
->winsys
->buffer_map(pipe
->winsys
, csc
->vertex_bufs
[0].buffer
, PIPE_BUFFER_USAGE_CPU_WRITE
),
542 sizeof(struct vlVertex2f
) * 4
545 pipe
->winsys
->buffer_unmap(pipe
->winsys
, csc
->vertex_bufs
[0].buffer
);
547 csc
->vertex_elems
[0].src_offset
= 0;
548 csc
->vertex_elems
[0].vertex_buffer_index
= 0;
549 csc
->vertex_elems
[0].nr_components
= 2;
550 csc
->vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
553 Create our texcoord buffer and texcoord buffer element
554 Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices
556 csc
->vertex_bufs
[1].pitch
= sizeof(struct vlVertex2f
);
557 csc
->vertex_bufs
[1].max_index
= 3;
558 csc
->vertex_bufs
[1].buffer_offset
= 0;
559 csc
->vertex_bufs
[1].buffer
= pipe
->winsys
->buffer_create
563 PIPE_BUFFER_USAGE_VERTEX
,
564 sizeof(struct vlVertex2f
) * 4
569 pipe
->winsys
->buffer_map(pipe
->winsys
, csc
->vertex_bufs
[1].buffer
, PIPE_BUFFER_USAGE_CPU_WRITE
),
571 sizeof(struct vlVertex2f
) * 4
574 pipe
->winsys
->buffer_unmap(pipe
->winsys
, csc
->vertex_bufs
[1].buffer
);
576 csc
->vertex_elems
[1].src_offset
= 0;
577 csc
->vertex_elems
[1].vertex_buffer_index
= 1;
578 csc
->vertex_elems
[1].nr_components
= 2;
579 csc
->vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
582 Create our vertex shader's constant buffer
583 Const buffer contains scaling and translation vectors
585 csc
->vs_const_buf
.size
= sizeof(struct vlVertexShaderConsts
);
586 csc
->vs_const_buf
.buffer
= pipe
->winsys
->buffer_create
590 PIPE_BUFFER_USAGE_CONSTANT
,
591 csc
->vs_const_buf
.size
595 Create our fragment shader's constant buffer
596 Const buffer contains the color conversion matrix and bias vectors
598 csc
->fs_const_buf
.size
= sizeof(struct vlFragmentShaderConsts
);
599 csc
->fs_const_buf
.buffer
= pipe
->winsys
->buffer_create
603 PIPE_BUFFER_USAGE_CONSTANT
,
604 csc
->fs_const_buf
.size
608 TODO: Refactor this into a seperate function,
609 allow changing the CSC matrix at runtime to switch between regular & full versions
613 pipe
->winsys
->buffer_map(pipe
->winsys
, csc
->fs_const_buf
.buffer
, PIPE_BUFFER_USAGE_CPU_WRITE
),
615 sizeof(struct vlFragmentShaderConsts
)
618 pipe
->winsys
->buffer_unmap(pipe
->winsys
, csc
->fs_const_buf
.buffer
);
625 struct vlBasicCSC
*csc
628 struct pipe_context
*pipe
;
629 struct pipe_sampler_state sampler
;
635 /* Delay creating the FB until vlPutSurface() so we know window size */
636 csc
->framebuffer
.num_cbufs
= 1;
637 csc
->framebuffer
.cbufs
[0] = NULL
;
638 csc
->framebuffer
.zsbuf
= NULL
;
640 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
641 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
642 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
643 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
644 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
645 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
646 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
647 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
648 sampler
.normalized_coords
= 1;
649 /*sampler.prefilter = ;*/
650 /*sampler.shadow_ambient = ;*/
651 /*sampler.lod_bias = ;*/
652 /*sampler.min_lod = ;*/
653 /*sampler.max_lod = ;*/
654 /*sampler.border_color[i] = ;*/
655 /*sampler.max_anisotropy = ;*/
656 csc
->sampler
= pipe
->create_sampler_state(pipe
, &sampler
);
658 vlCreateVertexShader(csc
);
659 vlCreateFragmentShader(csc
);
660 vlCreateDataBufs(csc
);
667 struct pipe_context
*pipe
,
671 struct vlBasicCSC
*basic_csc
;
676 basic_csc
= calloc(1, sizeof(struct vlBasicCSC
));
681 basic_csc
->base
.vlResizeFrameBuffer
= &vlResizeFrameBuffer
;
682 basic_csc
->base
.vlBegin
= &vlBegin
;
683 basic_csc
->base
.vlPutPicture
= &vlPutPictureCSC
;
684 basic_csc
->base
.vlEnd
= &vlEnd
;
685 basic_csc
->base
.vlGetFrameBuffer
= &vlGetFrameBuffer
;
686 basic_csc
->base
.vlDestroy
= &vlDestroy
;
687 basic_csc
->pipe
= pipe
;
691 *csc
= &basic_csc
->base
;