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
28typedef struct
29{
30    Bool supported;
31    CARD32 col0;
32    CARD32 col1;
33    CARD32 al0;
34    CARD32 al1;
35} ViaCompositeOperator;
36
37typedef struct
38{
39    CARD32 pictFormat;
40    Bool dstSupported;
41    Bool texSupported;
42    CARD32 dstFormat;
43    CARD32 texFormat;
44} Via3DFormat;
45
46static ViaCompositeOperator viaOperatorModes[256];
47static 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
53static 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
75static 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
93static CARD32
94via3DDstFormat(int format)
95{
96    return via3DFormats[VIA_FMT_HASH(format)].dstFormat;
97}
98
99static CARD32
100via3DTexFormat(int format)
101{
102    return via3DFormats[VIA_FMT_HASH(format)].texFormat;
103}
104
105static Bool
106via3DDstSupported(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
115static Bool
116via3DTexSupported(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
125static void
126viaSet3DDestination(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
136static void
137viaSet3DDrawing(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
147static void
148viaSet3DFlags(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
159static Bool
160viaOrder(CARD32 val, CARD32 * shift)
161{
162    *shift = 0;
163
164    while (val > (1 << *shift))
165        (*shift)++;
166    return (val == (1 << *shift));
167}
168
169static Bool
170viaSet3DTexture(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
235static void
236viaSet3DTexBlendCol(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 */
255static void
256viaSet3DCompositeOperator(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
273static Bool
274via3DOpSupported(CARD8 op)
275{
276    return viaOperatorModes[op].supported;
277}
278
279static void
280via3DEmitQuad(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
386static void
387via3DEmitState(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 */
534static void
535via3DEmitClipRect(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
547void
548viaInit3DState(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