2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
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:
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
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. */
23 #include "r300_context.h"
24 #include "r300_state.h"
26 static uint32_t translate_blend_function(int blend_func) {
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;
35 return R300_COMB_FCN_MIN;
37 return R300_COMB_FCN_MAX;
39 /* XXX should be unreachable, handle this */
45 /* XXX we can also offer the D3D versions of some of these... */
46 static uint32_t translate_blend_factor(int 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;
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;
82 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
83 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */
85 /* XXX the mythical 0x16 blend factor! */
91 /* Create a new blend state based on the CSO blend state.
93 * This encompasses alpha blending, logic/raster ops, and blend dithering. */
94 static void* r300_create_blend_state(struct pipe_context* pipe,
95 struct pipe_blend_state* state)
97 struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state);
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 |
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);
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;
127 blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
128 R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
134 /* Bind blend state. */
135 static void r300_bind_blend_state(struct pipe_context* pipe,
138 struct r300_context* r300 = r300_context(pipe);
140 r300->blend_state = (struct r300_blend_state*)state;
141 r300->dirty_state |= R300_NEW_BLEND;
144 /* Free blend state. */
145 static void r300_delete_blend_state(struct pipe_context* pipe,
151 static uint32_t translate_depth_stencil_function(int zs_func) {
153 case PIPE_FUNC_NEVER:
154 return R300_ZS_NEVER;
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;
170 /* XXX shouldn't be reachable */
176 static uint32_t translate_stencil_op(int s_op) {
178 case PIPE_STENCIL_OP_KEEP:
180 case PIPE_STENCIL_OP_ZERO:
182 case PIPE_STENCIL_OP_REPLACE:
183 return R300_ZS_REPLACE;
184 case PIPE_STENCIL_OP_INCR:
186 case PIPE_STENCIL_OP_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;
195 /* XXX shouldn't be reachable */
201 static uint32_t translate_alpha_function(int alpha_func) {
202 switch (alpha_func) {
203 case PIPE_FUNC_NEVER:
204 return R300_FG_ALPHA_FUNC_NEVER;
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;
220 /* XXX shouldn't be reachable */
226 /* Create a new depth, stencil, and alpha state based on the CSO dsa state.
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. */
231 static void* r300_create_dsa_state(struct pipe_context* pipe,
232 struct pipe_depth_stencil_alpha_state* state)
234 struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
236 /* Depth test setup. */
237 if (state->depth.enabled) {
238 dsa->z_buffer_control |= R300_Z_ENABLE;
240 if (state->depth.writemask) {
241 dsa->z_buffer_control |= R300_Z_WRITE_ENABLE;
244 dsa->z_stencil_control |=
245 (translate_depth_stencil_function(state->depth.func) <<
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);
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);
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);
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);
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);
290 dsa->z_buffer_top = R300_ZTOP_ENABLE;
296 /* Bind DSA state. */
297 static void r300_bind_dsa_state(struct pipe_context* pipe,
300 struct r300_context* r300 = r300_context(pipe);
302 r300->dsa_state = (struct r300_dsa_state*)state;
303 r300->dirty_state |= R300_NEW_DSA;
306 /* Free DSA state. */
307 static void r300_delete_dsa_state(struct pipe_context* pipe,
313 /* Create a new scissor state based on the CSO scissor state.
315 * This is only for the fragment scissors. */
316 static void* r300_create_scissor_state(struct pipe_context* pipe,
317 struct pipe_scissor_state* state)
319 uint32_t left, top, right, bottom;
320 struct r300_scissor_state* scissor = CALLOC_STRUCT(r300_scissor_state);
322 /* So, a bit of info. The scissors are offset by R300_SCISSORS_OFFSET in
323 * both directions for all values, and can only be 13 bits wide. Why?
324 * We may never know. */
325 left = (state->minx + R300_SCISSORS_OFFSET) & 0x1fff;
326 top = (state->miny + R300_SCISSORS_OFFSET) & 0x1fff;
327 right = (state->maxx + R300_SCISSORS_OFFSET) & 0x1fff;
328 bottom = (state->maxy + R300_SCISSORS_OFFSET) & 0x1fff;
330 scissor->scissor_top_left = (left << R300_SCISSORS_X_SHIFT) |
331 (top << R300_SCISSORS_Y_SHIFT);
332 scissor->scissor_bottom_right = (right << R300_SCISSORS_X_SHIFT) |
333 (bottom << R300_SCISSORS_Y_SHIFT);
335 return (void*)scissor;
338 /* Bind scissor state.*/
339 static void r300_bind_scissor_state(struct pipe_context* pipe,
342 struct r300_context* r300 = r300_context(pipe);
344 r300->scissor_state = (struct r300_scissor_state*)state;
345 r300->dirty_state |= R300_NEW_SCISSOR;
348 /* Delete scissor state. */
349 static void r300_delete_scissor_state(struct pipe_context* pipe,
355 static void* r300_create_vs_state(struct pipe_context* pipe,
356 struct pipe_shader_state* state)
358 struct r300_context* context = r300_context(pipe);
359 /* XXX handing this off to Draw for now */
360 return draw_create_vertex_shader(context->draw, state);
363 static void r300_bind_vs_state(struct pipe_context* pipe, void* state) {
364 struct r300_context* context = r300_context(pipe);
365 /* XXX handing this off to Draw for now */
366 draw_bind_vertex_shader(context->draw, (struct draw_vertex_shader*)state);
369 static void r300_delete_vs_state(struct pipe_context* pipe, void* state)
371 struct r300_context* context = r300_context(pipe);
372 /* XXX handing this off to Draw for now */
373 draw_delete_vertex_shader(context->draw, (struct draw_vertex_shader*)state);