diff options
| author | Younes Manton <younes.m@gmail.com> | 2009-10-01 21:53:17 -0400 | 
|---|---|---|
| committer | Younes Manton <younes.m@gmail.com> | 2009-10-01 22:52:59 -0400 | 
| commit | e00da1476fcdf8e5877fc1e62118080f5c4193f0 (patch) | |
| tree | 2ffc543f2c8dc702267fabc92ea1d186872f13b2 | |
| parent | 81aa5d717bd0098608e9cc292b316293800c7e11 (diff) | |
g3dvl: Color space conv interface & vl impl.
Interface is pipe_video_context::set_csc_matrix().
vl_csc.h defines some helpers to generate CSC matrices based on one of
the color standard and a user defined ProcAmp (brightness, contrast,
saturation, hue).
| -rw-r--r-- | src/gallium/auxiliary/vl/Makefile | 1 | ||||
| -rw-r--r-- | src/gallium/auxiliary/vl/SConscript | 1 | ||||
| -rw-r--r-- | src/gallium/auxiliary/vl/vl_compositor.c | 139 | ||||
| -rw-r--r-- | src/gallium/auxiliary/vl/vl_compositor.h | 2 | ||||
| -rw-r--r-- | src/gallium/auxiliary/vl/vl_csc.c | 179 | ||||
| -rw-r--r-- | src/gallium/auxiliary/vl/vl_csc.h | 26 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_video_context.c | 10 | ||||
| -rw-r--r-- | src/gallium/include/pipe/p_video_context.h | 4 | 
8 files changed, 249 insertions, 113 deletions
diff --git a/src/gallium/auxiliary/vl/Makefile b/src/gallium/auxiliary/vl/Makefile index 71bfb937ad..4314c1e8d6 100644 --- a/src/gallium/auxiliary/vl/Makefile +++ b/src/gallium/auxiliary/vl/Makefile @@ -7,6 +7,7 @@ C_SOURCES = \  	vl_bitstream_parser.c \  	vl_mpeg12_mc_renderer.c \  	vl_compositor.c \ +        vl_csc.c \  	vl_shader_build.c  include ../../Makefile.template diff --git a/src/gallium/auxiliary/vl/SConscript b/src/gallium/auxiliary/vl/SConscript index eb50940c35..aed69f5efe 100644 --- a/src/gallium/auxiliary/vl/SConscript +++ b/src/gallium/auxiliary/vl/SConscript @@ -6,6 +6,7 @@ vl = env.ConvenienceLibrary(  		'vl_bitstream_parser.c',  		'vl_mpeg12_mc_renderer.c',  		'vl_compositor.c', +                'vl_csc.c',  		'vl_shader_build.c',  	]) diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index 6431da6611..5d3458afd2 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -5,6 +5,7 @@  #include <tgsi/tgsi_parse.h>  #include <tgsi/tgsi_build.h>  #include <util/u_memory.h> +#include "vl_csc.h"  #include "vl_shader_build.h"  struct vertex2f @@ -27,7 +28,6 @@ struct vertex_shader_consts  struct fragment_shader_consts  { -   struct vertex4f bias;     float matrix[16];  }; @@ -49,94 +49,6 @@ static const struct vertex2f surface_verts[4] =   */  static const struct vertex2f *surface_texcoords = surface_verts; -/* - * Identity color conversion constants, for debugging - */ -static const struct fragment_shader_consts identity = -{ -   { -      0.0f, 0.0f, 0.0f, 0.0f -   }, -   { -      1.0f, 0.0f, 0.0f, 0.0f, -      0.0f, 1.0f, 0.0f, 0.0f, -      0.0f, 0.0f, 1.0f, 0.0f, -      0.0f, 0.0f, 0.0f, 1.0f -   } -}; - -/* - * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: - * Y is in [16,235], Cb and Cr are in [16,240] - * R, G, and B are in [16,235] - */ -static const struct fragment_shader_consts bt_601 = -{ -   { -      0.0f, 0.501960784f, 0.501960784f,	0.0f -   }, -   { -      1.0f, 0.0f,   1.371f,   0.0f, -      1.0f, -0.336f, -0.698f, 0.0f, -      1.0f, 1.732f, 0.0f,     0.0f, -      0.0f, 0.0f,   0.0f,     1.0f -   } -}; - -/* - * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: - * Y is in [16,235], Cb and Cr are in [16,240] - * R, G, and B are in [0,255] - */ -static const struct fragment_shader_consts bt_601_full = -{ -   { -      0.062745098f, 0.501960784f, 0.501960784f,	0.0f -   }, -   { -      1.164f, 0.0f,    1.596f,  0.0f, -      1.164f, -0.391f, -0.813f, 0.0f, -      1.164f, 2.018f,  0.0f,    0.0f, -      0.0f,   0.0f,    0.0f,    1.0f -   } -}; - -/* - * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: - * Y is in [16,235], Cb and Cr are in [16,240] - * R, G, and B are in [16,235] - */ -static const struct fragment_shader_consts bt_709 = -{ -   { -      0.0f, 0.501960784f, 0.501960784f,	0.0f -   }, -   { -      1.0f, 0.0f,    1.540f,  0.0f, -      1.0f, -0.183f, -0.459f, 0.0f, -      1.0f, 1.816f,  0.0f,    0.0f, -      0.0f, 0.0f,    0.0f,    1.0f -   } -}; - -/* - * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: - * Y is in [16,235], Cb and Cr are in [16,240] - * R, G, and B are in [0,255] - */ -const struct fragment_shader_consts bt_709_full = -{ -   { -      0.062745098f, 0.501960784f, 0.501960784f,	0.0f -   }, -   { -      1.164f, 0.0f,    1.793f,  0.0f, -      1.164f, -0.213f, -0.534f,	0.0f, -      1.164f, 2.115f,  0.0f,    0.0f, -      0.0f,   0.0f,    0.0f,    1.0f -   } -}; -  static void  create_vert_shader(struct vl_compositor *c)  { @@ -245,10 +157,9 @@ create_frag_shader(struct vl_compositor *c)     ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);     /* -    * decl c0             ; Bias vector for CSC -    * decl c1-c4          ; CSC matrix c1-c4 +    * decl c0-c3          ; CSC matrix c0-c3      */ -   decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4); +   decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);     ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);     /* decl o0             ; Fragment color */ @@ -267,17 +178,14 @@ create_frag_shader(struct vl_compositor *c)     inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0);     ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); -   /* sub t0, t0, c0      ; Subtract bias vector from pixel */ -   inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); -   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); -     /* -    * dp4 o0.x, t0, c1    ; Multiply pixel by the color conversion matrix -    * dp4 o0.y, t0, c2 -    * dp4 o0.z, t0, c3 +    * dp4 o0.x, t0, c0    ; Multiply pixel by the color conversion matrix +    * dp4 o0.y, t0, c1 +    * dp4 o0.z, t0, c2 +    * dp4 o0.w, t0, c3      */ -   for (i = 0; i < 3; ++i) { -      inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1); +   for (i = 0; i < 4; ++i) { +      inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i);        inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;        ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);     } @@ -352,6 +260,8 @@ static void cleanup_shaders(struct vl_compositor *c)  static bool  init_buffers(struct vl_compositor *c)  { +   struct fragment_shader_consts fsc; +     assert(c);     /* @@ -438,18 +348,9 @@ init_buffers(struct vl_compositor *c)        sizeof(struct fragment_shader_consts)     ); -   /* -    * TODO: Refactor this into a seperate function, -    * allow changing the CSC matrix at runtime to switch between regular & full versions -    */ -   memcpy -   ( -      pipe_buffer_map(c->pipe->screen, c->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), -      &bt_601_full, -      sizeof(struct fragment_shader_consts) -   ); +   vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, fsc.matrix); -   pipe_buffer_unmap(c->pipe->screen, c->fs_const_buf.buffer); +   vl_compositor_set_csc_matrix(c, fsc.matrix);     return true;  } @@ -588,3 +489,17 @@ void vl_compositor_render(struct vl_compositor          *compositor,     pipe_surface_reference(&compositor->fb_state.cbufs[0], NULL);  } + +void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat) +{ +   assert(compositor); + +   memcpy +   ( +      pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +      mat, +      sizeof(struct fragment_shader_consts) +   ); + +   pipe_buffer_unmap(compositor->pipe->screen, compositor->fs_const_buf.buffer); +} diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h index 19ad66d9c6..975ea00bde 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.h +++ b/src/gallium/auxiliary/vl/vl_compositor.h @@ -44,4 +44,6 @@ void vl_compositor_render(struct vl_compositor          *compositor,                            struct pipe_video_rect        *layer_dst_areas,*/                            struct pipe_fence_handle      **fence); +void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat); +  #endif /* vl_compositor_h */ diff --git a/src/gallium/auxiliary/vl/vl_csc.c b/src/gallium/auxiliary/vl/vl_csc.c new file mode 100644 index 0000000000..828cebe4ed --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_csc.c @@ -0,0 +1,179 @@ +#include "vl_csc.h" +#include <util/u_math.h> +#include <util/u_debug.h> + +/* + * Color space conversion formulas + * + * To convert YCbCr to RGB, + *    vec4  ycbcr, rgb + *    mat44 csc + *    rgb = csc * ycbcr + * + * To calculate the color space conversion matrix csc with ProcAmp adjustments, + *    mat44 csc, cstd, procamp, bias + *    csc = cstd * (procamp * bias) + * + * Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc) + * adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full), + * bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full) + * + * To calculate procamp, + *    mat44 procamp, hue, saturation, brightness, contrast + *    procamp = brightness * (saturation * (contrast * hue)) + * Alternatively, + *    procamp = saturation * (brightness * (contrast * hue)) + * + * contrast + * [ c, 0, 0, 0] + * [ 0, c, 0, 0] + * [ 0, 0, c, 0] + * [ 0, 0, 0, 1] + * + * brightness + * [ 1, 0, 0, b] + * [ 0, 1, 0, 0] + * [ 0, 0, 1, 0] + * [ 0, 0, 0, 1] + * + * saturation + * [ 1, 0, 0, 0] + * [ 0, s, 0, 0] + * [ 0, 0, s, 0] + * [ 0, 0, 0, 1] + * + * hue + * [ 1,       0,      0, 0] + * [ 0,  cos(h), sin(h), 0] + * [ 0, -sin(h), cos(h), 0] + * [ 0,       0,      0, 1] + * + * procamp + * [ c,           0,          0, b] + * [ 0,  c*s*cos(h), c*s*sin(h), 0] + * [ 0, -c*s*sin(h), c*s*cos(h), 0] + * [ 0,           0,          0, 1] + * + * bias + * [ 1, 0, 0,  ybias] + * [ 0, 1, 0, cbbias] + * [ 0, 0, 1, crbias] + * [ 0, 0, 0,      1] + * + * csc + * [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + * [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + * [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + * [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + */ + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +static const float bt_601[16] = +{ +   1.0f,  0.0f,    1.371f, 0.0f, +   1.0f, -0.336f, -0.698f, 0.0f, +   1.0f,  1.732f,  0.0f,   0.0f, +   0.0f,  0.0f,    0.0f,   1.0f +}; + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +static const float bt_601_full[16] = +{ +   1.164f,  0.0f,    1.596f, 0.0f, +   1.164f, -0.391f, -0.813f, 0.0f, +   1.164f,  2.018f,  0.0f,   0.0f, +   0.0f,    0.0f,    0.0f,   1.0f +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +static const float bt_709[16] = +{ +   1.0f,  0.0f,    1.540f, 0.0f, +   1.0f, -0.183f, -0.459f, 0.0f, +   1.0f,  1.816f,  0.0f,   0.0f, +   0.0f,  0.0f,    0.0f,   1.0f +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +static const float bt_709_full[16] = +{ +   1.164f,  0.0f,    1.793f, 0.0f, +   1.164f, -0.213f, -0.534f, 0.0f, +   1.164f,  2.115f,  0.0f,   0.0f, +   0.0f,    0.0f,    0.0f,   1.0f +}; + +static const float identity[16] = +{ +   1.0f, 0.0f, 0.0f, 0.0f, +   0.0f, 1.0f, 0.0f, 0.0f, +   0.0f, 0.0f, 1.0f, 0.0f, +   0.0f, 0.0f, 0.0f, 1.0f +}; + +void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, +                       struct vl_procamp *procamp, +                       bool full_range, +                       float *matrix) +{ +   float ybias = full_range ? -16.0f/255.0f : 0.0f; +   float cbbias = -128.0f/255.0f; +   float crbias = -128.0f/255.0f; +   float c = procamp ? procamp->contrast : 1.0f; +   float s = procamp ? procamp->saturation : 1.0f; +   float b = procamp ? procamp->brightness : 0.0f; +   float h = procamp ? procamp->hue : 0.0f; +   const float *cstd; + +   assert(matrix); + +   switch (cs) { +      case VL_CSC_COLOR_STANDARD_BT_601: +         cstd = full_range ? &bt_601_full[0] : &bt_601[0]; +         break; +      case VL_CSC_COLOR_STANDARD_BT_709: +         cstd = full_range ? &bt_709_full[0] : &bt_709[0]; +         break; +      case VL_CSC_COLOR_STANDARD_IDENTITY: +      default: +         assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY); +         memcpy(matrix, &identity[0], sizeof(float) * 16); +         return; +   } + +   matrix[ 0] = c*cstd[ 0]; +   matrix[ 1] = c*cstd[ 1]*s*cosf(h) - c*cstd[ 2]*s*sinf(h); +   matrix[ 2] = c*cstd[ 2]*s*cosf(h) + c*cstd[ 1]*s*sinf(h); +   matrix[ 3] = cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 2]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h)); + +   matrix[ 4] = c*cstd[ 4]; +   matrix[ 5] = c*cstd[ 5]*s*cosf(h) - c*cstd[ 6]*s*sinf(h); +   matrix[ 6] = c*cstd[ 6]*s*cosf(h) + c*cstd[ 5]*s*sinf(h); +   matrix[ 7] = cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 6]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h)); + +   matrix[ 8] = c*cstd[ 8]; +   matrix[ 9] = c*cstd[ 9]*s*cosf(h) - c*cstd[10]*s*sinf(h); +   matrix[10] = c*cstd[10]*s*cosf(h) + c*cstd[ 9]*s*sinf(h); +   matrix[11] = cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[10]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h)); + +   matrix[12] = c*cstd[12]; +   matrix[13] = c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h); +   matrix[14] = c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h); +   matrix[15] = cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h)); +} diff --git a/src/gallium/auxiliary/vl/vl_csc.h b/src/gallium/auxiliary/vl/vl_csc.h new file mode 100644 index 0000000000..c3b87d279c --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_csc.h @@ -0,0 +1,26 @@ +#ifndef vl_csc_h +#define vl_csc_h + +#include <pipe/p_compiler.h> + +struct vl_procamp +{ +   float brightness; +   float contrast; +   float saturation; +   float hue; +}; + +enum VL_CSC_COLOR_STANDARD +{ +   VL_CSC_COLOR_STANDARD_IDENTITY, +   VL_CSC_COLOR_STANDARD_BT_601, +   VL_CSC_COLOR_STANDARD_BT_709 +}; + +void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, +                       struct vl_procamp *procamp, +                       bool full_range, +                       float *matrix); + +#endif /* vl_csc_h */ diff --git a/src/gallium/drivers/softpipe/sp_video_context.c b/src/gallium/drivers/softpipe/sp_video_context.c index 7e9136d8e0..00b4b7d560 100644 --- a/src/gallium/drivers/softpipe/sp_video_context.c +++ b/src/gallium/drivers/softpipe/sp_video_context.c @@ -109,6 +109,15 @@ sp_mpeg12_set_decode_target(struct pipe_video_context *vpipe,     pipe_video_surface_reference(&ctx->decode_target, dt);  } +static void sp_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe, const float *mat) +{ +   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + +   assert(vpipe); + +   vl_compositor_set_csc_matrix(&ctx->compositor, mat); +} +  static bool  init_pipe_state(struct sp_mpeg12_context *ctx)  { @@ -211,6 +220,7 @@ sp_mpeg12_create(struct pipe_screen *screen, enum pipe_video_profile profile,     ctx->base.clear_surface = sp_mpeg12_clear_surface;     ctx->base.render_picture = sp_mpeg12_render_picture;     ctx->base.set_decode_target = sp_mpeg12_set_decode_target; +   ctx->base.set_csc_matrix = sp_mpeg12_set_csc_matrix;     ctx->pipe = softpipe_create(screen);     if (!ctx->pipe) { diff --git a/src/gallium/include/pipe/p_video_context.h b/src/gallium/include/pipe/p_video_context.h index 937705ac50..4d125fa4d5 100644 --- a/src/gallium/include/pipe/p_video_context.h +++ b/src/gallium/include/pipe/p_video_context.h @@ -80,7 +80,9 @@ struct pipe_video_context     void (*set_decode_target)(struct pipe_video_context *vpipe,                               struct pipe_video_surface *dt); -   /* TODO: Interface for CSC matrix, scaling modes, post-processing, etc. */ +   void (*set_csc_matrix)(struct pipe_video_context *vpipe, const float *mat); + +   /* TODO: Interface for scaling modes, post-processing, etc. */     /*@}*/  };  | 
