Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / r600 / evergreen_vertprog.c
1 /*
2  * Copyright (C) 2008-2009  Advanced Micro Devices, Inc.
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, sublicense,
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 shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21
22 /*
23  * Authors:
24  *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
25  */
26
27
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include "main/imports.h"
35 #include "main/mtypes.h"
36
37 #include "tnl/t_context.h"
38 #include "program/program.h"
39 #include "program/prog_parameter.h"
40 #include "program/prog_statevars.h"
41
42 #include "radeon_debug.h"
43 #include "r600_context.h"
44 #include "r600_cmdbuf.h"
45 #include "r600_emit.h"
46 #include "program/programopt.h"
47
48 #include "evergreen_vertprog.h"
49
50 unsigned int evergreen_Map_Vertex_Output(r700_AssemblerBase       *pAsm, 
51                                                    struct gl_vertex_program *mesa_vp,
52                                                    unsigned int unStart)
53 {
54     unsigned int i;
55         unsigned int unBit;
56         unsigned int unTotal = unStart;
57
58     //!!!!!!! THE ORDER MATCH FS INPUT
59
60         unBit = 1 << VERT_RESULT_HPOS;
61         if(mesa_vp->Base.OutputsWritten & unBit)
62         {
63                 pAsm->ucVP_OutputMap[VERT_RESULT_HPOS] = unTotal++;
64         }
65
66         unBit = 1 << VERT_RESULT_COL0;
67         if(mesa_vp->Base.OutputsWritten & unBit)
68         {
69                 pAsm->ucVP_OutputMap[VERT_RESULT_COL0] = unTotal++;
70         }
71
72         unBit = 1 << VERT_RESULT_COL1;
73         if(mesa_vp->Base.OutputsWritten & unBit)
74         {
75                 pAsm->ucVP_OutputMap[VERT_RESULT_COL1] = unTotal++;
76         }
77
78         //TODO : dealing back face.
79         unBit = 1 << VERT_RESULT_BFC0;
80         if(mesa_vp->Base.OutputsWritten & unBit)
81         {
82                 pAsm->ucVP_OutputMap[VERT_RESULT_BFC0] = unTotal++;
83         }
84
85         unBit = 1 << VERT_RESULT_BFC1;
86         if(mesa_vp->Base.OutputsWritten & unBit)
87         {
88                 pAsm->ucVP_OutputMap[VERT_RESULT_BFC1] = unTotal++;
89         }
90
91         //TODO : dealing fog.
92         unBit = 1 << VERT_RESULT_FOGC;
93         if(mesa_vp->Base.OutputsWritten & unBit)
94         {
95                 pAsm->ucVP_OutputMap[VERT_RESULT_FOGC] = unTotal++;
96         }
97
98         //TODO : dealing point size.
99         unBit = 1 << VERT_RESULT_PSIZ;
100         if(mesa_vp->Base.OutputsWritten & unBit)
101         {
102                 pAsm->ucVP_OutputMap[VERT_RESULT_PSIZ] = unTotal++;
103         }
104
105         for(i=0; i<8; i++)
106         {
107                 unBit = 1 << (VERT_RESULT_TEX0 + i);
108                 if(mesa_vp->Base.OutputsWritten & unBit)
109                 {
110                         pAsm->ucVP_OutputMap[VERT_RESULT_TEX0 + i] = unTotal++;
111                 }
112         }
113
114     for(i=VERT_RESULT_VAR0; i<VERT_RESULT_MAX; i++)
115         {
116                 unBit = 1 << i;
117                 if(mesa_vp->Base.OutputsWritten & unBit)
118                 {
119                         pAsm->ucVP_OutputMap[i] = unTotal++;
120                 }
121         }
122
123         return (unTotal - unStart);
124 }
125
126 unsigned int evergreen_Map_Vertex_Input(r700_AssemblerBase       *pAsm, 
127                                           struct gl_vertex_program *mesa_vp,
128                                           unsigned int unStart)
129 {
130         int i;
131         unsigned int unBit;
132         unsigned int unTotal = unStart;
133         for(i=0; i<VERT_ATTRIB_MAX; i++)
134         {
135                 unBit = 1 << i;
136                 if(mesa_vp->Base.InputsRead & unBit)
137                 {
138                         pAsm->ucVP_AttributeMap[i] = unTotal++;
139                 }
140         }
141         return (unTotal - unStart);
142 }
143
144 GLboolean evergreen_Process_Vertex_Program_Vfetch_Instructions(
145                                                 struct evergreen_vertex_program *vp,
146                                                 struct gl_vertex_program   *mesa_vp)
147 {
148         int i;
149     unsigned int unBit;
150         VTX_FETCH_METHOD vtxFetchMethod;
151         vtxFetchMethod.bEnableMini          = GL_FALSE;
152         vtxFetchMethod.mega_fetch_remainder = 0;
153
154         for(i=0; i<VERT_ATTRIB_MAX; i++)
155         {
156                 unBit = 1 << i;
157                 if(mesa_vp->Base.InputsRead & unBit)
158                 {
159                         assemble_vfetch_instruction(&vp->r700AsmCode,
160                                                     i,
161                                                     vp->r700AsmCode.ucVP_AttributeMap[i],
162                                                     vp->aos_desc[i].size,
163                                                     vp->aos_desc[i].type,
164                                                     &vtxFetchMethod);
165                 }
166         }
167         
168         return GL_TRUE;
169 }
170
171 GLboolean evergreen_Process_Vertex_Program_Vfetch_Instructions2(
172     struct gl_context *ctx,
173         struct evergreen_vertex_program *vp,
174         struct gl_vertex_program   *mesa_vp)
175 {
176     int i;
177     context_t *context = R700_CONTEXT(ctx);
178
179     VTX_FETCH_METHOD vtxFetchMethod;
180         vtxFetchMethod.bEnableMini          = GL_FALSE;
181         vtxFetchMethod.mega_fetch_remainder = 0;
182
183     for(i=0; i<context->nNumActiveAos; i++)
184     {
185         EG_assemble_vfetch_instruction(&vp->r700AsmCode,
186                                       vp->r700AsmCode.ucVP_AttributeMap[context->stream_desc[i].element],
187                                       context->stream_desc[i].type,
188                                       context->stream_desc[i].size,
189                                       context->stream_desc[i].element,
190                                       context->stream_desc[i]._signed,
191                                       context->stream_desc[i].normalize,
192                                       context->stream_desc[i].format,
193                                      &vtxFetchMethod);
194     }
195
196     return GL_TRUE;
197 }
198
199 void evergreen_Map_Vertex_Program(struct gl_context *ctx,
200                         struct evergreen_vertex_program *vp,
201                                                 struct gl_vertex_program   *mesa_vp)
202 {
203     r700_AssemblerBase *pAsm = &(vp->r700AsmCode);
204         unsigned int num_inputs;
205
206         // R0 will always be used for index into vertex buffer
207         pAsm->number_used_registers = 1;
208         pAsm->starting_vfetch_register_number = pAsm->number_used_registers;
209
210     // Map Inputs: Add 1 to mapping since R0 is used for index
211         num_inputs = evergreen_Map_Vertex_Input(pAsm, mesa_vp, pAsm->number_used_registers);
212         pAsm->number_used_registers += num_inputs;
213
214         // Create VFETCH instructions for inputs
215         if (GL_TRUE != evergreen_Process_Vertex_Program_Vfetch_Instructions2(ctx, vp, mesa_vp) )
216         {
217                 radeon_error("Calling evergreen_Process_Vertex_Program_Vfetch_Instructions2 return error. \n");
218                 return;
219         }
220
221         // Map Outputs
222         pAsm->number_of_exports = evergreen_Map_Vertex_Output(pAsm, mesa_vp, pAsm->number_used_registers);
223
224         pAsm->starting_export_register_number = pAsm->number_used_registers;
225
226         pAsm->number_used_registers += pAsm->number_of_exports;
227
228     /* Map temporary registers (GPRs) */
229     pAsm->starting_temp_register_number = pAsm->number_used_registers;
230
231     if(mesa_vp->Base.NumNativeTemporaries >= mesa_vp->Base.NumTemporaries)
232     {   /* arb uses NumNativeTemporaries */
233         pAsm->number_used_registers += mesa_vp->Base.NumNativeTemporaries;
234     }
235     else
236     {   /* fix func t_vp uses NumTemporaries */
237         pAsm->number_used_registers += mesa_vp->Base.NumTemporaries;
238     }
239
240     pAsm->flag_reg_index = pAsm->number_used_registers++;
241
242     pAsm->uFirstHelpReg = pAsm->number_used_registers;
243 }
244
245 GLboolean evergreen_Find_Instruction_Dependencies_vp(struct evergreen_vertex_program *vp,
246                                                                 struct gl_vertex_program   *mesa_vp)
247 {
248     GLuint i, j;
249     GLint * puiTEMPwrites;
250     struct prog_instruction *pILInst;
251     InstDeps         *pInstDeps;
252
253     puiTEMPwrites = (GLint*) MALLOC(sizeof(GLuint)*mesa_vp->Base.NumTemporaries);
254     for(i=0; i<mesa_vp->Base.NumTemporaries; i++)
255     {
256         puiTEMPwrites[i] = -1;
257     }
258
259     pInstDeps = (InstDeps*)MALLOC(sizeof(InstDeps)*mesa_vp->Base.NumInstructions);
260
261     for(i=0; i<mesa_vp->Base.NumInstructions; i++)
262     {
263         pInstDeps[i].nDstDep = -1;
264         pILInst = &(mesa_vp->Base.Instructions[i]);
265
266         //Dst
267         if(pILInst->DstReg.File == PROGRAM_TEMPORARY)
268         {
269             //Set lastwrite for the temp
270             puiTEMPwrites[pILInst->DstReg.Index] = i;
271         }
272
273         //Src
274         for(j=0; j<3; j++)
275         {
276             if(pILInst->SrcReg[j].File == PROGRAM_TEMPORARY)
277             {
278                 //Set dep.
279                 pInstDeps[i].nSrcDeps[j] = puiTEMPwrites[pILInst->SrcReg[j].Index];
280             }
281             else
282             {
283                 pInstDeps[i].nSrcDeps[j] = -1;
284             }
285         }
286     }
287
288     vp->r700AsmCode.pInstDeps = pInstDeps;
289
290     FREE(puiTEMPwrites);
291
292     return GL_TRUE;
293 }
294
295 struct evergreen_vertex_program* evergreenTranslateVertexShader(struct gl_context *ctx,
296                                                       struct gl_vertex_program *mesa_vp)
297 {
298         context_t *context = EVERGREEN_CONTEXT(ctx);
299
300         struct evergreen_vertex_program *vp;
301         unsigned int i;
302
303         vp = calloc(1, sizeof(*vp));
304         vp->mesa_program = _mesa_clone_vertex_program(ctx, mesa_vp);
305     
306     vp->constbo0 = NULL;
307
308         if (mesa_vp->IsPositionInvariant)
309         {
310                 _mesa_insert_mvp_code(ctx, vp->mesa_program);
311         }
312
313         for(i=0; i<context->nNumActiveAos; i++)
314         {
315                 vp->aos_desc[i].size   = context->stream_desc[i].size;
316                 vp->aos_desc[i].stride = context->stream_desc[i].stride;
317                 vp->aos_desc[i].type   = context->stream_desc[i].type;
318                 vp->aos_desc[i].format = context->stream_desc[i].format;
319         }
320
321         if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
322         {
323                 vp->r700AsmCode.bR6xx = 1;
324         }
325
326         //Init_Program
327         Init_r700_AssemblerBase(SPT_VP, &(vp->r700AsmCode), &(vp->r700Shader) );
328         
329     vp->r700AsmCode.bUseMemConstant = GL_TRUE;  
330     vp->r700AsmCode.unAsic = 8;
331
332         evergreen_Map_Vertex_Program(ctx, vp, vp->mesa_program );
333
334         if(GL_FALSE == evergreen_Find_Instruction_Dependencies_vp(vp, vp->mesa_program))
335         {
336                 return NULL;
337         }
338
339     InitShaderProgram(&(vp->r700AsmCode));
340
341     for(i=0; i < MAX_SAMPLERS; i++)
342     {
343         vp->r700AsmCode.SamplerUnits[i] = vp->mesa_program->Base.SamplerUnits[i];
344     }
345
346     vp->r700AsmCode.unCurNumILInsts = vp->mesa_program->Base.NumInstructions;
347
348         if(GL_FALSE == AssembleInstr(0,
349                                  0,
350                                  vp->mesa_program->Base.NumInstructions,
351                                  &(vp->mesa_program->Base.Instructions[0]),
352                                  &(vp->r700AsmCode)) )
353         {
354                 return NULL;
355         }
356
357     if(GL_FALSE == Process_Vertex_Exports(&(vp->r700AsmCode), vp->mesa_program->Base.OutputsWritten) )
358     {
359         return NULL;
360     }
361
362     if( GL_FALSE == RelocProgram(&(vp->r700AsmCode), &(vp->mesa_program->Base)) )
363     {
364         return GL_FALSE;
365     }
366
367     vp->r700Shader.nRegs = (vp->r700AsmCode.number_used_registers == 0) ? 0 
368                          : (vp->r700AsmCode.number_used_registers - 1);
369
370         vp->r700Shader.nParamExports = vp->r700AsmCode.number_of_exports;
371
372     vp->translated = GL_TRUE;
373
374         return vp;
375 }
376
377 void evergreenSelectVertexShader(struct gl_context *ctx)
378 {
379     context_t *context = EVERGREEN_CONTEXT(ctx);
380     struct evergreen_vertex_program_cont *vpc;
381     struct evergreen_vertex_program *vp;
382     unsigned int i;
383     GLboolean match;
384     GLbitfield InputsRead;
385
386     vpc = (struct evergreen_vertex_program_cont *)ctx->VertexProgram._Current;
387
388     InputsRead = vpc->mesa_program.Base.InputsRead;
389     if (vpc->mesa_program.IsPositionInvariant)
390     {
391         InputsRead |= VERT_BIT_POS;
392     }
393
394     for (vp = vpc->progs; vp; vp = vp->next)
395     {
396         match = GL_TRUE;
397         for(i=0; i<context->nNumActiveAos; i++)
398         {
399                 if (vp->aos_desc[i].size != context->stream_desc[i].size ||
400                     vp->aos_desc[i].format != context->stream_desc[i].format)
401                 {
402                         match = GL_FALSE;
403                         break;
404                 }
405         }
406         if (match)
407         {
408                 context->selected_vp = (struct r700_vertex_program *) vp;
409                 return;
410         }
411     }
412
413     vp = evergreenTranslateVertexShader(ctx, &(vpc->mesa_program));
414     if(!vp)
415     {
416         radeon_error("Failed to translate vertex shader. \n");
417         return;
418     }
419     vp->next = vpc->progs;
420     vpc->progs = vp;
421     context->selected_vp = (struct r700_vertex_program *) vp;
422     return;
423 }
424
425 int evergreen_getTypeSize(GLenum type)
426 {
427     switch (type) 
428     {
429     case GL_DOUBLE:
430         return sizeof(GLdouble);
431     case GL_FLOAT:
432         return sizeof(GLfloat);
433     case GL_INT:
434         return sizeof(GLint);
435     case GL_UNSIGNED_INT:
436         return sizeof(GLuint);
437     case GL_SHORT:
438         return sizeof(GLshort);
439     case GL_UNSIGNED_SHORT:
440         return sizeof(GLushort);
441     case GL_BYTE:
442         return sizeof(GLbyte);
443     case GL_UNSIGNED_BYTE:
444         return sizeof(GLubyte);
445     default:
446         assert(0);
447         return 0;
448     }
449 }
450
451 static void evergreenTranslateAttrib(struct gl_context *ctx, GLuint unLoc, int count, const struct gl_client_array *input)
452 {
453     context_t *context = EVERGREEN_CONTEXT(ctx);
454     
455     StreamDesc * pStreamDesc = &(context->stream_desc[context->nNumActiveAos]);
456
457         GLuint stride;
458
459         stride = (input->StrideB == 0) ? evergreen_getTypeSize(input->Type) * input->Size 
460                                    : input->StrideB;
461
462     if (input->Type == GL_DOUBLE || input->Type == GL_UNSIGNED_INT || input->Type == GL_INT
463 #if MESA_BIG_ENDIAN
464         || evergreen_getTypeSize(input->Type) != 4
465 #endif
466         )
467     {
468         pStreamDesc->type = GL_FLOAT;
469
470         if (input->StrideB == 0) 
471         {
472                 pStreamDesc->stride = 0;
473         } 
474         else 
475         {
476                 pStreamDesc->stride = sizeof(GLfloat) * input->Size;
477         }
478         pStreamDesc->dwords = input->Size;
479         pStreamDesc->is_named_bo = GL_FALSE;
480     } 
481     else 
482     {
483         pStreamDesc->type = input->Type;
484         pStreamDesc->dwords = (evergreen_getTypeSize(input->Type) * input->Size + 3)/ 4;
485         if (!input->BufferObj->Name) 
486         {
487             if (input->StrideB == 0) 
488             {
489                 pStreamDesc->stride = 0;
490             } 
491             else 
492             {
493                 pStreamDesc->stride = (evergreen_getTypeSize(pStreamDesc->type) * input->Size + 3) & ~3;
494             }
495
496             pStreamDesc->is_named_bo = GL_FALSE;
497         }
498     }
499
500         pStreamDesc->size = input->Size;
501         pStreamDesc->dst_loc = context->nNumActiveAos;
502         pStreamDesc->element = unLoc;
503         pStreamDesc->format = input->Format;
504
505         switch (pStreamDesc->type) 
506         { //GetSurfaceFormat
507         case GL_FLOAT:
508                 pStreamDesc->_signed = 0;
509                 pStreamDesc->normalize = GL_FALSE;
510                 break;
511         case GL_SHORT:
512                 pStreamDesc->_signed = 1;
513                 pStreamDesc->normalize = input->Normalized;
514                 break;
515         case GL_BYTE:
516                 pStreamDesc->_signed = 1;
517                 pStreamDesc->normalize = input->Normalized;
518                 break;
519         case GL_UNSIGNED_SHORT:
520                 pStreamDesc->_signed = 0;
521                 pStreamDesc->normalize = input->Normalized;
522                 break;
523         case GL_UNSIGNED_BYTE:
524                 pStreamDesc->_signed = 0;
525                 pStreamDesc->normalize = input->Normalized;
526                 break;
527         default:
528         case GL_INT:
529         case GL_UNSIGNED_INT:
530         case GL_DOUBLE: 
531                 assert(0);
532                 break;
533         }
534         context->nNumActiveAos++;
535 }
536
537 void evergreenSetVertexFormat(struct gl_context *ctx, const struct gl_client_array *arrays[], int count)
538 {
539     context_t *context = EVERGREEN_CONTEXT(ctx);
540     struct evergreen_vertex_program *vpc
541            = (struct evergreen_vertex_program *)ctx->VertexProgram._Current;
542
543     struct gl_vertex_program * mesa_vp = (struct gl_vertex_program *)&(vpc->mesa_program);
544     unsigned int unLoc = 0;
545     unsigned int unBit = mesa_vp->Base.InputsRead;
546     context->nNumActiveAos = 0;
547
548     if (mesa_vp->IsPositionInvariant)
549     {
550         unBit |= VERT_BIT_POS;
551     }
552
553     while(unBit) 
554     {
555         if(unBit & 1)
556         {
557             evergreenTranslateAttrib(ctx, unLoc, count, arrays[unLoc]);
558         }
559
560         unBit >>= 1;
561         ++unLoc;
562     }
563     context->radeon.tcl.aos_count = context->nNumActiveAos;
564 }
565
566 void * evergreenGetActiveVpShaderBo(struct gl_context * ctx)
567 {
568     context_t *context = EVERGREEN_CONTEXT(ctx);
569     struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *) context->selected_vp;
570
571     if (vp)
572         return vp->shaderbo;
573     else
574         return NULL;
575 }
576
577 void * evergreenGetActiveVpShaderConstBo(struct gl_context * ctx)
578 {
579     context_t *context = EVERGREEN_CONTEXT(ctx);
580     struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *) context->selected_vp;
581
582     if (vp)
583         return vp->constbo0;
584     else
585         return NULL;
586 }
587
588 GLboolean evergreenSetupVertexProgram(struct gl_context * ctx)
589 {
590     context_t *context = EVERGREEN_CONTEXT(ctx);
591     EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
592     struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *) context->selected_vp;
593
594     if(GL_FALSE == vp->loaded)
595     {
596             if(vp->r700Shader.bNeedsAssembly == GL_TRUE)
597             {
598                     Assemble( &(vp->r700Shader) );
599             }
600
601         /* Load vp to gpu */
602         r600EmitShader(ctx,
603                        &(vp->shaderbo),
604                        (GLvoid *)(vp->r700Shader.pProgram),
605                        vp->r700Shader.uShaderBinaryDWORDSize,
606                        "VS");
607    
608         vp->loaded = GL_TRUE;
609     }
610
611     EVERGREEN_STATECHANGE(context, vs);      
612     
613     /* TODO : enable this after MemUse fixed *=
614     (context->chipobj.MemUse)(context, vp->shadercode.buf->id);
615     */       
616
617     evergreen->SQ_PGM_RESOURCES_VS.u32All = 0;
618     SETbit(evergreen->SQ_PGM_RESOURCES_VS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit);
619     
620     evergreen->vs.SQ_ALU_CONST_CACHE_VS_0.u32All = 0; /* set from buffer object. */
621     
622     evergreen->vs.SQ_PGM_START_VS.u32All = 0;
623
624     SETfield(evergreen->SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.nRegs + 1,
625              NUM_GPRS_shift, NUM_GPRS_mask);
626
627     if(vp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */
628         {
629         SETfield(evergreen->SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.uStackSize,
630                  STACK_SIZE_shift, STACK_SIZE_mask);
631     }
632
633     EVERGREEN_STATECHANGE(context, spi);
634
635     SETfield(evergreen->SPI_VS_OUT_CONFIG.u32All,
636              vp->r700Shader.nParamExports ? (vp->r700Shader.nParamExports - 1) : 0,
637              VS_EXPORT_COUNT_shift, VS_EXPORT_COUNT_mask);
638     SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, vp->r700Shader.nParamExports,
639              NUM_INTERP_shift, NUM_INTERP_mask);
640
641     /*
642     SETbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
643     CLEARbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
644     */
645
646     return GL_TRUE;
647 }
648
649 GLboolean evergreenSetupVPconstants(struct gl_context * ctx)
650 {
651     context_t *context = EVERGREEN_CONTEXT(ctx);
652     EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
653     struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *) context->selected_vp;
654
655     struct gl_program_parameter_list *paramList;
656     unsigned int unNumParamData;
657     unsigned int ui;
658     int alloc_size;
659
660     /* sent out shader constants. */
661     paramList = vp->mesa_program->Base.Parameters;
662
663     if(NULL != paramList) {
664         /* vp->mesa_program was cloned, not updated by glsl shader api. */
665         /* _mesa_reference_program has already checked glsl shProg is ok and set ctx->VertexProgem._Current */
666         /* so, use ctx->VertexProgem._Current */       
667         struct gl_program_parameter_list *paramListOrginal = 
668                          ctx->VertexProgram._Current->Base.Parameters;
669          
670             _mesa_load_state_parameters(ctx, paramList);
671
672             if (paramList->NumParameters > EVERGREEN_MAX_DX9_CONSTS)
673                     return GL_FALSE;
674
675             EVERGREEN_STATECHANGE(context, vs);
676
677             evergreen->vs.num_consts = paramList->NumParameters;
678
679             unNumParamData = paramList->NumParameters;
680
681             /* alloc multiple of 16 constants */
682             alloc_size = ((unNumParamData * 4 * 4) + 255) & ~255;
683
684             for(ui=0; ui<unNumParamData; ui++) {
685             if(paramList->Parameters[ui].Type == PROGRAM_UNIFORM) 
686             {
687                 evergreen->vs.consts[ui][0].f32All = paramListOrginal->ParameterValues[ui][0];
688                         evergreen->vs.consts[ui][1].f32All = paramListOrginal->ParameterValues[ui][1];
689                         evergreen->vs.consts[ui][2].f32All = paramListOrginal->ParameterValues[ui][2];
690                         evergreen->vs.consts[ui][3].f32All = paramListOrginal->ParameterValues[ui][3];
691             }
692             else
693             {
694                         evergreen->vs.consts[ui][0].f32All = paramList->ParameterValues[ui][0];
695                         evergreen->vs.consts[ui][1].f32All = paramList->ParameterValues[ui][1];
696                         evergreen->vs.consts[ui][2].f32All = paramList->ParameterValues[ui][2];
697                         evergreen->vs.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
698             }
699             }
700
701         radeonAllocDmaRegion(&context->radeon, 
702                              &context->vp_Constbo, 
703                              &context->vp_bo_offset, 
704                              alloc_size,
705                              256);        
706         r600EmitShaderConsts(ctx,
707                              context->vp_Constbo,
708                              context->vp_bo_offset,
709                              (GLvoid *)&(evergreen->vs.consts[0][0]),
710                              unNumParamData * 4 * 4);
711     } else
712             evergreen->vs.num_consts = 0;
713
714     COMPILED_SUB * pCompiledSub;
715     GLuint uj;
716     GLuint unConstOffset = evergreen->vs.num_consts;
717     for(ui=0; ui<vp->r700AsmCode.unNumPresub; ui++)
718     {
719         pCompiledSub = vp->r700AsmCode.presubs[ui].pCompiledSub;
720
721         evergreen->vs.num_consts += pCompiledSub->NumParameters;
722
723         for(uj=0; uj<pCompiledSub->NumParameters; uj++)
724         {
725             evergreen->vs.consts[uj + unConstOffset][0].f32All = pCompiledSub->ParameterValues[uj][0];
726                     evergreen->vs.consts[uj + unConstOffset][1].f32All = pCompiledSub->ParameterValues[uj][1];
727                     evergreen->vs.consts[uj + unConstOffset][2].f32All = pCompiledSub->ParameterValues[uj][2];
728                     evergreen->vs.consts[uj + unConstOffset][3].f32All = pCompiledSub->ParameterValues[uj][3];
729         }
730         unConstOffset += pCompiledSub->NumParameters;
731     }
732
733     return GL_TRUE;
734 }
735