Home | History | Annotate | Download | only in radeon
      1 /**************************************************************************
      2 
      3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
      4                      Tungsten Graphics Inc., Cedar Park, Texas.
      5 
      6 All Rights Reserved.
      7 
      8 Permission is hereby granted, free of charge, to any person obtaining
      9 a copy of this software and associated documentation files (the
     10 "Software"), to deal in the Software without restriction, including
     11 without limitation the rights to use, copy, modify, merge, publish,
     12 distribute, sublicense, and/or sell copies of the Software, and to
     13 permit persons to whom the Software is furnished to do so, subject to
     14 the following conditions:
     15 
     16 The above copyright notice and this permission notice (including the
     17 next paragraph) shall be included in all copies or substantial
     18 portions of the Software.
     19 
     20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     27 
     28 **************************************************************************/
     29 
     30 /*
     31  * Authors:
     32  *   Keith Whitwell <keith (at) tungstengraphics.com>
     33  */
     34 
     35 #include "main/glheader.h"
     36 #include "main/imports.h"
     37 #include "main/mtypes.h"
     38 #include "main/macros.h"
     39 
     40 #include "swrast_setup/swrast_setup.h"
     41 #include "math/m_translate.h"
     42 #include "tnl/tnl.h"
     43 
     44 #include "radeon_context.h"
     45 #include "radeon_ioctl.h"
     46 #include "radeon_state.h"
     47 #include "radeon_swtcl.h"
     48 #include "radeon_maos.h"
     49 #include "radeon_tcl.h"
     50 
     51 static void emit_s0_vec(uint32_t *out, GLvoid *data, int stride, int count)
     52 {
     53    int i;
     54    if (RADEON_DEBUG & RADEON_VERTS)
     55       fprintf(stderr, "%s count %d stride %d\n",
     56 	      __FUNCTION__, count, stride);
     57 
     58    for (i = 0; i < count; i++) {
     59       out[0] = *(int *)data;
     60       out[1] = 0;
     61       out += 2;
     62       data += stride;
     63    }
     64 }
     65 
     66 static void emit_stq_vec(uint32_t *out, GLvoid *data, int stride, int count)
     67 {
     68    int i;
     69 
     70    if (RADEON_DEBUG & RADEON_VERTS)
     71       fprintf(stderr, "%s count %d stride %d\n",
     72 	      __FUNCTION__, count, stride);
     73 
     74    for (i = 0; i < count; i++) {
     75       out[0] = *(int *)data;
     76       out[1] = *(int *)(data+4);
     77       out[2] = *(int *)(data+12);
     78       out += 3;
     79       data += stride;
     80    }
     81 }
     82 
     83 static void emit_tex_vector(struct gl_context *ctx, struct radeon_aos *aos,
     84 			    GLvoid *data, int size, int stride, int count)
     85 {
     86    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
     87    int emitsize;
     88    uint32_t *out;
     89 
     90    if (RADEON_DEBUG & RADEON_VERTS)
     91       fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
     92 
     93    switch (size) {
     94    case 4: emitsize = 3; break;
     95    case 3: emitsize = 3; break;
     96    default: emitsize = 2; break;
     97    }
     98 
     99 
    100    if (stride == 0) {
    101       radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * 4, 32);
    102       count = 1;
    103       aos->stride = 0;
    104    }
    105    else {
    106       radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * count * 4, 32);
    107       aos->stride = emitsize;
    108    }
    109 
    110    aos->components = emitsize;
    111    aos->count = count;
    112 
    113    /* Emit the data
    114     */
    115    radeon_bo_map(aos->bo, 1);
    116    out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
    117    switch (size) {
    118    case 1:
    119       emit_s0_vec( out, data, stride, count );
    120       break;
    121    case 2:
    122       radeonEmitVec8( out, data, stride, count );
    123       break;
    124    case 3:
    125       radeonEmitVec12( out, data, stride, count );
    126       break;
    127    case 4:
    128       emit_stq_vec( out, data, stride, count );
    129       break;
    130    default:
    131       assert(0);
    132       exit(1);
    133       break;
    134    }
    135    radeon_bo_unmap(aos->bo);
    136 }
    137 
    138 
    139 
    140 
    141 /* Emit any changed arrays to new GART memory, re-emit a packet to
    142  * update the arrays.
    143  */
    144 void radeonEmitArrays( struct gl_context *ctx, GLuint inputs )
    145 {
    146    r100ContextPtr rmesa = R100_CONTEXT( ctx );
    147    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
    148    GLuint nr = 0;
    149    GLuint vfmt = 0;
    150    GLuint count = VB->Count;
    151    GLuint vtx, unit;
    152 
    153 #if 0
    154    if (RADEON_DEBUG & RADEON_VERTS)
    155       _tnl_print_vert_flags( __FUNCTION__, inputs );
    156 #endif
    157 
    158    if (1) {
    159       if (!rmesa->tcl.obj.buf)
    160 	rcommon_emit_vector( ctx,
    161 			     &(rmesa->tcl.aos[nr]),
    162 			     (char *)VB->AttribPtr[_TNL_ATTRIB_POS]->data,
    163 			     VB->AttribPtr[_TNL_ATTRIB_POS]->size,
    164 			     VB->AttribPtr[_TNL_ATTRIB_POS]->stride,
    165 			     count);
    166 
    167       switch( VB->AttribPtr[_TNL_ATTRIB_POS]->size ) {
    168       case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
    169       case 3: vfmt |= RADEON_CP_VC_FRMT_Z;
    170       case 2: vfmt |= RADEON_CP_VC_FRMT_XY;
    171       default:
    172          break;
    173       }
    174       nr++;
    175    }
    176 
    177 
    178    if (inputs & VERT_BIT_NORMAL) {
    179       if (!rmesa->tcl.norm.buf)
    180 	 rcommon_emit_vector( ctx,
    181 			      &(rmesa->tcl.aos[nr]),
    182 			      (char *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data,
    183 			      3,
    184 			      VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride,
    185 			      count);
    186 
    187       vfmt |= RADEON_CP_VC_FRMT_N0;
    188       nr++;
    189    }
    190 
    191    if (inputs & VERT_BIT_COLOR0) {
    192       int emitsize;
    193       if (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size == 4 &&
    194 	  (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride != 0 ||
    195 	   VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data[0][3] != 1.0)) {
    196 	 vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA;
    197 	 emitsize = 4;
    198       }
    199 
    200       else {
    201 	 vfmt |= RADEON_CP_VC_FRMT_FPCOLOR;
    202 	 emitsize = 3;
    203       }
    204 
    205       if (!rmesa->tcl.rgba.buf)
    206 	rcommon_emit_vector( ctx,
    207 			     &(rmesa->tcl.aos[nr]),
    208 			     (char *)VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data,
    209 			     emitsize,
    210 			     VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride,
    211 			     count);
    212 
    213       nr++;
    214    }
    215 
    216 
    217    if (inputs & VERT_BIT_COLOR1) {
    218       if (!rmesa->tcl.spec.buf) {
    219 
    220 	rcommon_emit_vector( ctx,
    221 			     &(rmesa->tcl.aos[nr]),
    222 			     (char *)VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data,
    223 			     3,
    224 			     VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride,
    225 			     count);
    226       }
    227 
    228       vfmt |= RADEON_CP_VC_FRMT_FPSPEC;
    229       nr++;
    230    }
    231 
    232 /* FIXME: not sure if this is correct. May need to stitch this together with
    233    secondary color. It seems odd that for primary color color and alpha values
    234    are emitted together but for secondary color not. */
    235    if (inputs & VERT_BIT_FOG) {
    236       if (!rmesa->tcl.fog.buf)
    237 	 rcommon_emit_vecfog( ctx,
    238 			      &(rmesa->tcl.aos[nr]),
    239 			      (char *)VB->AttribPtr[_TNL_ATTRIB_FOG]->data,
    240 			      VB->AttribPtr[_TNL_ATTRIB_FOG]->stride,
    241 			      count);
    242 
    243       vfmt |= RADEON_CP_VC_FRMT_FPFOG;
    244       nr++;
    245    }
    246 
    247 
    248    vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
    249 	  ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2));
    250 
    251    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
    252       if (inputs & VERT_BIT_TEX(unit)) {
    253 	 if (!rmesa->tcl.tex[unit].buf)
    254 	    emit_tex_vector( ctx,
    255 			     &(rmesa->tcl.aos[nr]),
    256 			     (char *)VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->data,
    257 			     VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size,
    258 			     VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->stride,
    259 			     count );
    260 	 nr++;
    261 
    262 	 vfmt |= RADEON_ST_BIT(unit);
    263          /* assume we need the 3rd coord if texgen is active for r/q OR at least
    264 	    3 coords are submitted. This may not be 100% correct */
    265          if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) {
    266 	    vtx |= RADEON_Q_BIT(unit);
    267 	    vfmt |= RADEON_Q_BIT(unit);
    268 	 }
    269 	 if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) )
    270 	    vtx |= RADEON_Q_BIT(unit);
    271 	 else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) &&
    272 	          ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) {
    273 	    GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3);
    274 	    if (((rmesa->NeedTexMatrix >> unit) & 1) &&
    275 		 (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
    276 	       radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
    277 	 }
    278       }
    279    }
    280 
    281    if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
    282       RADEON_STATECHANGE( rmesa, tcl );
    283       rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
    284    }
    285 
    286    rmesa->tcl.nr_aos_components = nr;
    287    rmesa->tcl.vertex_format = vfmt;
    288 }
    289 
    290