Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright 2012 Red Hat 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 in
12
 * all copies or substantial portions of the Software.
13
 *
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 * OTHER DEALINGS IN THE SOFTWARE.
21
 *
22
 * Authors: Ben Skeggs
23
 *
24
 */
25
 
26
#include "util/u_dynarray.h"
27
#include "tgsi/tgsi_parse.h"
28
 
29
#include "nouveau/nv_object.xml.h"
30
#include "nv30-40_3d.xml.h"
31
#include "nv30_context.h"
32
#include "nv30_state.h"
33
 
34
static void
35
nv30_vertprog_destroy(struct nv30_vertprog *vp)
36
{
37
   util_dynarray_fini(&vp->branch_relocs);
38
   nouveau_heap_free(&vp->exec);
39
   FREE(vp->insns);
40
   vp->insns = NULL;
41
   vp->nr_insns = 0;
42
 
43
   util_dynarray_fini(&vp->const_relocs);
44
   nouveau_heap_free(&vp->data);
45
   FREE(vp->consts);
46
   vp->consts = NULL;
47
   vp->nr_consts = 0;
48
 
49
   vp->translated = FALSE;
50
}
51
 
52
void
53
nv30_vertprog_validate(struct nv30_context *nv30)
54
{
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;
61
   unsigned i;
62
 
63
   if (nv30->dirty & NV30_NEW_FRAGPROG) {
64
      if (memcmp(vp->texcoord, fp->texcoord, sizeof(vp->texcoord))) {
65
         if (vp->translated)
66
            nv30_vertprog_destroy(vp);
67
         memcpy(vp->texcoord, fp->texcoord, sizeof(vp->texcoord));
68
      }
69
   }
70
 
71
   if (nv30->rast && nv30->rast->pipe.clip_plane_enable != vp->enabled_ucps) {
72
      vp->enabled_ucps = nv30->rast->pipe.clip_plane_enable;
73
      if (vp->translated)
74
         nv30_vertprog_destroy(vp);
75
   }
76
 
77
   if (!vp->translated) {
78
      vp->translated = _nvfx_vertprog_translate(nv30, vp);
79
      if (!vp->translated) {
80
         nv30->draw_flags |= NV30_NEW_VERTPROG;
81
         return;
82
      }
83
      nv30->dirty |= NV30_NEW_VERTPROG;
84
   }
85
 
86
   if (!vp->exec) {
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;
91
 
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);
96
         }
97
 
98
         if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) {
99
            nv30->draw_flags |= NV30_NEW_VERTPROG;
100
            return;
101
         }
102
      }
103
 
104
      if (eng3d->oclass < NV40_3D_CLASS) {
105
         while (nr_reloc--) {
106
            inst     = vp->insns[reloc->location].data;
107
            target   = vp->exec->start + reloc->target;
108
 
109
            inst[2] &= ~0x000007fc;
110
            inst[2] |= target << 2;
111
            reloc++;
112
         }
113
      } else {
114
         while (nr_reloc--) {
115
            inst     = vp->insns[reloc->location].data;
116
            target   = vp->exec->start + reloc->target;
117
 
118
            inst[2] &= ~0x0000003f;
119
            inst[2] |= target >> 3;
120
            inst[3] &= ~0xe0000000;
121
            inst[3] |= target << 29;
122
            reloc++;
123
         }
124
      }
125
 
126
      upload_code = TRUE;
127
   }
128
 
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;
134
 
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);
139
         }
140
 
141
         if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) {
142
            nv30->draw_flags |= NV30_NEW_VERTPROG;
143
            return;
144
         }
145
      }
146
 
147
      if (eng3d->oclass < NV40_3D_CLASS) {
148
         while (nr_reloc--) {
149
            inst     = vp->insns[reloc->location].data;
150
            target   = vp->data->start + reloc->target;
151
 
152
            inst[1] &= ~0x0007fc000;
153
            inst[1] |= (target & 0x1ff) << 14;
154
            reloc++;
155
         }
156
      } else {
157
         while (nr_reloc--) {
158
            inst     = vp->insns[reloc->location].data;
159
            target   = vp->data->start + reloc->target;
160
 
161
            inst[1] &= ~0x0001ff000;
162
            inst[1] |= (target & 0x1ff) << 12;
163
            reloc++;
164
         }
165
      }
166
 
167
      upload_code = TRUE;
168
      upload_data = TRUE;
169
   }
170
 
171
   if (vp->nr_consts) {
172
      struct nv04_resource *res = nv04_resource(nv30->vertprog.constbuf);
173
 
174
      for (i = 0; i < vp->nr_consts; i++) {
175
         struct nv30_vertprog_data *data = &vp->consts[i];
176
 
177
         if (data->index < 0) {
178
            if (!upload_data)
179
               continue;
180
         } else {
181
            float *constbuf = (float *)res->data;
182
            if (!upload_data &&
183
                !memcmp(data->value, &constbuf[data->index * 4], 16))
184
               continue;
185
            memcpy(data->value, &constbuf[data->index * 4], 16);
186
         }
187
 
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);
191
      }
192
   }
193
 
194
   if (upload_code) {
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);
200
      }
201
   }
202
 
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 */
209
      } else {
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);
215
      }
216
   }
217
}
218
 
219
static void *
220
nv30_vp_state_create(struct pipe_context *pipe,
221
                     const struct pipe_shader_state *cso)
222
{
223
   struct nv30_vertprog *vp = CALLOC_STRUCT(nv30_vertprog);
224
   if (!vp)
225
      return NULL;
226
 
227
   vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
228
   tgsi_scan_shader(vp->pipe.tokens, &vp->info);
229
   return vp;
230
}
231
 
232
static void
233
nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso)
234
{
235
   struct nv30_vertprog *vp = hwcso;
236
 
237
   if (vp->translated)
238
      nv30_vertprog_destroy(vp);
239
   FREE((void *)vp->pipe.tokens);
240
   FREE(vp);
241
}
242
 
243
static void
244
nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso)
245
{
246
   struct nv30_context *nv30 = nv30_context(pipe);
247
 
248
   nv30->vertprog.program = hwcso;
249
   nv30->dirty |= NV30_NEW_VERTPROG;
250
}
251
 
252
void
253
nv30_vertprog_init(struct pipe_context *pipe)
254
{
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;
258
}