2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "util/u_dynarray.h"
27 #include "tgsi/tgsi_parse.h"
29 #include "nouveau/nv_object.xml.h"
30 #include "nv30-40_3d.xml.h"
31 #include "nv30_context.h"
32 #include "nv30_state.h"
35 nv30_vertprog_destroy(struct nv30_vertprog
*vp
)
37 util_dynarray_fini(&vp
->branch_relocs
);
38 nouveau_heap_free(&vp
->exec
);
43 util_dynarray_fini(&vp
->const_relocs
);
44 nouveau_heap_free(&vp
->data
);
49 vp
->translated
= FALSE
;
53 nv30_vertprog_validate(struct nv30_context
*nv30
)
55 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
56 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
57 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
58 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
59 boolean upload_code
= FALSE
;
60 boolean upload_data
= FALSE
;
63 if (nv30
->dirty
& NV30_NEW_FRAGPROG
) {
64 if (memcmp(vp
->texcoord
, fp
->texcoord
, sizeof(vp
->texcoord
))) {
66 nv30_vertprog_destroy(vp
);
67 memcpy(vp
->texcoord
, fp
->texcoord
, sizeof(vp
->texcoord
));
71 if (nv30
->rast
&& nv30
->rast
->pipe
.clip_plane_enable
!= vp
->enabled_ucps
) {
72 vp
->enabled_ucps
= nv30
->rast
->pipe
.clip_plane_enable
;
74 nv30_vertprog_destroy(vp
);
77 if (!vp
->translated
) {
78 vp
->translated
= _nvfx_vertprog_translate(nv30
, vp
);
79 if (!vp
->translated
) {
80 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
83 nv30
->dirty
|= NV30_NEW_VERTPROG
;
87 struct nouveau_heap
*heap
= nv30
->screen
->vp_exec_heap
;
88 struct nv30_shader_reloc
*reloc
= vp
->branch_relocs
.data
;
89 unsigned nr_reloc
= vp
->branch_relocs
.size
/ sizeof(*reloc
);
90 uint32_t *inst
, target
;
92 if (nouveau_heap_alloc(heap
, vp
->nr_insns
, &vp
->exec
, &vp
->exec
)) {
93 while (heap
->next
&& heap
->size
< vp
->nr_insns
) {
94 struct nouveau_heap
**evict
= heap
->next
->priv
;
95 nouveau_heap_free(evict
);
98 if (nouveau_heap_alloc(heap
, vp
->nr_insns
, &vp
->exec
, &vp
->exec
)) {
99 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
104 if (eng3d
->oclass
< NV40_3D_CLASS
) {
106 inst
= vp
->insns
[reloc
->location
].data
;
107 target
= vp
->exec
->start
+ reloc
->target
;
109 inst
[2] &= ~0x000007fc;
110 inst
[2] |= target
<< 2;
115 inst
= vp
->insns
[reloc
->location
].data
;
116 target
= vp
->exec
->start
+ reloc
->target
;
118 inst
[2] &= ~0x0000003f;
119 inst
[2] |= target
>> 3;
120 inst
[3] &= ~0xe0000000;
121 inst
[3] |= target
<< 29;
129 if (vp
->nr_consts
&& !vp
->data
) {
130 struct nouveau_heap
*heap
= nv30
->screen
->vp_data_heap
;
131 struct nv30_shader_reloc
*reloc
= vp
->const_relocs
.data
;
132 unsigned nr_reloc
= vp
->const_relocs
.size
/ sizeof(*reloc
);
133 uint32_t *inst
, target
;
135 if (nouveau_heap_alloc(heap
, vp
->nr_consts
, vp
, &vp
->data
)) {
136 while (heap
->next
&& heap
->size
< vp
->nr_consts
) {
137 struct nv30_vertprog
*evp
= heap
->next
->priv
;
138 nouveau_heap_free(&evp
->data
);
141 if (nouveau_heap_alloc(heap
, vp
->nr_consts
, vp
, &vp
->data
)) {
142 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
147 if (eng3d
->oclass
< NV40_3D_CLASS
) {
149 inst
= vp
->insns
[reloc
->location
].data
;
150 target
= vp
->data
->start
+ reloc
->target
;
152 inst
[1] &= ~0x0007fc000;
153 inst
[1] |= (target
& 0x1ff) << 14;
158 inst
= vp
->insns
[reloc
->location
].data
;
159 target
= vp
->data
->start
+ reloc
->target
;
161 inst
[1] &= ~0x0001ff000;
162 inst
[1] |= (target
& 0x1ff) << 12;
172 struct nv04_resource
*res
= nv04_resource(nv30
->vertprog
.constbuf
);
174 for (i
= 0; i
< vp
->nr_consts
; i
++) {
175 struct nv30_vertprog_data
*data
= &vp
->consts
[i
];
177 if (data
->index
< 0) {
181 float *constbuf
= (float *)res
->data
;
183 !memcmp(data
->value
, &constbuf
[data
->index
* 4], 16))
185 memcpy(data
->value
, &constbuf
[data
->index
* 4], 16);
188 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_CONST_ID
), 5);
189 PUSH_DATA (push
, vp
->data
->start
+ i
);
190 PUSH_DATAp(push
, data
->value
, 4);
195 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_FROM_ID
), 1);
196 PUSH_DATA (push
, vp
->exec
->start
);
197 for (i
= 0; i
< vp
->nr_insns
; i
++) {
198 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
199 PUSH_DATAp(push
, vp
->insns
[i
].data
, 4);
203 if (nv30
->dirty
& (NV30_NEW_VERTPROG
| NV30_NEW_FRAGPROG
)) {
204 BEGIN_NV04(push
, NV30_3D(VP_START_FROM_ID
), 1);
205 PUSH_DATA (push
, vp
->exec
->start
);
206 if (eng3d
->oclass
< NV40_3D_CLASS
) {
207 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
208 PUSH_DATA (push
, 0x00000013); /* vp instead of ff, somehow */
210 BEGIN_NV04(push
, NV40_3D(VP_ATTRIB_EN
), 2);
211 PUSH_DATA (push
, vp
->ir
);
212 PUSH_DATA (push
, vp
->or | fp
->vp_or
);
213 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
214 PUSH_DATA (push
, 0x00000011);
220 nv30_vp_state_create(struct pipe_context
*pipe
,
221 const struct pipe_shader_state
*cso
)
223 struct nv30_vertprog
*vp
= CALLOC_STRUCT(nv30_vertprog
);
227 vp
->pipe
.tokens
= tgsi_dup_tokens(cso
->tokens
);
228 tgsi_scan_shader(vp
->pipe
.tokens
, &vp
->info
);
233 nv30_vp_state_delete(struct pipe_context
*pipe
, void *hwcso
)
235 struct nv30_vertprog
*vp
= hwcso
;
238 nv30_vertprog_destroy(vp
);
239 FREE((void *)vp
->pipe
.tokens
);
244 nv30_vp_state_bind(struct pipe_context
*pipe
, void *hwcso
)
246 struct nv30_context
*nv30
= nv30_context(pipe
);
248 nv30
->vertprog
.program
= hwcso
;
249 nv30
->dirty
|= NV30_NEW_VERTPROG
;
253 nv30_vertprog_init(struct pipe_context
*pipe
)
255 pipe
->create_vs_state
= nv30_vp_state_create
;
256 pipe
->bind_vs_state
= nv30_vp_state_bind
;
257 pipe
->delete_vs_state
= nv30_vp_state_delete
;