1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin GD library
3   File:     GDPixel.c
4 
5   Copyright 2001 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: GDPixel.c,v $
14   Revision 1.2  2006/02/20 04:24:39  mitu
15   Changed include path from dolphin/ to revolution/.
16 
17   Revision 1.1.1.1  2005/05/12 02:15:49  yasuh-to
18   Ported from dolphin source tree.
19 
20 
21     4     2003/07/17 11:42 Hirose
22     Fixed "PE_CMODE1_MASK_SETBLENDMODE" macro definition.
23 
24     3     2002/10/28 11:08 Hirose
25     Supported fog functions for orthographic projection.
26 
27     2     2001/10/13 2:27a Hirose
28     Added GDSetBlendMode().
29 
30     1     2001/09/12 1:52p Carl
31     Initial revision of GD: Graphics Display List Library.
32   $NoKeywords: $
33  *---------------------------------------------------------------------------*/
34 
35 #include <revolution/gd.h>
36 #include <revolution/os.h>
37 
38 /*---------------------------------------------------------------------------*/
39 
40 
41 /*---------------------------------------------------------------------------*/
42 //  Name:         GDSetFog
43 //
44 //  Description:  Computes and sets fog parameters.
45 //
46 //  Arguments:    type:    	IN Fog type
47 //                startz,
48 //                endz:    	IN Z Range for linear fog.
49 //                nearz,
50 //                farz:    	IN Clipping planes Z values (projection matrix)
51 //                color:   	IN Color of the fog.
52 //
53 //  Returns:
54 //
55 /*---------------------------------------------------------------------------*/
56 
GDSetFog(GXFogType type,f32 startz,f32 endz,f32 nearz,f32 farz,GXColor color)57 void GDSetFog( GXFogType    type,
58                f32          startz,
59                f32          endz,
60                f32          nearz,
61                f32          farz,
62                GXColor      color )
63 {
64     f32     A, B, B_mant, C, A_f;
65     u32     b_expn, b_m, a_hex, c_hex;
66     u32     fsel, proj;
67 
68     ASSERTMSG(farz >= 0, "GDSetFog: The farz should be positive value");
69     ASSERTMSG(farz >= nearz, "GDSetFog: The farz should be larger than nearz");
70 
71     fsel = (u32)(type & 0x07);
72     proj = (u32)((type >> 3) & 0x01);
73 
74     if ( proj ) // ORTHOGRAPHIC
75     {
76         // Calculate constants a and c (TEV HW requirements).
77         if ((farz == nearz) || (endz == startz))
78         {
79             // take care of the odd-ball case.
80             A_f = 0.0f;
81             C   = 0.0f;
82         }
83         else
84         {
85             A   = 1.0F / (endz - startz);
86             A_f = (farz - nearz) * A;
87             C   = (startz - nearz) * A;
88         }
89 
90         b_expn = 0;
91         b_m    = 0;
92     }
93     else // PERSPECTIVE
94     {
95         // Calculate constants a, b, and c (TEV HW requirements).
96         if ((farz == nearz) || (endz == startz))
97         {
98             // take care of the odd-ball case.
99             A = 0.0f;
100             B = 0.5f;
101             C = 0.0f;
102         }
103         else
104         {
105             A = (farz * nearz) / ((farz-nearz) * (endz-startz));
106             B = farz / (farz-nearz);
107             C = startz / (endz-startz);
108         }
109 
110         B_mant = B;
111         b_expn = 1;
112         while (B_mant > 1.0)
113         {
114             B_mant /= 2;
115             b_expn++;
116         }
117         while ((B_mant > 0) && (B_mant < 0.5))
118         {
119             B_mant *= 2;
120             b_expn--;
121         }
122 
123         A_f   = A / (1 << (b_expn));
124         b_m   = (u32)(B_mant * 8388638);
125     }
126 
127     a_hex = (* (u32 *) &A_f);
128     c_hex = (* (u32 *) &C);
129 
130     // Write out register values.
131     GDWriteBPCmd( TEV_FOG_PARAM_0_PS( (a_hex >> 12), TEV_FOG_PARAM_0_ID ));
132 
133     GDWriteBPCmd( TEV_FOG_PARAM_1( b_m, TEV_FOG_PARAM_1_ID ));
134     GDWriteBPCmd( TEV_FOG_PARAM_2( b_expn, TEV_FOG_PARAM_2_ID ));
135 
136     GDWriteBPCmd( TEV_FOG_PARAM_3_PS( (c_hex >> 12), proj, fsel,
137                                       TEV_FOG_PARAM_3_ID ));
138 
139     GDWriteBPCmd( TEV_FOG_COLOR( color.b, color.g, color.r, TEV_FOG_COLOR_ID ));
140 }
141 
142 
143 /*---------------------------------------------------------------------------*/
144 //  Name:         GDSetBlendMode
145 //
146 //  Description:  Sets Blending and logic operation registers in PE.
147 //                Register mask is used to prevent changing other status
148 //                in the cmode0 register.
149 //
150 //  Arguments:    type:          	Blending or Logic op enable.
151 //                src_factor:    	Blending source factor.
152 //                dst_factor:    	Blending destination factor.
153 //                logic_op:      	Logic operation.
154 //
155 //  Returns:      None.
156 //
157 /*---------------------------------------------------------------------------*/
158 
159 #define PE_CMODE1_MASK_SETBLENDMODE \
160     (( 0x000001 << PE_CMODE0_BLEND_ENABLE_SHIFT )   | \
161      ( 0x000001 << PE_CMODE0_LOGICOP_ENABLE_SHIFT ) | \
162      ( 0x000007 << PE_CMODE0_DFACTOR_SHIFT )        | \
163      ( 0x000007 << PE_CMODE0_SFACTOR_SHIFT )        | \
164      ( 0x000001 << PE_CMODE0_BLENDOP_SHIFT )        | \
165      ( 0x00000F << PE_CMODE0_LOGICOP_SHIFT ))
166 
167 
GDSetBlendMode(GXBlendMode type,GXBlendFactor src_factor,GXBlendFactor dst_factor,GXLogicOp logic_op)168 void GDSetBlendMode( GXBlendMode    type,
169                      GXBlendFactor  src_factor,
170                      GXBlendFactor  dst_factor,
171                      GXLogicOp      logic_op )
172 {
173     GDWriteBPCmd( SS_MASK( PE_CMODE1_MASK_SETBLENDMODE ));
174 
175     GDWriteBPCmd( PE_CMODE0(
176         ((type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)),
177         (type == GX_BM_LOGIC),
178         0,
179         0,
180         0,
181         dst_factor,
182         src_factor,
183         (type == GX_BM_SUBTRACT),
184         logic_op,
185         PE_CMODE0_ID ));
186 }
187 
188 
189 /*---------------------------------------------------------------------------*/
190 //  Name:         GDSetBlendModeEtc
191 //
192 //  Description:  Sets Blending and logic operation registers in PE.
193 //                Also sets color and alpha write masks and dither mode.
194 //
195 //  Arguments:    type:          	Blending or Logic op enable.
196 //                src_factor:    	Blending source factor.
197 //                dst_factor:    	Blending destination factor.
198 //                logic_op:      	Logic operation.
199 //                color_update_enable:   	as it says
200 //                alpha_update_enable:   	as it says
201 //                dither_enable:         	as it says
202 //
203 //  Returns:      None.
204 //
205 /*---------------------------------------------------------------------------*/
206 
GDSetBlendModeEtc(GXBlendMode type,GXBlendFactor src_factor,GXBlendFactor dst_factor,GXLogicOp logic_op,GXBool color_update_enable,GXBool alpha_update_enable,GXBool dither_enable)207 void GDSetBlendModeEtc( GXBlendMode     type,
208                         GXBlendFactor   src_factor,
209                         GXBlendFactor   dst_factor,
210                         GXLogicOp       logic_op,
211                         GXBool          color_update_enable,
212                         GXBool          alpha_update_enable,
213                         GXBool          dither_enable )
214 {
215     GDWriteBPCmd( PE_CMODE0(
216         ((type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)),
217         (type == GX_BM_LOGIC),
218         dither_enable,
219         color_update_enable,
220         alpha_update_enable,
221         dst_factor,
222         src_factor,
223         (type == GX_BM_SUBTRACT),
224         logic_op,
225         PE_CMODE0_ID ));
226 }
227 
228 /*---------------------------------------------------------------------------*/
229 //  Name:         GDSetZMode
230 //
231 //  Description:  Sets zbuffer compare and update parameters.
232 //
233 //  Arguments:    compare_enable:  	enables z comparison and culling.
234 //                func:            	function used in z comparision.
235 //                update_enable:   	enables writing new z values to zbuffer.
236 //
237 //  Returns:      None.
238 //
239 /*---------------------------------------------------------------------------*/
240 
GDSetZMode(GXBool compare_enable,GXCompare func,GXBool update_enable)241 void GDSetZMode( GXBool     compare_enable,
242                  GXCompare  func,
243                  GXBool     update_enable )
244 {
245     GDWriteBPCmd( PE_ZMODE( compare_enable, func, update_enable, PE_ZMODE_ID ));
246 }
247 
248 /*---------------------------------------------------------------------------*/
249 //  Name:         GDSetDstAlpha
250 //
251 //  Description:  Sets a constant alpha value for writing to framebuffer.
252 //
253 //  Arguments:    enable:        	Enable constant alpha writes.
254 //                alpha:         	constant value.
255 //
256 //  Returns:      None.
257 //
258 /*---------------------------------------------------------------------------*/
259 
GDSetDstAlpha(GXBool enable,u8 alpha)260 void GDSetDstAlpha( GXBool enable, u8 alpha )
261 {
262     GDWriteBPCmd( PE_CMODE1( alpha, enable, PE_CMODE1_ID ));
263 }
264 
265 /*---------------------------------------------------------------------------*/
266 //  Name:         GDSetDrawSync
267 //
268 //  Description:  Writes a sync token to the PE's token register via GFX fifo.
269 //
270 //  Arguments:    token:         	token value to be written to the pipe.
271 //
272 //  Returns:
273 //
274 /*---------------------------------------------------------------------------*/
275 
GDSetDrawSync(u16 token)276 void GDSetDrawSync( u16 token )
277 {
278     // TOKEN_INT is the register that is compared against TOKEN
279     // to see whether or not to generate a CPU interrupt.
280     // TOKEN is the register that is readable using GXReadDrawSync().
281 
282     GDWriteBPCmd( PE_TOKEN( token, PE_TOKEN_INT_ID ));
283     GDWriteBPCmd( PE_TOKEN( token, PE_TOKEN_ID ));
284 }
285 
286