1/*
2 * Copyright 2009 Joakim Sindholt <opensource@zhasha.com>
3 *                Corbin Simpson <MostAwesomeDude@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24#ifndef R300_STATE_INLINES_H
25#define R300_STATE_INLINES_H
26
27#include "draw/draw_vertex.h"
28#include "pipe/p_format.h"
29#include "util/u_format.h"
30#include "r300_reg.h"
31#include <stdio.h>
32
33/* Some maths. These should probably find their way to u_math, if needed. */
34
35static inline int pack_float_16_6x(float f) {
36    return ((int)(f * 6.0) & 0xffff);
37}
38
39/* Blend state. */
40
41static inline uint32_t r300_translate_blend_function(int blend_func,
42                                                     boolean clamp)
43{
44    switch (blend_func) {
45    case PIPE_BLEND_ADD:
46        return clamp ? R300_COMB_FCN_ADD_CLAMP : R300_COMB_FCN_ADD_NOCLAMP;
47    case PIPE_BLEND_SUBTRACT:
48        return clamp ? R300_COMB_FCN_SUB_CLAMP : R300_COMB_FCN_SUB_NOCLAMP;
49    case PIPE_BLEND_REVERSE_SUBTRACT:
50        return clamp ? R300_COMB_FCN_RSUB_CLAMP : R300_COMB_FCN_RSUB_NOCLAMP;
51    case PIPE_BLEND_MIN:
52        return R300_COMB_FCN_MIN;
53    case PIPE_BLEND_MAX:
54        return R300_COMB_FCN_MAX;
55    default:
56        fprintf(stderr, "r300: Unknown blend function %d\n", blend_func);
57        assert(0);
58        break;
59    }
60    return 0;
61}
62
63static inline uint32_t r300_translate_blend_factor(int blend_fact)
64{
65    switch (blend_fact) {
66        case PIPE_BLENDFACTOR_ONE:
67            return R300_BLEND_GL_ONE;
68        case PIPE_BLENDFACTOR_SRC_COLOR:
69            return R300_BLEND_GL_SRC_COLOR;
70        case PIPE_BLENDFACTOR_SRC_ALPHA:
71            return R300_BLEND_GL_SRC_ALPHA;
72        case PIPE_BLENDFACTOR_DST_ALPHA:
73            return R300_BLEND_GL_DST_ALPHA;
74        case PIPE_BLENDFACTOR_DST_COLOR:
75            return R300_BLEND_GL_DST_COLOR;
76        case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
77            return R300_BLEND_GL_SRC_ALPHA_SATURATE;
78        case PIPE_BLENDFACTOR_CONST_COLOR:
79            return R300_BLEND_GL_CONST_COLOR;
80        case PIPE_BLENDFACTOR_CONST_ALPHA:
81            return R300_BLEND_GL_CONST_ALPHA;
82        case PIPE_BLENDFACTOR_ZERO:
83            return R300_BLEND_GL_ZERO;
84        case PIPE_BLENDFACTOR_INV_SRC_COLOR:
85            return R300_BLEND_GL_ONE_MINUS_SRC_COLOR;
86        case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
87            return R300_BLEND_GL_ONE_MINUS_SRC_ALPHA;
88        case PIPE_BLENDFACTOR_INV_DST_ALPHA:
89            return R300_BLEND_GL_ONE_MINUS_DST_ALPHA;
90        case PIPE_BLENDFACTOR_INV_DST_COLOR:
91            return R300_BLEND_GL_ONE_MINUS_DST_COLOR;
92        case PIPE_BLENDFACTOR_INV_CONST_COLOR:
93            return R300_BLEND_GL_ONE_MINUS_CONST_COLOR;
94        case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
95            return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA;
96
97        case PIPE_BLENDFACTOR_SRC1_COLOR:
98        case PIPE_BLENDFACTOR_SRC1_ALPHA:
99        case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
100        case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
101            fprintf(stderr, "r300: Implementation error: "
102                "Bad blend factor %d not supported!\n", blend_fact);
103            assert(0);
104            break;
105
106        default:
107            fprintf(stderr, "r300: Unknown blend factor %d\n", blend_fact);
108            assert(0);
109            break;
110    }
111    return 0;
112}
113
114/* DSA state. */
115
116static inline uint32_t r300_translate_depth_stencil_function(int zs_func)
117{
118    switch (zs_func) {
119        case PIPE_FUNC_NEVER:
120            return R300_ZS_NEVER;
121        case PIPE_FUNC_LESS:
122            return R300_ZS_LESS;
123        case PIPE_FUNC_EQUAL:
124            return R300_ZS_EQUAL;
125        case PIPE_FUNC_LEQUAL:
126            return R300_ZS_LEQUAL;
127        case PIPE_FUNC_GREATER:
128            return R300_ZS_GREATER;
129        case PIPE_FUNC_NOTEQUAL:
130            return R300_ZS_NOTEQUAL;
131        case PIPE_FUNC_GEQUAL:
132            return R300_ZS_GEQUAL;
133        case PIPE_FUNC_ALWAYS:
134            return R300_ZS_ALWAYS;
135        default:
136            fprintf(stderr, "r300: Unknown depth/stencil function %d\n",
137                zs_func);
138            assert(0);
139            break;
140    }
141    return 0;
142}
143
144static inline uint32_t r300_translate_stencil_op(int s_op)
145{
146    switch (s_op) {
147        case PIPE_STENCIL_OP_KEEP:
148            return R300_ZS_KEEP;
149        case PIPE_STENCIL_OP_ZERO:
150            return R300_ZS_ZERO;
151        case PIPE_STENCIL_OP_REPLACE:
152            return R300_ZS_REPLACE;
153        case PIPE_STENCIL_OP_INCR:
154            return R300_ZS_INCR;
155        case PIPE_STENCIL_OP_DECR:
156            return R300_ZS_DECR;
157        case PIPE_STENCIL_OP_INCR_WRAP:
158            return R300_ZS_INCR_WRAP;
159        case PIPE_STENCIL_OP_DECR_WRAP:
160            return R300_ZS_DECR_WRAP;
161        case PIPE_STENCIL_OP_INVERT:
162            return R300_ZS_INVERT;
163        default:
164            fprintf(stderr, "r300: Unknown stencil op %d", s_op);
165            assert(0);
166            break;
167    }
168    return 0;
169}
170
171static inline uint32_t r300_translate_alpha_function(int alpha_func)
172{
173    switch (alpha_func) {
174        case PIPE_FUNC_NEVER:
175            return R300_FG_ALPHA_FUNC_NEVER;
176        case PIPE_FUNC_LESS:
177            return R300_FG_ALPHA_FUNC_LESS;
178        case PIPE_FUNC_EQUAL:
179            return R300_FG_ALPHA_FUNC_EQUAL;
180        case PIPE_FUNC_LEQUAL:
181            return R300_FG_ALPHA_FUNC_LE;
182        case PIPE_FUNC_GREATER:
183            return R300_FG_ALPHA_FUNC_GREATER;
184        case PIPE_FUNC_NOTEQUAL:
185            return R300_FG_ALPHA_FUNC_NOTEQUAL;
186        case PIPE_FUNC_GEQUAL:
187            return R300_FG_ALPHA_FUNC_GE;
188        case PIPE_FUNC_ALWAYS:
189            return R300_FG_ALPHA_FUNC_ALWAYS;
190        default:
191            fprintf(stderr, "r300: Unknown alpha function %d", alpha_func);
192            assert(0);
193            break;
194    }
195    return 0;
196}
197
198static inline uint32_t
199r300_translate_polygon_mode_front(unsigned mode) {
200    switch (mode)
201    {
202        case PIPE_POLYGON_MODE_FILL:
203            return R300_GA_POLY_MODE_FRONT_PTYPE_TRI;
204        case PIPE_POLYGON_MODE_LINE:
205            return R300_GA_POLY_MODE_FRONT_PTYPE_LINE;
206        case PIPE_POLYGON_MODE_POINT:
207            return R300_GA_POLY_MODE_FRONT_PTYPE_POINT;
208
209        default:
210            fprintf(stderr, "r300: Bad polygon mode %i in %s\n", mode,
211                __FUNCTION__);
212            return R300_GA_POLY_MODE_FRONT_PTYPE_TRI;
213    }
214}
215
216static inline uint32_t
217r300_translate_polygon_mode_back(unsigned mode) {
218    switch (mode)
219    {
220        case PIPE_POLYGON_MODE_FILL:
221            return R300_GA_POLY_MODE_BACK_PTYPE_TRI;
222        case PIPE_POLYGON_MODE_LINE:
223            return R300_GA_POLY_MODE_BACK_PTYPE_LINE;
224        case PIPE_POLYGON_MODE_POINT:
225            return R300_GA_POLY_MODE_BACK_PTYPE_POINT;
226
227        default:
228            fprintf(stderr, "r300: Bad polygon mode %i in %s\n", mode,
229                __FUNCTION__);
230            return R300_GA_POLY_MODE_BACK_PTYPE_TRI;
231    }
232}
233
234/* Texture sampler state. */
235
236static inline uint32_t r300_translate_wrap(int wrap)
237{
238    switch (wrap) {
239        case PIPE_TEX_WRAP_REPEAT:
240            return R300_TX_REPEAT;
241        case PIPE_TEX_WRAP_CLAMP:
242            return R300_TX_CLAMP;
243        case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
244            return R300_TX_CLAMP_TO_EDGE;
245        case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
246            return R300_TX_CLAMP_TO_BORDER;
247        case PIPE_TEX_WRAP_MIRROR_REPEAT:
248            return R300_TX_REPEAT | R300_TX_MIRRORED;
249        case PIPE_TEX_WRAP_MIRROR_CLAMP:
250            return R300_TX_CLAMP | R300_TX_MIRRORED;
251        case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
252            return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
253        case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
254            return R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED;
255        default:
256            fprintf(stderr, "r300: Unknown texture wrap %d", wrap);
257            assert(0);
258            return 0;
259    }
260}
261
262static inline uint32_t r300_translate_tex_filters(int min, int mag, int mip,
263                                                  boolean is_anisotropic)
264{
265    uint32_t retval = 0;
266
267    switch (min) {
268    case PIPE_TEX_FILTER_NEAREST:
269        retval |= R300_TX_MIN_FILTER_NEAREST;
270        break;
271    case PIPE_TEX_FILTER_LINEAR:
272        retval |= is_anisotropic ? R300_TX_MIN_FILTER_ANISO :
273                                   R300_TX_MIN_FILTER_LINEAR;
274        break;
275    default:
276        fprintf(stderr, "r300: Unknown texture filter %d\n", min);
277        assert(0);
278    }
279
280    switch (mag) {
281    case PIPE_TEX_FILTER_NEAREST:
282        retval |= R300_TX_MAG_FILTER_NEAREST;
283        break;
284    case PIPE_TEX_FILTER_LINEAR:
285        retval |= is_anisotropic ? R300_TX_MAG_FILTER_ANISO :
286                                   R300_TX_MAG_FILTER_LINEAR;
287        break;
288    default:
289        fprintf(stderr, "r300: Unknown texture filter %d\n", mag);
290        assert(0);
291    }
292
293    switch (mip) {
294    case PIPE_TEX_MIPFILTER_NONE:
295        retval |= R300_TX_MIN_FILTER_MIP_NONE;
296        break;
297    case PIPE_TEX_MIPFILTER_NEAREST:
298        retval |= R300_TX_MIN_FILTER_MIP_NEAREST;
299        break;
300    case PIPE_TEX_MIPFILTER_LINEAR:
301        retval |= R300_TX_MIN_FILTER_MIP_LINEAR;
302        break;
303    default:
304        fprintf(stderr, "r300: Unknown texture filter %d\n", mip);
305        assert(0);
306    }
307
308    return retval;
309}
310
311static inline uint32_t r300_anisotropy(unsigned max_aniso)
312{
313    if (max_aniso >= 16) {
314        return R300_TX_MAX_ANISO_16_TO_1;
315    } else if (max_aniso >= 8) {
316        return R300_TX_MAX_ANISO_8_TO_1;
317    } else if (max_aniso >= 4) {
318        return R300_TX_MAX_ANISO_4_TO_1;
319    } else if (max_aniso >= 2) {
320        return R300_TX_MAX_ANISO_2_TO_1;
321    } else {
322        return R300_TX_MAX_ANISO_1_TO_1;
323    }
324}
325
326static inline uint32_t r500_anisotropy(unsigned max_aniso)
327{
328    if (!max_aniso) {
329        return 0;
330    }
331    max_aniso -= 1;
332
333    // Map the range [0, 15] to [0, 63].
334    return R500_TX_MAX_ANISO(MIN2((unsigned)(max_aniso*4.2001), 63)) |
335           R500_TX_ANISO_HIGH_QUALITY;
336}
337
338/* Translate pipe_formats into PSC vertex types. */
339static inline uint16_t
340r300_translate_vertex_data_type(enum pipe_format format) {
341    uint32_t result = 0;
342    const struct util_format_description *desc;
343    unsigned i;
344
345    if (!format)
346        format = PIPE_FORMAT_R32_FLOAT;
347
348    desc = util_format_description(format);
349
350    if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
351        return R300_INVALID_FORMAT;
352    }
353
354    /* Find the first non-VOID channel. */
355    for (i = 0; i < 4; i++) {
356        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
357            break;
358        }
359    }
360
361    switch (desc->channel[i].type) {
362        /* Half-floats, floats, doubles */
363        case UTIL_FORMAT_TYPE_FLOAT:
364            switch (desc->channel[i].size) {
365                case 16:
366                    /* Supported only on RV350 and later. */
367                    if (desc->nr_channels > 2) {
368                        result = R300_DATA_TYPE_FLT16_4;
369                    } else {
370                        result = R300_DATA_TYPE_FLT16_2;
371                    }
372                    break;
373                case 32:
374                    result = R300_DATA_TYPE_FLOAT_1 + (desc->nr_channels - 1);
375                    break;
376                default:
377                    return R300_INVALID_FORMAT;
378            }
379            break;
380        /* Unsigned ints */
381        case UTIL_FORMAT_TYPE_UNSIGNED:
382        /* Signed ints */
383        case UTIL_FORMAT_TYPE_SIGNED:
384            switch (desc->channel[i].size) {
385                case 8:
386                    result = R300_DATA_TYPE_BYTE;
387                    break;
388                case 16:
389                    if (desc->nr_channels > 2) {
390                        result = R300_DATA_TYPE_SHORT_4;
391                    } else {
392                        result = R300_DATA_TYPE_SHORT_2;
393                    }
394                    break;
395                default:
396                    return R300_INVALID_FORMAT;
397            }
398            break;
399        default:
400            return R300_INVALID_FORMAT;
401    }
402
403    if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
404        result |= R300_SIGNED;
405    }
406    if (desc->channel[i].normalized) {
407        result |= R300_NORMALIZE;
408    }
409
410    return result;
411}
412
413static inline uint16_t
414r300_translate_vertex_data_swizzle(enum pipe_format format) {
415    const struct util_format_description *desc;
416    unsigned i, swizzle = 0;
417
418    if (!format)
419        return (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_X_SHIFT) |
420               (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Y_SHIFT) |
421               (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
422               (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT);
423
424    desc = util_format_description(format);
425
426    if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
427        fprintf(stderr, "r300: Bad format %s in %s:%d\n",
428            util_format_short_name(format), __FUNCTION__, __LINE__);
429        return 0;
430    }
431
432    for (i = 0; i < desc->nr_channels; i++) {
433        swizzle |=
434            MIN2(desc->swizzle[i], R300_SWIZZLE_SELECT_FP_ONE) << (3*i);
435    }
436    /* Set (0,0,0,1) in unused components. */
437    for (; i < 3; i++) {
438        swizzle |= R300_SWIZZLE_SELECT_FP_ZERO << (3*i);
439    }
440    for (; i < 4; i++) {
441        swizzle |= R300_SWIZZLE_SELECT_FP_ONE << (3*i);
442    }
443
444    return swizzle | (0xf << R300_WRITE_ENA_SHIFT);
445}
446
447#endif /* R300_STATE_INLINES_H */
448