OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // @gyp_namespace(ui_surface) | 5 // @gyp_namespace(ui_surface) |
6 // Compiles into C++ as 'accelerated_surface_transformer_win_hlsl_compiled.h' | 6 // Compiles into C++ as 'accelerated_surface_transformer_win_hlsl_compiled.h' |
7 | 7 |
8 struct Vertex { | 8 struct Vertex { |
9 float4 position : POSITION; | 9 float4 position : POSITION; |
10 float2 texCoord : TEXCOORD0; | 10 float2 texCoord : TEXCOORD0; |
11 }; | 11 }; |
12 | 12 |
13 texture t; | 13 texture t; |
14 sampler s; | 14 sampler s; |
15 | 15 extern uniform float2 kRenderTargetSize : c0; |
16 // @gyp_compile(vs_2_0, vsOneTexture) | 16 |
17 // @gyp_compile(vs_2_0, vsOneTextureFlipY) | |
17 // | 18 // |
18 // Passes a position and texture coordinate to the pixel shader. | 19 // Passes a position and texture coordinate to the pixel shader. |
19 Vertex vsOneTexture(Vertex input) { | 20 Vertex vsOneTextureFlipY(Vertex input) { |
21 input.texCoord.y = 1 - input.texCoord.y; | |
22 input.position.x += -1 / kRenderTargetSize.x; | |
23 input.position.y += 1 / kRenderTargetSize.y; | |
20 return input; | 24 return input; |
21 }; | 25 }; |
22 | 26 |
23 // @gyp_compile(ps_2_0, psOneTexture) | 27 // @gyp_compile(ps_2_0, psOneTexture) |
24 // | 28 // |
25 // Samples a texture at the given texture coordinate and returns the result. | 29 // Samples a texture at the given texture coordinate and returns the result. |
26 float4 psOneTexture(float2 texCoord : TEXCOORD0) : COLOR0 { | 30 float4 psOneTexture(float2 texCoord : TEXCOORD0) : COLOR0 { |
27 return tex2D(s, texCoord); | 31 return tex2D(s, texCoord); |
28 }; | 32 }; |
33 | |
34 // Return |value| rounded up to the nearest multiple of |multiple|. | |
35 float alignTo(float value, float multiple) { | |
36 // |multiple| is usually a compile-time constant; this check allows | |
37 // the compiler to avoid the fmod when possible. | |
38 if (multiple == 1) | |
39 return value; | |
40 | |
41 // Biasing the value provides numeric stability. We expect |value| to | |
42 // be an integer; this prevents 4.001 from being rounded up to 8. | |
43 float biased_value = value - 0.5; | |
44 return biased_value + multiple - fmod(biased_value, multiple); | |
45 } | |
46 | |
47 float4 packForByteOrder(float4 value) { | |
48 return value.bgra; | |
49 } | |
50 | |
51 // Adjust the input vertex to address the correct range of texels. This depends | |
52 // on the value of the shader constant |kRenderTargetSize|, as well as an | |
53 // alignment factor |align| that effectively specifies the footprint of the | |
54 // texel samples done by this shader pass, and is used to correct when that | |
55 // footprint size doesn't align perfectly with the actual input size. | |
56 Vertex adjustForAlignmentAndPacking(Vertex vtx, float2 align) { | |
57 float src_width = kRenderTargetSize.x; | |
58 float src_height = kRenderTargetSize.y; | |
59 | |
60 // Because our caller expects to be sampling |align.x| many pixels from src at | |
61 // a time, if src's width isn't evenly divisible by |align.x|, it is necessary | |
62 // to pretend that the source is slightly bigger than it is. | |
63 float bloated_src_width = alignTo(src_width, align.x); | |
64 float bloated_src_height = alignTo(src_height, align.y); | |
65 | |
66 // When bloated_src_width != src_width, we'll adjust the texture coordinates | |
67 // to sample past the edge of the vtx; clamping will produce extra copies of | |
68 // the last row. | |
69 float texture_x_scale = bloated_src_width / src_width; | |
70 float texture_y_scale = bloated_src_height / src_height; | |
71 | |
72 // Adjust positions so that we're addressing full fragments in the output, per | |
73 // the top-left filling convention. The shifts would be equivalent to | |
74 // 1/dst_width and 1/dst_height, if we were to calculate those explicitly. | |
75 vtx.position.x -= align.x / bloated_src_width; | |
76 vtx.position.y += align.y / bloated_src_height; | |
77 | |
78 // Apply the texture scale | |
79 vtx.texCoord.x *= texture_x_scale; | |
80 vtx.texCoord.y *= texture_y_scale; | |
81 | |
82 return vtx; | |
83 } | |
84 | |
85 /////////////////////////////////////////////////////////////////////// | |
86 // RGB24 to YV12 in two passes; writing two 8888 targets each pass. | |
87 // | |
88 // YV12 is full-resolution luma and half-resolution red/green chroma. | |
miu
2012/12/27 21:40:17
s/green/blue/
ncarter (slow)
2013/01/07 22:49:10
Done.
| |
89 // | |
90 // (original) | |
91 // XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB | |
92 // XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB | |
93 // XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB | |
94 // XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB | |
95 // XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB | |
96 // XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB | |
97 // | | |
98 // | (y plane) (temporary) | |
99 // | YYYY YYYY UVUV UVUV | |
100 // +--> { YYYY YYYY + UVUV UVUV } | |
101 // YYYY YYYY UVUV UVUV | |
102 // First YYYY YYYY UVUV UVUV | |
103 // pass YYYY YYYY UVUV UVUV | |
104 // YYYY YYYY UVUV UVUV | |
105 // | | |
106 // | (u plane) (v plane) | |
107 // Second | UUUU VVVV | |
108 // pass +--> { UUUU + VVVV } | |
109 // UUUU VVVV | |
110 // | |
111 /////////////////////////////////////////////////////////////////////// | |
112 | |
113 // Phase one of RGB24->YV12 conversion: vsFetch4Pixels/psConvertRGBtoY8UV44 | |
114 // | |
115 // @gyp_compile(vs_2_0, vsFetch4Pixels) | |
116 // @gyp_compile(ps_2_0, psConvertRGBtoY8UV44) | |
117 // | |
118 // Writes four source pixels at a time to a full-size Y plane and a half-width | |
119 // interleaved UV plane. After execution, the Y plane is complete but the UV | |
120 // planes still need to be de-interleaved and vertically scaled. | |
121 // | |
122 void vsFetch4Pixels(in Vertex vertex, | |
123 out float4 position : POSITION, | |
124 out float2 texCoord0 : TEXCOORD0, | |
125 out float2 texCoord1 : TEXCOORD1, | |
126 out float2 texCoord2 : TEXCOORD2, | |
127 out float2 texCoord3 : TEXCOORD3) { | |
128 Vertex adjusted = adjustForAlignmentAndPacking(vertex, float2(4, 1)); | |
129 | |
130 // Set up four taps, aligned to texel centers if the src's true size is | |
131 // |kRenderTargetSize|, and doing bilinear interpolation otherwise. | |
132 float2 one_texel_x = float2(1 / kRenderTargetSize.x, 0); | |
133 position = adjusted.position; | |
134 texCoord0 = adjusted.texCoord - 1.5f * one_texel_x; | |
135 texCoord1 = adjusted.texCoord - 0.5f * one_texel_x; | |
136 texCoord2 = adjusted.texCoord + 0.5f * one_texel_x; | |
137 texCoord3 = adjusted.texCoord + 1.5f * one_texel_x; | |
138 }; | |
139 | |
140 struct YV16QuadPixel | |
141 { | |
142 float4 YYYY : COLOR0; | |
143 float4 UUVV : COLOR1; | |
144 }; | |
145 | |
146 // Color conversion constants. | |
147 static const float3x1 rgb_to_y = float3x1( +0.257f, +0.504f, +0.098f ); | |
148 static const float3x1 rgb_to_u = float3x1( -0.148f, -0.291f, +0.439f ); | |
149 static const float3x1 rgb_to_v = float3x1( +0.439f, -0.368f, -0.071f ); | |
150 static const float y_bias = 0.0625f; | |
151 static const float uv_bias = 0.5f; | |
152 | |
153 YV16QuadPixel psConvertRGBtoY8UV44(float2 texCoord0 : TEXCOORD0, | |
154 float2 texCoord1 : TEXCOORD1, | |
155 float2 texCoord2 : TEXCOORD2, | |
156 float2 texCoord3 : TEXCOORD3) { | |
157 // Color conversion constants. | |
158 const float3x1 rgb_to_u_half = rgb_to_u / 2; | |
miu
2012/12/27 21:40:17
Should these be static constants?
ncarter (slow)
2013/01/07 22:49:10
Deleted these; they were cruft.
| |
159 const float3x1 rgb_to_v_half = rgb_to_v / 2; | |
160 | |
161 // Load the four texture samples into a matrix. | |
162 float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, | |
163 tex2D(s, texCoord1).rgb, | |
164 tex2D(s, texCoord2).rgb, | |
165 tex2D(s, texCoord3).rgb); | |
166 | |
167 // RGB -> Y conversion (x4). | |
168 float4 yyyy = mul(rgb_quad_pixel, rgb_to_y) + y_bias; | |
169 | |
170 // Average adjacent texture samples while converting RGB->UV. This is the same | |
171 // as color converting then averaging, but slightly less math. These values | |
172 // will be in the range [-0.439f, +0.439f] and still need to have the bias | |
173 // term applied. | |
174 float2x3 rgb_double_pixel = float2x3(rgb_quad_pixel[0] + rgb_quad_pixel[1], | |
175 rgb_quad_pixel[2] + rgb_quad_pixel[3]); | |
176 float2 uu = mul(rgb_double_pixel, rgb_to_u / 2); | |
miu
2012/12/27 21:40:17
Use rgb_to_u_half here (and rgb_to_v_half in next
ncarter (slow)
2013/01/07 22:49:10
The compiler is able to optimize this appropriatel
| |
177 float2 vv = mul(rgb_double_pixel, rgb_to_v / 2); | |
178 | |
179 // Package the result to account for BGRA byte ordering. | |
180 YV16QuadPixel result; | |
181 result.YYYY = packForByteOrder(yyyy); | |
182 result.UUVV.xyzw = float4(uu, vv) + uv_bias; // Apply uv bias. | |
183 return result; | |
184 }; | |
185 | |
186 // Phase two of RGB24->YV12 conversion: vsFetch2Pixels/psConvertUV44toU2V2 | |
187 // | |
188 // @gyp_compile(vs_2_0, vsFetch2Pixels) | |
189 // @gyp_compile(ps_2_0, psConvertUV44toU2V2) | |
190 // | |
191 // Deals with UV only. Input is interleaved UV pixels, already scaled | |
192 // horizontally, packed two per RGBA texel. Output is two color planes U and V, | |
193 // packed four to a RGBA pixel. | |
194 // | |
195 // Vertical scaling happens via a half-texel offset and bilinear interpolation | |
196 // during texture sampling. | |
197 void vsFetch2Pixels(in Vertex vertex, | |
198 out float4 position : POSITION, | |
199 out float2 texCoord0 : TEXCOORD0, | |
200 out float2 texCoord1 : TEXCOORD1) { | |
201 // We fetch two texels in the horizontal direction, and scale by 2 in the | |
202 // vertical direction. | |
203 Vertex adjusted = adjustForAlignmentAndPacking(vertex, float2(2, 2)); | |
204 | |
205 // Setup the two texture coordinates. No need to adjust texCoord.y; it's | |
206 // already at the mid-way point between the two rows. Horizontally, we'll | |
207 // fetch two texels so that we have enough data to fill our output. | |
208 float2 one_texel_x = float2(1 / kRenderTargetSize.x, 0); | |
209 position = adjusted.position; | |
210 texCoord0 = adjusted.texCoord - 0.5f * one_texel_x; | |
211 texCoord1 = adjusted.texCoord + 0.5f * one_texel_x; | |
212 }; | |
213 | |
214 struct UV8QuadPixel { | |
215 float4 UUUU : COLOR0; | |
216 float4 VVVV : COLOR1; | |
217 }; | |
218 | |
219 UV8QuadPixel psConvertUV44toU2V2(float2 texCoord0 : TEXCOORD0, | |
220 float2 texCoord1 : TEXCOORD1) { | |
221 // We're just sampling two pixels and unswizzling them. There's no need to do | |
222 // vertical scaling with math, since bilinear interpolation in the sampler | |
223 // takes care of that. | |
224 float4 lo_uuvv = tex2D(s, texCoord0); | |
225 float4 hi_uuvv = tex2D(s, texCoord1); | |
226 UV8QuadPixel result; | |
227 result.UUUU = packForByteOrder(float4(lo_uuvv.xy, hi_uuvv.xy)); | |
228 result.VVVV = packForByteOrder(float4(lo_uuvv.zw, hi_uuvv.zw)); | |
229 return result; | |
230 }; | |
231 | |
232 | |
233 /////////////////////////////////////////////////////////////////////// | |
234 // RGB24 to YV12 in three passes, without MRT: one pass per output color plane. | |
235 // vsFetch4Pixels is the common vertex shader for all three passes. | |
236 // | |
237 // Note that this technique will not do full bilinear filtering on its RGB | |
238 // input (you'd get correctly filtered Y, but aliasing in U and V). | |
239 // | |
240 // Pass 1: vsFetch4Pixels + psConvertRGBToY | |
241 // Pass 2: vsFetch4Pixels_Scale2 + psConvertRGBToU | |
242 // Pass 3: vsFetch4Pixels_Scale2 + psConvertRGBToV | |
243 // | |
244 // @gyp_compile(vs_2_0, vsFetch4Pixels_Scale2) | |
245 // @gyp_compile(ps_2_0, psConvertRGBtoY) | |
246 // @gyp_compile(ps_2_0, psConvertRGBtoU) | |
247 // @gyp_compile(ps_2_0, psConvertRGBtoV) | |
248 // | |
249 /////////////////////////////////////////////////////////////////////// | |
250 void vsFetch4Pixels_Scale2(in Vertex vertex, | |
251 out float4 position : POSITION, | |
252 out float2 texCoord0 : TEXCOORD0, | |
253 out float2 texCoord1 : TEXCOORD1, | |
254 out float2 texCoord2 : TEXCOORD2, | |
255 out float2 texCoord3 : TEXCOORD3) { | |
256 Vertex adjusted = adjustForAlignmentAndPacking(vertex, float2(8, 2)); | |
257 | |
258 // Set up four taps, each of which samples a 2x2 texel quad at the midpoint. | |
259 float2 one_texel_x = float2(1 / kRenderTargetSize.x, 0); | |
260 position = adjusted.position; | |
261 texCoord0 = adjusted.texCoord - 3 * one_texel_x; | |
262 texCoord1 = adjusted.texCoord - 1 * one_texel_x; | |
263 texCoord2 = adjusted.texCoord + 1 * one_texel_x; | |
264 texCoord3 = adjusted.texCoord + 3 * one_texel_x; | |
265 }; | |
266 | |
267 // RGB -> Y, four samples at a time. | |
268 float4 psConvertRGBtoY(float2 texCoord0 : TEXCOORD0, | |
269 float2 texCoord1 : TEXCOORD1, | |
270 float2 texCoord2 : TEXCOORD2, | |
271 float2 texCoord3 : TEXCOORD3) : COLOR0 { | |
272 float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, | |
273 tex2D(s, texCoord1).rgb, | |
274 tex2D(s, texCoord2).rgb, | |
275 tex2D(s, texCoord3).rgb); | |
276 return packForByteOrder(mul(rgb_quad_pixel, rgb_to_y) + y_bias); | |
277 } | |
278 | |
279 // RGB -> U, four samples at a time. | |
280 float4 psConvertRGBtoU(float2 texCoord0 : TEXCOORD0, | |
281 float2 texCoord1 : TEXCOORD1, | |
282 float2 texCoord2 : TEXCOORD2, | |
283 float2 texCoord3 : TEXCOORD3) : COLOR0 { | |
284 float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, | |
285 tex2D(s, texCoord1).rgb, | |
286 tex2D(s, texCoord2).rgb, | |
287 tex2D(s, texCoord3).rgb); | |
288 return packForByteOrder(mul(rgb_quad_pixel, rgb_to_u) + uv_bias); | |
289 } | |
290 | |
291 // RGB -> V, four samples at a time. | |
292 float4 psConvertRGBtoV(float2 texCoord0 : TEXCOORD0, | |
293 float2 texCoord1 : TEXCOORD1, | |
294 float2 texCoord2 : TEXCOORD2, | |
295 float2 texCoord3 : TEXCOORD3) : COLOR0 { | |
296 float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, | |
297 tex2D(s, texCoord1).rgb, | |
298 tex2D(s, texCoord2).rgb, | |
299 tex2D(s, texCoord3).rgb); | |
300 return packForByteOrder(mul(rgb_quad_pixel, rgb_to_v) + uv_bias); | |
301 } | |
OLD | NEW |