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  02/20/2006 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   transitioned from the Dolphin source tree
19 
20 
21     4     03/07/17 11:42 Hirose
22     Fixed "PE_CMODE1_MASK_SETBLENDMODE" macro definition.
23 
24     3     02/10/28 11:08 Hirose
25     Supported fog functions for orthographic projection.
26 
27     2     10/13/01 2:27a Hirose
28     Added GDSetBlendMode().
29 
30     1     9/12/01 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