r300_state.c revision 21a5a133fff3ab1a068a11a32144dcb63f1d5020
1/*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23#include "r300_context.h"
24#include "r300_state.h"
25
26static uint32_t translate_blend_function(int blend_func) {
27    switch (blend_func) {
28        case PIPE_BLEND_ADD:
29            return R300_COMB_FCN_ADD_CLAMP;
30        case PIPE_BLEND_SUBTRACT:
31            return R300_COMB_FCN_SUB_CLAMP;
32        case PIPE_BLEND_REVERSE_SUBTRACT:
33            return R300_COMB_FCN_RSUB_CLAMP;
34        case PIPE_BLEND_MIN:
35            return R300_COMB_FCN_MIN;
36        case PIPE_BLEND_MAX:
37            return R300_COMB_FCN_MAX;
38        default:
39            /* XXX should be unreachable, handle this */
40            break;
41    }
42    return 0;
43}
44
45/* XXX we can also offer the D3D versions of some of these... */
46static uint32_t translate_blend_factor(int blend_fact) {
47    switch (blend_fact) {
48        case PIPE_BLENDFACTOR_ONE:
49            return R300_BLEND_GL_ONE;
50        case PIPE_BLENDFACTOR_SRC_COLOR:
51            return R300_BLEND_GL_SRC_COLOR;
52        case PIPE_BLENDFACTOR_SRC_ALPHA:
53            return R300_BLEND_GL_SRC_ALPHA;
54        case PIPE_BLENDFACTOR_DST_ALPHA:
55            return R300_BLEND_GL_DST_ALPHA;
56        case PIPE_BLENDFACTOR_DST_COLOR:
57            return R300_BLEND_GL_DST_COLOR;
58        case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
59            return R300_BLEND_GL_SRC_ALPHA_SATURATE;
60        case PIPE_BLENDFACTOR_CONST_COLOR:
61            return R300_BLEND_GL_CONST_COLOR;
62        case PIPE_BLENDFACTOR_CONST_ALPHA:
63            return R300_BLEND_GL_CONST_ALPHA;
64        /* XXX WTF are these?
65        case PIPE_BLENDFACTOR_SRC1_COLOR:
66        case PIPE_BLENDFACTOR_SRC1_ALPHA: */
67        case PIPE_BLENDFACTOR_ZERO:
68            return R300_BLEND_GL_ZERO;
69        case PIPE_BLENDFACTOR_INV_SRC_COLOR:
70            return R300_BLEND_GL_ONE_MINUS_SRC_COLOR;
71        case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
72            return R300_BLEND_GL_ONE_MINUS_SRC_ALPHA;
73        case PIPE_BLENDFACTOR_INV_DST_ALPHA:
74            return R300_BLEND_GL_ONE_MINUS_DST_ALPHA;
75        case PIPE_BLENDFACTOR_INV_DST_COLOR:
76            return R300_BLEND_GL_ONE_MINUS_DST_COLOR;
77        case PIPE_BLENDFACTOR_INV_CONST_COLOR:
78            return R300_BLEND_GL_ONE_MINUS_CONST_COLOR;
79        case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
80            return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA;
81        /* XXX see above
82        case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
83        case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */
84        default:
85            /* XXX the mythical 0x16 blend factor! */
86            break;
87    }
88    return 0;
89}
90
91/* Create a new blend state based on the CSO blend state.
92 *
93 * This encompasses alpha blending, logic/raster ops, and blend dithering. */
94static void* r300_create_blend_state(struct pipe_context* pipe,
95                                     const struct pipe_blend_state* state)
96{
97    struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state);
98
99    if (state->blend_enable) {
100        /* XXX for now, always do separate alpha...
101         * is it faster to do it with one reg? */
102        blend->blend_control = R300_ALPHA_BLEND_ENABLE |
103                R300_SEPARATE_ALPHA_ENABLE |
104                R300_READ_ENABLE |
105                translate_blend_function(state->rgb_func) |
106                (translate_blend_factor(state->rgb_src_factor) <<
107                    R300_SRC_BLEND_SHIFT) |
108                (translate_blend_factor(state->rgb_dst_factor) <<
109                    R300_DST_BLEND_SHIFT);
110        blend->alpha_blend_control =
111                translate_blend_function(state->alpha_func) |
112                (translate_blend_factor(state->alpha_src_factor) <<
113                    R300_SRC_BLEND_SHIFT) |
114                (translate_blend_factor(state->alpha_dst_factor) <<
115                    R300_DST_BLEND_SHIFT);
116    }
117
118    /* PIPE_LOGICOP_* don't need to be translated, fortunately. */
119    /* XXX are logicops still allowed if blending's disabled?
120     * Does Gallium take care of it for us? */
121    if (state->logicop_enable) {
122        blend->rop = R300_RB3D_ROPCNTL_ROP_ENABLE |
123                (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT;
124    }
125
126    if (state->dither) {
127        blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
128                R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
129    }
130
131    return (void*)blend;
132}
133
134/* Bind blend state. */
135static void r300_bind_blend_state(struct pipe_context* pipe,
136                                  void* state)
137{
138    struct r300_context* r300 = r300_context(pipe);
139
140    r300->blend_state = (struct r300_blend_state*)state;
141    r300->dirty_state |= R300_NEW_BLEND;
142}
143
144/* Free blend state. */
145static void r300_delete_blend_state(struct pipe_context* pipe,
146                                    void* state)
147{
148    FREE(state);
149}
150
151static uint32_t translate_depth_stencil_function(int zs_func) {
152    switch (zs_func) {
153        case PIPE_FUNC_NEVER:
154            return R300_ZS_NEVER;
155        case PIPE_FUNC_LESS:
156            return R300_ZS_LESS;
157        case PIPE_FUNC_EQUAL:
158            return R300_ZS_EQUAL;
159        case PIPE_FUNC_LEQUAL:
160            return R300_ZS_LEQUAL;
161        case PIPE_FUNC_GREATER:
162            return R300_ZS_GREATER;
163        case PIPE_FUNC_NOTEQUAL:
164            return R300_ZS_NOTEQUAL;
165        case PIPE_FUNC_GEQUAL:
166            return R300_ZS_GEQUAL;
167        case PIPE_FUNC_ALWAYS:
168            return R300_ZS_ALWAYS;
169        default:
170            /* XXX shouldn't be reachable */
171            break;
172    }
173    return 0;
174}
175
176static uint32_t translate_stencil_op(int s_op) {
177    switch (s_op) {
178        case PIPE_STENCIL_OP_KEEP:
179            return R300_ZS_KEEP;
180        case PIPE_STENCIL_OP_ZERO:
181            return R300_ZS_ZERO;
182        case PIPE_STENCIL_OP_REPLACE:
183            return R300_ZS_REPLACE;
184        case PIPE_STENCIL_OP_INCR:
185            return R300_ZS_INCR;
186        case PIPE_STENCIL_OP_DECR:
187            return R300_ZS_DECR;
188        case PIPE_STENCIL_OP_INCR_WRAP:
189            return R300_ZS_INCR_WRAP;
190        case PIPE_STENCIL_OP_DECR_WRAP:
191            return R300_ZS_DECR_WRAP;
192        case PIPE_STENCIL_OP_INVERT:
193            return R300_ZS_INVERT;
194        default:
195            /* XXX shouldn't be reachable */
196            break;
197    }
198    return 0;
199}
200
201static uint32_t translate_alpha_function(int alpha_func) {
202    switch (alpha_func) {
203        case PIPE_FUNC_NEVER:
204            return R300_FG_ALPHA_FUNC_NEVER;
205        case PIPE_FUNC_LESS:
206            return R300_FG_ALPHA_FUNC_LESS;
207        case PIPE_FUNC_EQUAL:
208            return R300_FG_ALPHA_FUNC_EQUAL;
209        case PIPE_FUNC_LEQUAL:
210            return R300_FG_ALPHA_FUNC_LE;
211        case PIPE_FUNC_GREATER:
212            return R300_FG_ALPHA_FUNC_GREATER;
213        case PIPE_FUNC_NOTEQUAL:
214            return R300_FG_ALPHA_FUNC_NOTEQUAL;
215        case PIPE_FUNC_GEQUAL:
216            return R300_FG_ALPHA_FUNC_GE;
217        case PIPE_FUNC_ALWAYS:
218            return R300_FG_ALPHA_FUNC_ALWAYS;
219        default:
220            /* XXX shouldn't be reachable */
221            break;
222    }
223    return 0;
224}
225
226/* Create a new depth, stencil, and alpha state based on the CSO dsa state.
227 *
228 * This contains the depth buffer, stencil buffer, alpha test, and such.
229 * On the Radeon, depth and stencil buffer setup are intertwined, which is
230 * the reason for some of the strange-looking assignments across registers. */
231static void* r300_create_dsa_state(struct pipe_context* pipe,
232                                     struct pipe_depth_stencil_alpha_state* state)
233{
234    struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
235
236    /* Depth test setup. */
237    if (state->depth.enabled) {
238        dsa->z_buffer_control |= R300_Z_ENABLE;
239
240        if (state->depth.writemask) {
241            dsa->z_buffer_control |= R300_Z_WRITE_ENABLE;
242        }
243
244        dsa->z_stencil_control |=
245                (translate_depth_stencil_function(state->depth.func) <<
246                    R300_Z_FUNC_SHIFT);
247    }
248
249    /* Stencil buffer setup. */
250    if (state->stencil[0].enabled) {
251        dsa->z_buffer_control |= R300_STENCIL_ENABLE;
252        dsa->z_stencil_control |=
253                (translate_depth_stencil_function(state->stencil[0].func) <<
254                    R300_S_FRONT_FUNC_SHIFT) |
255                (translate_stencil_op(state->stencil[0].fail_op) <<
256                    R300_S_FRONT_SFAIL_OP_SHIFT) |
257                (translate_stencil_op(state->stencil[0].zpass_op) <<
258                    R300_S_FRONT_ZPASS_OP_SHIFT) |
259                (translate_stencil_op(state->stencil[0].zfail_op) <<
260                    R300_S_FRONT_ZFAIL_OP_SHIFT);
261
262        dsa->stencil_ref_mask = (state->stencil[0].ref_value) |
263                (state->stencil[0].value_mask << R300_STENCILMASK_SHIFT) |
264                (state->stencil[0].write_mask << R300_STENCILWRITEMASK_SHIFT);
265
266        if (state->stencil[1].enabled) {
267            dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK;
268            dsa->z_stencil_control |=
269                    (translate_depth_stencil_function(state->stencil[1].func) <<
270                        R300_S_BACK_FUNC_SHIFT) |
271                    (translate_stencil_op(state->stencil[1].fail_op) <<
272                        R300_S_BACK_SFAIL_OP_SHIFT) |
273                    (translate_stencil_op(state->stencil[1].zpass_op) <<
274                        R300_S_BACK_ZPASS_OP_SHIFT) |
275                    (translate_stencil_op(state->stencil[1].zfail_op) <<
276                        R300_S_BACK_ZFAIL_OP_SHIFT);
277
278            dsa->stencil_ref_bf = (state->stencil[1].ref_value) |
279                    (state->stencil[1].value_mask << R300_STENCILMASK_SHIFT) |
280                    (state->stencil[1].write_mask << R300_STENCILWRITEMASK_SHIFT);
281        }
282    }
283
284    /* Alpha test setup. */
285    if (state->alpha.enabled) {
286        dsa->alpha_function = translate_alpha_function(state->alpha.func) |
287                R300_FG_ALPHA_FUNC_ENABLE;
288        dsa->alpha_reference = CLAMP(state->alpha.ref * 1023.0f, 0, 1023);
289    } else {
290        dsa->z_buffer_top = R300_ZTOP_ENABLE;
291    }
292
293    return (void*)dsa;
294}
295
296/* Bind DSA state. */
297static void r300_bind_dsa_state(struct pipe_context* pipe,
298                                  void* state)
299{
300    struct r300_context* r300 = r300_context(pipe);
301
302    r300->dsa_state = (struct r300_dsa_state*)state;
303    r300->dirty_state |= R300_NEW_DSA;
304}
305
306/* Free DSA state. */
307static void r300_delete_dsa_state(struct pipe_context* pipe,
308                                    void* state)
309{
310    FREE(state);
311}
312
313static void r300_set_scissor_state(struct pipe_context* pipe,
314                                   struct pipe_scissor_state* state)
315{
316    struct r300_context* r300 = r300_context(pipe);
317    draw_flush(r300->draw);
318
319    /* XXX figure out how this memory doesn't get lost in space
320    memcpy(r300->scissor, scissor, sizeof(struct pipe_scissor_state)); */
321    r300->dirty_state |= R300_NEW_SCISSOR;
322}
323
324static void* r300_create_vs_state(struct pipe_context* pipe,
325                                  struct pipe_shader_state* state)
326{
327    struct r300_context* context = r300_context(pipe);
328    /* XXX handing this off to Draw for now */
329    return draw_create_vertex_shader(context->draw, state);
330}
331
332static void r300_bind_vs_state(struct pipe_context* pipe, void* state) {
333    struct r300_context* context = r300_context(pipe);
334    /* XXX handing this off to Draw for now */
335    draw_bind_vertex_shader(context->draw, (struct draw_vertex_shader*)state);
336}
337
338static void r300_delete_vs_state(struct pipe_context* pipe, void* state)
339{
340    struct r300_context* context = r300_context(pipe);
341    /* XXX handing this off to Draw for now */
342    draw_delete_vertex_shader(context->draw, (struct draw_vertex_shader*)state);
343}
344
345void r300_init_state_functions(struct r300_context* r300) {
346
347    r300->context.create_blend_state = r300_create_blend_state;
348    r300->context.bind_blend_state = r300_bind_blend_state;
349    r300->context.delete_blend_state = r300_delete_blend_state;
350
351    r300->context.create_depth_stencil_alpha_state = r300_create_dsa_state;
352    r300->context.bind_depth_stencil_alpha_state = r300_bind_dsa_state;
353    r300->context.delete_depth_stencil_alpha_state = r300_delete_dsa_state;
354
355    r300->context.set_scissor_state = r300_set_scissor_state;
356
357    r300->context.create_vs_state = r300_create_vs_state;
358    r300->context.bind_vs_state = r300_bind_vs_state;
359    r300->context.delete_vs_state = r300_delete_vs_state;
360}