asm_fill.h revision 213e288e78bf5b0fb0a996cc17dfd959756c2c53
1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.  All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#ifndef ASM_FILL_H
28#define ASM_FILL_H
29
30#include "tgsi/tgsi_ureg.h"
31
32typedef void (* ureg_func)( struct ureg_program *ureg,
33                            struct ureg_dst *out,
34                            struct ureg_src *in,
35                            struct ureg_src *sampler,
36                            struct ureg_dst *temp,
37                            struct ureg_src *constant);
38
39static INLINE void
40solid_fill( struct ureg_program *ureg,
41            struct ureg_dst *out,
42            struct ureg_src *in,
43            struct ureg_src *sampler,
44            struct ureg_dst *temp,
45            struct ureg_src *constant)
46{
47   ureg_MOV(ureg, *out, constant[0]);
48}
49
50static INLINE void
51linear_grad( struct ureg_program *ureg,
52             struct ureg_dst *out,
53             struct ureg_src *in,
54             struct ureg_src *sampler,
55             struct ureg_dst *temp,
56             struct ureg_src *constant)
57{
58
59   ureg_MOV(ureg,
60            ureg_writemask(temp[0], TGSI_WRITEMASK_XY),
61            in[0]);
62   ureg_MOV(ureg,
63            ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
64            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
65   ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
66   ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
67   ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
68   ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
69   ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
70   ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
71   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1]));
72   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
73   ureg_MUL(ureg, temp[0],
74            ureg_scalar(constant[0], TGSI_SWIZZLE_Y),
75            ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_Y));
76   ureg_MAD(ureg, temp[1],
77            ureg_scalar(constant[0], TGSI_SWIZZLE_X),
78            ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_X),
79            ureg_src(temp[0]));
80   ureg_MUL(ureg, temp[2], ureg_src(temp[1]),
81            ureg_scalar(constant[0], TGSI_SWIZZLE_Z));
82   ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]);
83}
84
85static INLINE void
86radial_grad( struct ureg_program *ureg,
87             struct ureg_dst *out,
88             struct ureg_src *in,
89             struct ureg_src *sampler,
90             struct ureg_dst *temp,
91             struct ureg_src *constant)
92{
93
94   ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_XY), in[0]);
95   ureg_MOV(ureg,
96            ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
97            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
98   ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
99   ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
100   ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
101   ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
102   ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
103   ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
104   ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_X), ureg_src(temp[1]));
105   ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
106   ureg_MUL(ureg, temp[0], ureg_scalar(constant[0], TGSI_SWIZZLE_Y),
107            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y));
108   ureg_MAD(ureg, temp[1],
109            ureg_scalar(constant[0], TGSI_SWIZZLE_X),
110            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X), ureg_src(temp[0]));
111   ureg_ADD(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[1]));
112   ureg_MUL(ureg, temp[3],
113            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y),
114            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y));
115   ureg_MAD(ureg, temp[4],
116            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X),
117            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X),
118            ureg_src(temp[3]));
119   ureg_MOV(ureg, temp[4], ureg_negate(ureg_src(temp[4])));
120   ureg_MUL(ureg, temp[2],
121            ureg_scalar(constant[0], TGSI_SWIZZLE_Z),
122            ureg_src(temp[4]));
123   ureg_MUL(ureg, temp[0],
124            ureg_scalar(constant[1], TGSI_SWIZZLE_W),
125            ureg_src(temp[2]));
126   ureg_MUL(ureg, temp[3], ureg_src(temp[1]), ureg_src(temp[1]));
127
128   ureg_SUB(ureg, temp[2], ureg_src(temp[3]), ureg_src(temp[0]));
129   ureg_RSQ(ureg, temp[2], ureg_abs(ureg_src(temp[2])));
130   ureg_RCP(ureg, temp[2], ureg_src(temp[2]));
131   ureg_SUB(ureg, temp[1], ureg_src(temp[2]), ureg_src(temp[1]));
132   ureg_ADD(ureg, temp[0],
133            ureg_scalar(constant[0], TGSI_SWIZZLE_Z),
134            ureg_scalar(constant[0], TGSI_SWIZZLE_Z));
135   ureg_RCP(ureg, temp[0], ureg_src(temp[0]));
136   ureg_MUL(ureg, temp[2], ureg_src(temp[1]), ureg_src(temp[0]));
137   ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]);
138
139}
140
141
142static INLINE void
143pattern( struct ureg_program *ureg,
144         struct ureg_dst     *out,
145         struct ureg_src     *in,
146         struct ureg_src     *sampler,
147         struct ureg_dst     *temp,
148         struct ureg_src     *constant)
149{
150   ureg_MOV(ureg,
151            ureg_writemask(temp[0], TGSI_WRITEMASK_XY),
152            in[0]);
153   ureg_MOV(ureg,
154            ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
155            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
156   ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
157   ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
158   ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
159   ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
160   ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
161   ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
162   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1]));
163   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
164   ureg_RCP(ureg, temp[0],
165            ureg_swizzle(constant[1],
166                         TGSI_SWIZZLE_Z,
167                         TGSI_SWIZZLE_W,
168                         TGSI_SWIZZLE_Z,
169                         TGSI_SWIZZLE_W));
170   ureg_MOV(ureg, temp[1], ureg_src(temp[4]));
171   ureg_MUL(ureg,
172            ureg_writemask(temp[1], TGSI_WRITEMASK_X),
173            ureg_src(temp[1]),
174            ureg_src(temp[0]));
175   ureg_MUL(ureg,
176            ureg_writemask(temp[1], TGSI_WRITEMASK_Y),
177            ureg_src(temp[1]),
178            ureg_src(temp[0]));
179   ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, ureg_src(temp[1]), sampler[0]);
180}
181
182static INLINE void
183mask( struct ureg_program *ureg,
184      struct ureg_dst *out,
185      struct ureg_src *in,
186      struct ureg_src *sampler,
187      struct ureg_dst *temp,
188      struct ureg_src *constant)
189{
190   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[1]);
191   ureg_MUL(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_W),
192            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
193            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
194   ureg_MOV(ureg, *out, ureg_src(temp[0]));
195}
196
197static INLINE void
198image_normal( struct ureg_program *ureg,
199              struct ureg_dst *out,
200              struct ureg_src *in,
201              struct ureg_src *sampler,
202              struct ureg_dst *temp,
203              struct ureg_src *constant)
204{
205   ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, in[1], sampler[3]);
206}
207
208
209static INLINE void
210image_multiply( struct ureg_program *ureg,
211                struct ureg_dst *out,
212                struct ureg_src *in,
213                struct ureg_src *sampler,
214                struct ureg_dst *temp,
215                struct ureg_src *constant)
216{
217   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
218   ureg_MUL(ureg, *out, ureg_src(temp[0]), ureg_src(temp[1]));
219}
220
221
222static INLINE void
223image_stencil( struct ureg_program *ureg,
224               struct ureg_dst *out,
225               struct ureg_src *in,
226               struct ureg_src *sampler,
227               struct ureg_dst *temp,
228               struct ureg_src *constant)
229{
230   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
231   ureg_MUL(ureg, *out, ureg_src(temp[0]), ureg_src(temp[1]));
232}
233
234#define EXTENDED_BLENDER_OVER_FUNC                                      \
235   ureg_SUB(ureg, temp[3],                                              \
236            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),                   \
237            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));            \
238   ureg_SUB(ureg, temp[4],                                              \
239            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),                   \
240            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));            \
241   ureg_MUL(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[3]));       \
242   ureg_MUL(ureg, temp[4], ureg_src(temp[1]), ureg_src(temp[4]));       \
243   ureg_ADD(ureg, temp[3], ureg_src(temp[3]), ureg_src(temp[4]));
244
245
246static INLINE void
247blend_multiply( struct ureg_program *ureg,
248                struct ureg_dst *out,
249                struct ureg_src *in,
250                struct ureg_src *sampler,
251                struct ureg_dst *temp,
252                struct ureg_src *constant)
253{
254   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
255   EXTENDED_BLENDER_OVER_FUNC
256   ureg_MUL(ureg, temp[4], ureg_src(temp[0]), ureg_src(temp[1]));
257   ureg_ADD(ureg, temp[1], ureg_src(temp[4]), ureg_src(temp[3]));
258
259   ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
260            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
261   ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
262            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
263   ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
264            ureg_src(temp[3]), ureg_src(temp[2]));
265
266   ureg_MOV(ureg, *out, ureg_src(temp[1]));
267}
268
269static INLINE void
270blend_screen( struct ureg_program *ureg,
271              struct ureg_dst     *out,
272              struct ureg_src     *in,
273              struct ureg_src     *sampler,
274              struct ureg_dst     *temp,
275              struct ureg_src     *constant)
276{
277   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
278   ureg_ADD(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[1]));
279   ureg_MUL(ureg, temp[2], ureg_src(temp[0]), ureg_src(temp[1]));
280   ureg_SUB(ureg, *out, ureg_src(temp[3]), ureg_src(temp[2]));
281}
282
283static INLINE void
284blend_darken( struct ureg_program *ureg,
285              struct ureg_dst     *out,
286              struct ureg_src     *in,
287              struct ureg_src     *sampler,
288              struct ureg_dst     *temp,
289              struct ureg_src     *constant)
290{
291   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
292   EXTENDED_BLENDER_OVER_FUNC
293   ureg_MUL(ureg, temp[4], ureg_src(temp[0]),
294            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
295   ureg_MUL(ureg, temp[5], ureg_src(temp[1]),
296            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
297   ureg_MIN(ureg, temp[4], ureg_src(temp[4]), ureg_src(temp[5]));
298   ureg_ADD(ureg, temp[1], ureg_src(temp[3]), ureg_src(temp[4]));
299
300   ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
301            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
302   ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
303            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
304   ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
305            ureg_src(temp[3]), ureg_src(temp[2]));
306
307   ureg_MOV(ureg, *out, ureg_src(temp[1]));
308}
309
310static INLINE void
311blend_lighten( struct ureg_program *ureg,
312               struct ureg_dst     *out,
313               struct ureg_src     *in,
314               struct ureg_src     *sampler,
315               struct ureg_dst *temp,
316               struct ureg_src     *constant)
317{
318   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
319   EXTENDED_BLENDER_OVER_FUNC
320   ureg_MUL(ureg, temp[4], ureg_src(temp[0]),
321            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
322   ureg_MUL(ureg, temp[5], ureg_src(temp[1]),
323            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
324   ureg_MAX(ureg, temp[4], ureg_src(temp[4]), ureg_src(temp[5]));
325   ureg_ADD(ureg, temp[1], ureg_src(temp[3]), ureg_src(temp[4]));
326
327   ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
328            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
329   ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
330            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
331   ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
332            ureg_src(temp[3]), ureg_src(temp[2]));
333
334   ureg_MOV(ureg, *out, ureg_src(temp[1]));
335}
336
337static INLINE void
338premultiply( struct ureg_program *ureg,
339                struct ureg_dst *out,
340                struct ureg_src *in,
341                struct ureg_src *sampler,
342                struct ureg_dst *temp,
343                struct ureg_src *constant)
344{
345   ureg_MUL(ureg,
346            ureg_writemask(temp[0], TGSI_WRITEMASK_XYZ),
347            ureg_src(temp[0]),
348            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
349}
350
351static INLINE void
352unpremultiply( struct ureg_program *ureg,
353                struct ureg_dst *out,
354                struct ureg_src *in,
355                struct ureg_src *sampler,
356                struct ureg_dst *temp,
357                struct ureg_src *constant)
358{
359   ureg_TEX(ureg, temp[0], TGSI_TEXTURE_2D, in[0], sampler[1]);
360}
361
362
363static INLINE void
364color_bw( struct ureg_program *ureg,
365                struct ureg_dst *out,
366                struct ureg_src *in,
367                struct ureg_src *sampler,
368                struct ureg_dst *temp,
369                struct ureg_src *constant)
370{
371   ureg_ADD(ureg, temp[1],
372            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),
373            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
374   ureg_RCP(ureg, temp[2], ureg_src(temp[1]));
375   ureg_ADD(ureg, temp[1],
376            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),
377            ureg_src(temp[2]));
378   ureg_ADD(ureg, ureg_writemask(temp[2], TGSI_WRITEMASK_X),
379            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_X),
380            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_Y));
381   ureg_ADD(ureg, ureg_writemask(temp[2], TGSI_WRITEMASK_X),
382            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_Z),
383            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_X));
384   ureg_SGE(ureg,
385            ureg_writemask(temp[0], TGSI_WRITEMASK_XYZ),
386            ureg_scalar(ureg_src(temp[2]), TGSI_SWIZZLE_X),
387            ureg_src(temp[1]));
388  ureg_SGE(ureg,
389           ureg_writemask(temp[0], TGSI_WRITEMASK_W),
390           ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
391           ureg_scalar(ureg_src(temp[2]), TGSI_SWIZZLE_Y));
392  ureg_MOV(ureg, *out, ureg_src(temp[0]));
393}
394
395
396struct shader_asm_info {
397   VGint id;
398   ureg_func func;
399
400   VGboolean needs_position;
401
402   VGint start_const;
403   VGint num_consts;
404
405   VGint start_sampler;
406   VGint num_samplers;
407
408   VGint start_temp;
409   VGint num_temps;
410};
411
412
413/* paint types */
414static const struct shader_asm_info shaders_paint_asm[] = {
415   {VEGA_SOLID_FILL_SHADER, solid_fill,
416    VG_FALSE, 0, 1, 0, 0, 0, 0},
417   {VEGA_LINEAR_GRADIENT_SHADER, linear_grad,
418    VG_TRUE,  0, 5, 0, 1, 0, 5},
419   {VEGA_RADIAL_GRADIENT_SHADER, radial_grad,
420    VG_TRUE,  0, 5, 0, 1, 0, 6},
421   {VEGA_PATTERN_SHADER, pattern,
422    VG_TRUE,  1, 4, 0, 1, 0, 5}
423};
424
425/* image draw modes */
426static const struct shader_asm_info shaders_image_asm[] = {
427   {VEGA_IMAGE_NORMAL_SHADER, image_normal,
428    VG_TRUE,  0, 0, 3, 1, 0, 0},
429   {VEGA_IMAGE_MULTIPLY_SHADER, image_multiply,
430    VG_TRUE,  0, 0, 3, 1, 0, 2},
431   {VEGA_IMAGE_STENCIL_SHADER, image_stencil,
432    VG_TRUE,  0, 0, 3, 1, 0, 2}
433};
434
435static const struct shader_asm_info shaders_mask_asm[] = {
436   {VEGA_MASK_SHADER, mask,
437    VG_TRUE,  0, 0, 1, 1, 0, 2}
438};
439
440/* extra blend modes */
441static const struct shader_asm_info shaders_blend_asm[] = {
442   {VEGA_BLEND_MULTIPLY_SHADER, blend_multiply,
443    VG_TRUE,  1, 1, 2, 1, 0, 5},
444   {VEGA_BLEND_SCREEN_SHADER, blend_screen,
445    VG_TRUE,  0, 0, 2, 1, 0, 4},
446   {VEGA_BLEND_DARKEN_SHADER, blend_darken,
447    VG_TRUE,  1, 1, 2, 1, 0, 6},
448   {VEGA_BLEND_LIGHTEN_SHADER, blend_lighten,
449    VG_TRUE,  1, 1, 2, 1, 0, 6},
450};
451
452/* premultiply */
453static const struct shader_asm_info shaders_premultiply_asm[] = {
454   {VEGA_PREMULTIPLY_SHADER, premultiply,
455    VG_FALSE,  0, 0, 0, 0, 0, 1},
456   {VEGA_UNPREMULTIPLY_SHADER, unpremultiply,
457    VG_FALSE,  0, 0, 0, 0, 0, 1},
458};
459
460/* color transform to black and white */
461static const struct shader_asm_info shaders_bw_asm[] = {
462   {VEGA_BW_SHADER, color_bw,
463    VG_FALSE,  1, 1, 0, 0, 0, 3},
464};
465
466#endif
467