1 /*
2  * Copyright 2006 Thomas Hellström. All Rights Reserved.
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  * the rights to use, copy, modify, merge, publish, distribute, sub license,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the
12  * next paragraph) shall be included in all copies or substantial portions
13  * of the 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "via_3d.h"
25 #include "via_3d_reg.h"
26 #include <picturestr.h>
27 
28 typedef struct
29 {
30     Bool supported;
31     CARD32 col0;
32     CARD32 col1;
33     CARD32 al0;
34     CARD32 al1;
35 } ViaCompositeOperator;
36 
37 typedef struct
38 {
39     CARD32 pictFormat;
40     Bool dstSupported;
41     Bool texSupported;
42     CARD32 dstFormat;
43     CARD32 texFormat;
44 } Via3DFormat;
45 
46 static ViaCompositeOperator viaOperatorModes[256];
47 static Via3DFormat via3DFormats[256];
48 
49 #define VIA_NUM_3D_OPCODES 19
50 #define VIA_NUM_3D_FORMATS 15
51 #define VIA_FMT_HASH(arg) (((((arg) >> 1) + (arg)) >> 8) & 0xFF)
52 
53 static const CARD32 viaOpCodes[VIA_NUM_3D_OPCODES][5] = {
54     {PictOpClear, 0x05, 0x45, 0x40, 0x80},
55     {PictOpSrc, 0x15, 0x45, 0x50, 0x80},
56     {PictOpDst, 0x05, 0x55, 0x40, 0x90},
57     {PictOpOver, 0x15, 0x52, 0x50, 0x91},
58     {PictOpOverReverse, 0x13, 0x45, 0x52, 0x90},
59     {PictOpIn, 0x03, 0x45, 0x42, 0x80},
60     {PictOpInReverse, 0x05, 0x42, 0x40, 0x81},
61     {PictOpOut, 0x13, 0x45, 0x52, 0x80},
62     {PictOpOutReverse, 0x05, 0x52, 0x40, 0x91},
63     {PictOpAtop, 0x03, 0x52, 0x42, 0x91},
64     {PictOpAtopReverse, 0x13, 0x42, 0x52, 0x81},
65     {PictOpXor, 0x15, 0x52, 0x52, 0x91},
66     {PictOpAdd, 0x15, 0x55, 0x50, 0x90},
67     {PictOpDisjointClear, 0x05, 0x45, 0x40, 0x80},
68     {PictOpDisjointSrc, 0x15, 0x45, 0x50, 0x80},
69     {PictOpDisjointDst, 0x05, 0x55, 0x40, 0x90},
70     {PictOpConjointClear, 0x05, 0x45, 0x40, 0x80},
71     {PictOpConjointSrc, 0x15, 0x45, 0x50, 0x80},
72     {PictOpConjointDst, 0x05, 0x55, 0x40, 0x90}
73 };
74 
75 static const CARD32 viaFormats[VIA_NUM_3D_FORMATS][5] = {
76     {PICT_x1r5g5b5, HC_HDBFM_RGB555, HC_HTXnFM_RGB555, 1, 1},
77     {PICT_r5g6b5, HC_HDBFM_RGB565, HC_HTXnFM_RGB565, 1, 1},
78     {PICT_a4r4g4b4, HC_HDBFM_ARGB4444, HC_HTXnFM_ARGB4444, 1, 1},
79     {PICT_a1r5g5b5, HC_HDBFM_ARGB1555, HC_HTXnFM_ARGB1555, 1, 1},
80     {PICT_x1b5g5r5, HC_HDBFM_BGR555, HC_HTXnFM_BGR555, 1, 1},
81     {PICT_b5g6r5, HC_HDBFM_BGR565, HC_HTXnFM_BGR565, 1, 1},
82     {PICT_a4b4g4r4, HC_HDBFM_ABGR4444, HC_HTXnFM_ABGR4444, 1, 1},
83     {PICT_a1b5g5r5, HC_HDBFM_ABGR1555, HC_HTXnFM_ABGR1555, 1, 1},
84     {PICT_x8r8g8b8, HC_HDBFM_ARGB0888, HC_HTXnFM_ARGB0888, 1, 1},
85     {PICT_a8r8g8b8, HC_HDBFM_ARGB8888, HC_HTXnFM_ARGB8888, 1, 1},
86     {PICT_x8b8g8r8, HC_HDBFM_ABGR0888, HC_HTXnFM_ABGR0888, 1, 1},
87     {PICT_a8b8g8r8, HC_HDBFM_ABGR8888, HC_HTXnFM_ABGR8888, 1, 1},
88     {PICT_a8, 0x00, HC_HTXnFM_A8, 0, 1},
89     {PICT_a4, 0x00, HC_HTXnFM_A4, 0, 1},
90     {PICT_a1, 0x00, HC_HTXnFM_A1, 0, 1}
91 };
92 
93 static CARD32
via3DDstFormat(int format)94 via3DDstFormat(int format)
95 {
96     return via3DFormats[VIA_FMT_HASH(format)].dstFormat;
97 }
98 
99 static CARD32
via3DTexFormat(int format)100 via3DTexFormat(int format)
101 {
102     return via3DFormats[VIA_FMT_HASH(format)].texFormat;
103 }
104 
105 static Bool
via3DDstSupported(int format)106 via3DDstSupported(int format)
107 {
108     Via3DFormat *fm = via3DFormats + VIA_FMT_HASH(format);
109 
110     if (fm->pictFormat != format)
111         return FALSE;
112     return fm->dstSupported;
113 }
114 
115 static Bool
via3DTexSupported(int format)116 via3DTexSupported(int format)
117 {
118     Via3DFormat *fm = via3DFormats + VIA_FMT_HASH(format);
119 
120     if (fm->pictFormat != format)
121         return FALSE;
122     return fm->texSupported;
123 }
124 
125 static void
viaSet3DDestination(Via3DState * v3d,CARD32 offset,CARD32 pitch,int format)126 viaSet3DDestination(Via3DState * v3d, CARD32 offset, CARD32 pitch, int format)
127 {
128     v3d->drawingDirty = TRUE;  /* Affects planemask format. */
129     v3d->destDirty = TRUE;
130     v3d->destOffset = offset;
131     v3d->destPitch = pitch;
132     v3d->destFormat = via3DDstFormat(format);
133     v3d->destDepth = (v3d->destFormat < HC_HDBFM_ARGB0888) ? 16 : 32;
134 }
135 
136 static void
viaSet3DDrawing(Via3DState * v3d,int rop,CARD32 planeMask,CARD32 solidColor,CARD32 solidAlpha)137 viaSet3DDrawing(Via3DState * v3d, int rop,
138                 CARD32 planeMask, CARD32 solidColor, CARD32 solidAlpha)
139 {
140     v3d->drawingDirty = TRUE;
141     v3d->rop = rop;
142     v3d->planeMask = planeMask;
143     v3d->solidColor = solidColor;
144     v3d->solidAlpha = solidAlpha;
145 }
146 
147 static void
viaSet3DFlags(Via3DState * v3d,int numTextures,Bool writeAlpha,Bool writeColor,Bool blend)148 viaSet3DFlags(Via3DState * v3d, int numTextures,
149               Bool writeAlpha, Bool writeColor, Bool blend)
150 {
151     v3d->enableDirty = TRUE;
152     v3d->blendDirty = TRUE;
153     v3d->numTextures = numTextures;
154     v3d->writeAlpha = writeAlpha;
155     v3d->writeColor = writeColor;
156     v3d->blend = blend;
157 }
158 
159 static Bool
viaOrder(CARD32 val,CARD32 * shift)160 viaOrder(CARD32 val, CARD32 * shift)
161 {
162     *shift = 0;
163 
164     while (val > (1 << *shift))
165         (*shift)++;
166     return (val == (1 << *shift));
167 }
168 
169 static Bool
viaSet3DTexture(Via3DState * v3d,int tex,CARD32 offset,CARD32 pitch,Bool npot,CARD32 width,CARD32 height,int format,ViaTextureModes sMode,ViaTextureModes tMode,ViaTexBlendingModes blendingMode,Bool agpTexture)170 viaSet3DTexture(Via3DState * v3d, int tex, CARD32 offset,
171                 CARD32 pitch, Bool npot, CARD32 width, CARD32 height,
172                 int format, ViaTextureModes sMode, ViaTextureModes tMode,
173                 ViaTexBlendingModes blendingMode, Bool agpTexture)
174 {
175     ViaTextureUnit *vTex = v3d->tex + tex;
176 
177     vTex->textureLevel0Offset = offset;
178     vTex->npot = npot;
179     if (!viaOrder(pitch, &vTex->textureLevel0Exp) && !vTex->npot)
180         return FALSE;
181     vTex->textureLevel0Pitch = pitch;
182     if (!viaOrder(width, &vTex->textureLevel0WExp))
183         return FALSE;
184     if (!viaOrder(height, &vTex->textureLevel0HExp))
185         return FALSE;
186 
187     if (pitch <= 4) {
188         ErrorF("Warning: texture pitch <= 4 !\n");
189     }
190 
191     vTex->textureFormat = via3DTexFormat(format);
192 
193     switch (blendingMode) {
194         case via_src:
195             vTex->texCsat = (0x01 << 23) | (0x10 << 14) | (0x03 << 7) | 0x00;
196             vTex->texAsat = ((0x0B << 14)
197                              | ((PICT_FORMAT_A(format) ? 0x04 : 0x02) << 7)
198                              | 0x03);
199             vTex->texRCa = 0x00000000;
200             vTex->texRAa = 0x00000000;
201             vTex->texBColDirty = TRUE;
202             break;
203         case via_src_onepix_mask:
204             vTex->texCsat = (0x01 << 23) | (0x09 << 14) | (0x03 << 7) | 0x00;
205             vTex->texAsat = ((0x03 << 14)
206                              | ((PICT_FORMAT_A(format) ? 0x04 : 0x02) << 7)
207                              | 0x03);
208             break;
209         case via_src_onepix_comp_mask:
210             vTex->texCsat = (0x01 << 23) | (0x09 << 14) | (0x03 << 7) | 0x00;
211             vTex->texAsat = ((0x03 << 14)
212                              | ((PICT_FORMAT_A(format) ? 0x04 : 0x02) << 7)
213                              | 0x03);
214             break;
215         case via_mask:
216             vTex->texCsat = (0x01 << 23) | (0x07 << 14) | (0x04 << 7) | 0x00;
217             vTex->texAsat = (0x01 << 23) | (0x04 << 14) | (0x02 << 7) | 0x03;
218             break;
219         case via_comp_mask:
220             vTex->texCsat = (0x01 << 23) | (0x03 << 14) | (0x04 << 7) | 0x00;
221             vTex->texAsat = (0x01 << 23) | (0x04 << 14) | (0x02 << 7) | 0x03;
222             break;
223         default:
224             return FALSE;
225     }
226 
227     vTex->textureDirty = TRUE;
228     vTex->textureModesS = sMode - via_single;
229     vTex->textureModesT = tMode - via_single;
230 
231     vTex->agpTexture = agpTexture;
232     return TRUE;
233 }
234 
235 static void
viaSet3DTexBlendCol(Via3DState * v3d,int tex,Bool component,CARD32 color)236 viaSet3DTexBlendCol(Via3DState * v3d, int tex, Bool component, CARD32 color)
237 {
238     CARD32 alpha;
239     ViaTextureUnit *vTex = v3d->tex + tex;
240 
241     vTex->texRAa = (color >> 8) & 0x00FF0000;
242     if (component) {
243         vTex->texRCa = (color & 0x00FFFFFF);
244     } else {
245         alpha = color >> 24;
246         vTex->texRCa = alpha | (alpha << 8) | (alpha << 16) | (alpha << 24);
247     }
248     vTex->texBColDirty = TRUE;
249 }
250 
251 /*
252  * Check if the compositing operator is supported and
253  * return the corresponding register setting.
254  */
255 static void
viaSet3DCompositeOperator(Via3DState * v3d,CARD8 op)256 viaSet3DCompositeOperator(Via3DState * v3d, CARD8 op)
257 {
258     ViaCompositeOperator *vOp = viaOperatorModes + op;
259 
260     if (v3d)
261         v3d->blendDirty = TRUE;
262     else
263         return;
264 
265     if (vOp->supported) {
266         v3d->blendCol0 = vOp->col0 << 4;
267         v3d->blendCol1 = vOp->col1 << 2;
268         v3d->blendAl0 = vOp->al0 << 4;
269         v3d->blendAl1 = vOp->al1 << 2;
270     }
271 }
272 
273 static Bool
via3DOpSupported(CARD8 op)274 via3DOpSupported(CARD8 op)
275 {
276     return viaOperatorModes[op].supported;
277 }
278 
279 static void
via3DEmitQuad(Via3DState * v3d,ViaCommandBuffer * cb,int dstX,int dstY,int src0X,int src0Y,int src1X,int src1Y,int w,int h)280 via3DEmitQuad(Via3DState * v3d, ViaCommandBuffer * cb, int dstX, int dstY,
281               int src0X, int src0Y, int src1X, int src1Y, int w, int h)
282 {
283     CARD32 acmd;
284     float dx1, dx2, dy1, dy2, sx1[2], sx2[2], sy1[2], sy2[2], wf;
285     double scalex, scaley;
286     int i, numTex;
287     ViaTextureUnit *vTex;
288 
289     numTex = v3d->numTextures;
290     dx1 = dstX;
291     dx2 = dstX + w;
292     dy1 = dstY;
293     dy2 = dstY + h;
294 
295     if (numTex) {
296         sx1[0] = src0X;
297         sx1[1] = src1X;
298         sy1[0] = src0Y;
299         sy1[1] = src1Y;
300         for (i = 0; i < numTex; ++i) {
301             vTex = v3d->tex + i;
302             scalex = 1. / (double)((1 << vTex->textureLevel0WExp));
303             scaley = 1. / (double)((1 << vTex->textureLevel0HExp));
304             sx2[i] = sx1[i] + w;
305             sy2[i] = sy1[i] + h;
306             sx1[i] *= scalex;
307             sy1[i] *= scaley;
308             sx2[i] *= scalex;
309             sy2[i] *= scaley;
310         }
311     }
312 
313     wf = 0.05;
314 
315     /*
316      * Vertex buffer. Emit two 3-point triangles. The W or Z coordinate
317      * is needed for AGP DMA, and the W coordinate is for some obscure
318      * reason needed for texture mapping to be done correctly. So emit
319      * a w value after the x and y coordinates.
320      */
321 
322     BEGIN_H2(HC_ParaType_CmdVdata, 22 + numTex * 6);
323     acmd = ((1 << 14) | (1 << 13) | (1 << 11));
324     if (numTex)
325         acmd |= ((1 << 7) | (1 << 8));
326     OUT_RING_SubA(0xEC, acmd);
327 
328     acmd = 2 << 16;
329     OUT_RING_SubA(0xEE, acmd);
330 
331     OUT_RING(*((CARD32 *) (&dx1)));
332     OUT_RING(*((CARD32 *) (&dy1)));
333     OUT_RING(*((CARD32 *) (&wf)));
334     for (i = 0; i < numTex; ++i) {
335         OUT_RING(*((CARD32 *) (sx1 + i)));
336         OUT_RING(*((CARD32 *) (sy1 + i)));
337     }
338 
339     OUT_RING(*((CARD32 *) (&dx2)));
340     OUT_RING(*((CARD32 *) (&dy1)));
341     OUT_RING(*((CARD32 *) (&wf)));
342     for (i = 0; i < numTex; ++i) {
343         OUT_RING(*((CARD32 *) (sx2 + i)));
344         OUT_RING(*((CARD32 *) (sy1 + i)));
345     }
346 
347     OUT_RING(*((CARD32 *) (&dx1)));
348     OUT_RING(*((CARD32 *) (&dy2)));
349     OUT_RING(*((CARD32 *) (&wf)));
350     for (i = 0; i < numTex; ++i) {
351         OUT_RING(*((CARD32 *) (sx1 + i)));
352         OUT_RING(*((CARD32 *) (sy2 + i)));
353     }
354 
355     OUT_RING(*((CARD32 *) (&dx1)));
356     OUT_RING(*((CARD32 *) (&dy2)));
357     OUT_RING(*((CARD32 *) (&wf)));
358     for (i = 0; i < numTex; ++i) {
359         OUT_RING(*((CARD32 *) (sx1 + i)));
360         OUT_RING(*((CARD32 *) (sy2 + i)));
361     }
362 
363     OUT_RING(*((CARD32 *) (&dx2)));
364     OUT_RING(*((CARD32 *) (&dy1)));
365     OUT_RING(*((CARD32 *) (&wf)));
366     for (i = 0; i < numTex; ++i) {
367         OUT_RING(*((CARD32 *) (sx2 + i)));
368         OUT_RING(*((CARD32 *) (sy1 + i)));
369     }
370 
371     OUT_RING(*((CARD32 *) (&dx2)));
372     OUT_RING(*((CARD32 *) (&dy2)));
373     OUT_RING(*((CARD32 *) (&wf)));
374     for (i = 0; i < numTex; ++i) {
375         OUT_RING(*((CARD32 *) (sx2 + i)));
376         OUT_RING(*((CARD32 *) (sy2 + i)));
377     }
378     OUT_RING_SubA(0xEE,
379                   acmd | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK);
380     OUT_RING_SubA(0xEE,
381                   acmd | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK);
382 
383     ADVANCE_RING;
384 }
385 
386 static void
via3DEmitState(Via3DState * v3d,ViaCommandBuffer * cb,Bool forceUpload)387 via3DEmitState(Via3DState * v3d, ViaCommandBuffer * cb, Bool forceUpload)
388 {
389     int i;
390     Bool saveHas3dState;
391     ViaTextureUnit *vTex;
392 
393     /*
394      * Destination buffer location, format and pitch.
395      */
396 
397     if (forceUpload || v3d->destDirty) {
398         v3d->destDirty = FALSE;
399         BEGIN_H2(HC_ParaType_NotTex, 3);
400 
401         OUT_RING_SubA(HC_SubA_HDBBasL, v3d->destOffset & 0x00FFFFFF);
402         OUT_RING_SubA(HC_SubA_HDBBasH, v3d->destOffset >> 24);
403         OUT_RING_SubA(HC_SubA_HDBFM, v3d->destFormat |
404                       (v3d->destPitch & HC_HDBPit_MASK) | HC_HDBLoc_Local);
405     }
406 
407     if (forceUpload || v3d->blendDirty) {
408         v3d->blendDirty = FALSE;
409         BEGIN_H2(HC_ParaType_NotTex, 6);
410         OUT_RING_SubA(HC_SubA_HABLRFCa, 0x00);
411         OUT_RING_SubA(HC_SubA_HABLRFCb, 0x00);
412         OUT_RING_SubA(HC_SubA_HABLCsat, v3d->blendCol0);
413         OUT_RING_SubA(HC_SubA_HABLCop, v3d->blendCol1);
414         OUT_RING_SubA(HC_SubA_HABLAsat, v3d->blendAl0);
415         OUT_RING_SubA(HC_SubA_HABLAop, v3d->blendAl1);
416     }
417 
418     if (forceUpload || v3d->drawingDirty) {
419 
420         CARD32 planeMaskLo, planeMaskHi;
421 
422         v3d->drawingDirty = FALSE;
423         BEGIN_H2(HC_ParaType_NotTex, 4);
424 
425         /*
426          * Raster operation and Planemask.
427          */
428 
429         if ( /* v3d->destDepth == 16 Bad Docs? */ FALSE) {
430             planeMaskLo = (v3d->planeMask & 0x000000FF) << 16;
431             planeMaskHi = (v3d->planeMask & 0x0000FF00) >> 8;
432         } else {
433             planeMaskLo = v3d->planeMask & 0x00FFFFFF;
434             planeMaskHi = v3d->planeMask >> 24;
435         }
436 
437         OUT_RING_SubA(HC_SubA_HROP, ((v3d->rop & 0x0F) << 8) | planeMaskHi);
438         OUT_RING_SubA(HC_SubA_HFBBMSKL, planeMaskLo);
439 
440         /*
441          * Solid shading color and alpha. Pixel center at
442          * floating coordinates (X.5,Y.5).
443          */
444 
445         OUT_RING_SubA(HC_SubA_HSolidCL,
446                       (v3d->solidColor & 0x00FFFFFF) | (0 << 23));
447         OUT_RING_SubA(HC_SubA_HPixGC,
448                       (((v3d->solidColor & 0xFF000000) >> 16) | (0 << 23)
449                        | (v3d->solidAlpha & 0xFF)));
450     }
451 
452     if (forceUpload || v3d->enableDirty) {
453         v3d->enableDirty = FALSE;
454         BEGIN_H2(HC_ParaType_NotTex, 1);
455 
456         OUT_RING_SubA(HC_SubA_HEnable,
457                       ((v3d->writeColor) ? HC_HenCW_MASK : 0) |
458                       ((v3d->blend) ? HC_HenABL_MASK : 0) |
459                       ((v3d->numTextures) ? HC_HenTXMP_MASK : 0) |
460                       ((v3d->writeAlpha) ? HC_HenAW_MASK : 0));
461 
462         if (v3d->numTextures) {
463             BEGIN_H2((HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)), 2);
464             OUT_RING_SubA(HC_SubA_HTXSMD, (0 << 7) | (0 << 6) |
465                           (((v3d->numTextures - 1) & 0x1) << 3) | (0 << 1) | 1);
466             OUT_RING_SubA(HC_SubA_HTXSMD, (0 << 7) | (0 << 6) |
467                           (((v3d->numTextures - 1) & 0x1) << 3) | (0 << 1) | 0);
468         }
469     }
470 
471     for (i = 0; i < v3d->numTextures; ++i) {
472         vTex = v3d->tex + i;
473 
474         if (forceUpload || vTex->textureDirty) {
475             vTex->textureDirty = FALSE;
476 
477             BEGIN_H2((HC_ParaType_Tex |
478                       (((i == 0) ? HC_SubType_Tex0 : HC_SubType_Tex1) << 8)),
479                      13);
480 
481             OUT_RING_SubA(HC_SubA_HTXnFM, (vTex->textureFormat |
482                                            (vTex->
483                                             agpTexture ? HC_HTXnLoc_AGP :
484                                             HC_HTXnLoc_Local)));
485             OUT_RING_SubA(HC_SubA_HTXnL0BasL,
486                           vTex->textureLevel0Offset & 0x00FFFFFF);
487             OUT_RING_SubA(HC_SubA_HTXnL012BasH,
488                           vTex->textureLevel0Offset >> 24);
489             if (vTex->npot) {
490                 OUT_RING_SubA(HC_SubA_HTXnL0Pit,
491                               (vTex->textureLevel0Pitch & HC_HTXnLnPit_MASK) |
492                               HC_HTXnEnPit_MASK);
493             } else {
494                 OUT_RING_SubA(HC_SubA_HTXnL0Pit,
495                               vTex->textureLevel0Exp << HC_HTXnLnPitE_SHIFT);
496             }
497             OUT_RING_SubA(HC_SubA_HTXnL0_5WE, vTex->textureLevel0WExp);
498             OUT_RING_SubA(HC_SubA_HTXnL0_5HE, vTex->textureLevel0HExp);
499             OUT_RING_SubA(HC_SubA_HTXnL0OS, 0x00);
500             OUT_RING_SubA(HC_SubA_HTXnTB, 0x00);
501             OUT_RING_SubA(HC_SubA_HTXnMPMD,
502                           ((((unsigned)vTex->textureModesT) << 19)
503                            | (((unsigned)vTex->textureModesS) << 16)));
504 
505             OUT_RING_SubA(HC_SubA_HTXnTBLCsat, vTex->texCsat);
506             OUT_RING_SubA(HC_SubA_HTXnTBLCop, (0x00 << 22) | (0x00 << 19) |
507                           (0x00 << 14) | (0x02 << 11) |
508                           (0x00 << 7) | (0x03 << 3) | 0x02);
509             OUT_RING_SubA(HC_SubA_HTXnTBLAsat, vTex->texAsat);
510             OUT_RING_SubA(HC_SubA_HTXnTBLRFog, 0x00);
511         }
512     }
513 
514     for (i = 0; i < v3d->numTextures; ++i) {
515         vTex = v3d->tex + i;
516 
517         if (forceUpload || vTex->texBColDirty) {
518             saveHas3dState = cb->has3dState;
519             vTex->texBColDirty = FALSE;
520             BEGIN_H2((HC_ParaType_Tex |
521                       (((i == 0) ? HC_SubType_Tex0 : HC_SubType_Tex1) << 8)),
522                      2);
523             OUT_RING_SubA(HC_SubA_HTXnTBLRAa, vTex->texRAa);
524             OUT_RING_SubA(HC_SubA_HTXnTBLRCa, vTex->texRCa);
525             cb->has3dState = saveHas3dState;
526         }
527     }
528 }
529 
530 /*
531  * Cliprect. Considered not important for the DRM 3D State, so restore the
532  * has3dState flag afterwards.
533  */
534 static void
via3DEmitClipRect(Via3DState * v3d,ViaCommandBuffer * cb,int x,int y,int w,int h)535 via3DEmitClipRect(Via3DState * v3d, ViaCommandBuffer * cb, int x, int y,
536                   int w, int h)
537 {
538     Bool saveHas3dState;
539 
540     saveHas3dState = cb->has3dState;
541     BEGIN_H2(HC_ParaType_NotTex, 4);
542     OUT_RING_SubA(HC_SubA_HClipTB, (y << 12) | (y + h));
543     OUT_RING_SubA(HC_SubA_HClipLR, (x << 12) | (x + w));
544     cb->has3dState = saveHas3dState;
545 }
546 
547 void
viaInit3DState(Via3DState * v3d)548 viaInit3DState(Via3DState * v3d)
549 {
550     ViaCompositeOperator *op;
551     int i;
552     CARD32 tmp, hash;
553     Via3DFormat *format;
554 
555     v3d->setDestination = viaSet3DDestination;
556     v3d->setDrawing = viaSet3DDrawing;
557     v3d->setFlags = viaSet3DFlags;
558     v3d->setTexture = viaSet3DTexture;
559     v3d->setTexBlendCol = viaSet3DTexBlendCol;
560     v3d->opSupported = via3DOpSupported;
561     v3d->setCompositeOperator = viaSet3DCompositeOperator;
562     v3d->emitQuad = via3DEmitQuad;
563     v3d->emitState = via3DEmitState;
564     v3d->emitClipRect = via3DEmitClipRect;
565     v3d->dstSupported = via3DDstSupported;
566     v3d->texSupported = via3DTexSupported;
567 
568     for (i = 0; i < 256; ++i) {
569         viaOperatorModes[i].supported = FALSE;
570     }
571 
572     for (i = 0; i < VIA_NUM_3D_OPCODES; ++i) {
573         op = viaOperatorModes + viaOpCodes[i][0];
574         op->supported = TRUE;
575         op->col0 = viaOpCodes[i][1];
576         op->col1 = viaOpCodes[i][2];
577         op->al0 = viaOpCodes[i][3];
578         op->al1 = viaOpCodes[i][4];
579     }
580 
581     for (i = 0; i < 256; ++i) {
582         via3DFormats[i].pictFormat = 0x00;
583     }
584     for (i = 0; i < VIA_NUM_3D_FORMATS; ++i) {
585         tmp = viaFormats[i][0];
586         hash = VIA_FMT_HASH(tmp);
587         format = via3DFormats + hash;
588         if (format->pictFormat) {
589             ErrorF("BUG: Bad hash function\n");
590         }
591         format->pictFormat = tmp;
592         format->dstSupported = (viaFormats[i][3] != 0x00);
593         format->texSupported = (viaFormats[i][4] != 0x00);
594         format->dstFormat = viaFormats[i][1];
595         format->texFormat = viaFormats[i][2];
596     }
597 }
598