sync with tizen_2.2
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / drivers / svga / svga_state_tss.c
1 /**********************************************************
2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  **********************************************************/
25
26 #include "util/u_inlines.h"
27 #include "util/u_memory.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_math.h"
30
31 #include "svga_sampler_view.h"
32 #include "svga_winsys.h"
33 #include "svga_context.h"
34 #include "svga_state.h"
35 #include "svga_cmd.h"
36
37
38 void svga_cleanup_tss_binding(struct svga_context *svga)
39 {
40    int i;
41    unsigned count = MAX2( svga->curr.num_sampler_views,
42                           svga->state.hw_draw.num_views );
43
44    for (i = 0; i < count; i++) {
45       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
46
47       svga_sampler_view_reference(&view->v, NULL);
48       pipe_sampler_view_reference( &svga->curr.sampler_views[i], NULL );
49       pipe_resource_reference( &view->texture, NULL );
50
51       view->dirty = 1;
52    }
53 }
54
55
56 struct bind_queue {
57    struct {
58       unsigned unit;
59       struct svga_hw_view_state *view;
60    } bind[PIPE_MAX_SAMPLERS];
61
62    unsigned bind_count;
63 };
64
65
66 static enum pipe_error
67 update_tss_binding(struct svga_context *svga, 
68                    unsigned dirty )
69 {
70    boolean reemit = svga->rebind.texture_samplers;
71    unsigned i;
72    unsigned count = MAX2( svga->curr.num_sampler_views,
73                           svga->state.hw_draw.num_views );
74    unsigned min_lod;
75    unsigned max_lod;
76
77    struct bind_queue queue;
78
79    queue.bind_count = 0;
80    
81    for (i = 0; i < count; i++) {
82       const struct svga_sampler_state *s = svga->curr.sampler[i];
83       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
84       struct pipe_resource *texture = NULL;
85
86       /* get min max lod */
87       if (svga->curr.sampler_views[i]) {
88          min_lod = MAX2(s->view_min_lod, 0);
89          max_lod = MIN2(s->view_max_lod, svga->curr.sampler_views[i]->texture->last_level);
90          texture = svga->curr.sampler_views[i]->texture;
91       } else {
92          min_lod = 0;
93          max_lod = 0;
94       }
95
96       if (view->texture != texture ||
97           view->min_lod != min_lod ||
98           view->max_lod != max_lod) {
99
100          svga_sampler_view_reference(&view->v, NULL);
101          pipe_resource_reference( &view->texture, texture );
102
103          view->dirty = TRUE;
104          view->min_lod = min_lod;
105          view->max_lod = max_lod;
106
107          if (texture)
108             view->v = svga_get_tex_sampler_view(&svga->pipe, 
109                                                 texture, 
110                                                 min_lod,
111                                                 max_lod);
112       }
113
114       /*
115        * We need to reemit non-null texture bindings, even when they are not
116        * dirty, to ensure that the resources are paged in.
117        */
118
119       if (view->dirty ||
120           (reemit && view->v)) {
121          queue.bind[queue.bind_count].unit = i;
122          queue.bind[queue.bind_count].view = view;
123          queue.bind_count++;
124       } 
125       if (!view->dirty && view->v) {
126          svga_validate_sampler_view(svga, view->v);
127       }
128    }
129
130    svga->state.hw_draw.num_views = svga->curr.num_sampler_views;
131
132    if (queue.bind_count) {
133       SVGA3dTextureState *ts;
134
135       if (SVGA3D_BeginSetTextureState( svga->swc,
136                                        &ts,
137                                        queue.bind_count ) != PIPE_OK)
138          goto fail;
139
140       for (i = 0; i < queue.bind_count; i++) {
141          struct svga_winsys_surface *handle;
142
143          ts[i].stage = queue.bind[i].unit;
144          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
145
146          if (queue.bind[i].view->v) {
147             handle = queue.bind[i].view->v->handle;
148          }
149          else {
150             handle = NULL;
151          }
152          svga->swc->surface_relocation(svga->swc,
153                                        &ts[i].value,
154                                        handle,
155                                        SVGA_RELOC_READ);
156          
157          queue.bind[i].view->dirty = FALSE;
158       }
159
160       SVGA_FIFOCommitAll( svga->swc );
161    }
162
163    svga->rebind.texture_samplers = FALSE;
164
165    return 0;
166
167 fail:
168    return PIPE_ERROR_OUT_OF_MEMORY;
169 }
170
171
172 /*
173  * Rebind textures.
174  *
175  * Similar to update_tss_binding, but without any state checking/update.
176  *
177  * Called at the beginning of every new command buffer to ensure that
178  * non-dirty textures are properly paged-in.
179  */
180 enum pipe_error
181 svga_reemit_tss_bindings(struct svga_context *svga)
182 {
183    unsigned i;
184    enum pipe_error ret;
185    struct bind_queue queue;
186
187    assert(svga->rebind.texture_samplers);
188
189    queue.bind_count = 0;
190
191    for (i = 0; i < svga->state.hw_draw.num_views; i++) {
192       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
193
194       if (view->v) {
195          queue.bind[queue.bind_count].unit = i;
196          queue.bind[queue.bind_count].view = view;
197          queue.bind_count++;
198       }
199    }
200
201    if (queue.bind_count) {
202       SVGA3dTextureState *ts;
203
204       ret = SVGA3D_BeginSetTextureState(svga->swc,
205                                         &ts,
206                                         queue.bind_count);
207       if (ret != PIPE_OK) {
208          return ret;
209       }
210
211       for (i = 0; i < queue.bind_count; i++) {
212          struct svga_winsys_surface *handle;
213
214          ts[i].stage = queue.bind[i].unit;
215          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
216
217          assert(queue.bind[i].view->v);
218          handle = queue.bind[i].view->v->handle;
219          svga->swc->surface_relocation(svga->swc,
220                                        &ts[i].value,
221                                        handle,
222                                        SVGA_RELOC_READ);
223       }
224
225       SVGA_FIFOCommitAll(svga->swc);
226    }
227
228    svga->rebind.texture_samplers = FALSE;
229
230    return PIPE_OK;
231 }
232
233
234 struct svga_tracked_state svga_hw_tss_binding = {
235    "texture binding emit",
236    SVGA_NEW_TEXTURE_BINDING |
237    SVGA_NEW_SAMPLER,
238    update_tss_binding
239 };
240
241
242 /***********************************************************************
243  */
244
245 struct ts_queue {
246    unsigned ts_count;
247    SVGA3dTextureState ts[PIPE_MAX_SAMPLERS*SVGA3D_TS_MAX];
248 };
249
250
251 #define EMIT_TS(svga, unit, val, token, fail)                           \
252 do {                                                                    \
253    assert(unit < Elements(svga->state.hw_draw.ts));                     \
254    assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit]));  \
255    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
256       svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val );           \
257       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
258    }                                                                    \
259 } while (0)
260
261 #define EMIT_TS_FLOAT(svga, unit, fvalue, token, fail)                  \
262 do {                                                                    \
263    unsigned val = fui(fvalue);                                          \
264    assert(unit < Elements(svga->state.hw_draw.ts));                     \
265    assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit]));  \
266    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
267       svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val );           \
268       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
269    }                                                                    \
270 } while (0)
271
272
273 static INLINE void 
274 svga_queue_tss( struct ts_queue *q,
275                 unsigned unit,
276                 unsigned tss,
277                 unsigned value )
278 {
279    assert(q->ts_count < sizeof(q->ts)/sizeof(q->ts[0]));
280    q->ts[q->ts_count].stage = unit;
281    q->ts[q->ts_count].name = tss;
282    q->ts[q->ts_count].value = value;
283    q->ts_count++;
284 }
285
286
287 static enum pipe_error
288 update_tss(struct svga_context *svga, 
289            unsigned dirty )
290 {
291    unsigned i;
292    struct ts_queue queue;
293
294    queue.ts_count = 0;
295    for (i = 0; i < svga->curr.num_samplers; i++) {
296       if (svga->curr.sampler[i]) {
297          const struct svga_sampler_state *curr = svga->curr.sampler[i];
298
299          EMIT_TS(svga, i, curr->mipfilter, MIPFILTER, fail);
300          EMIT_TS(svga, i, curr->min_lod, TEXTURE_MIPMAP_LEVEL, fail);
301          EMIT_TS(svga, i, curr->magfilter, MAGFILTER, fail);
302          EMIT_TS(svga, i, curr->minfilter, MINFILTER, fail);
303          EMIT_TS(svga, i, curr->aniso_level, TEXTURE_ANISOTROPIC_LEVEL, fail);
304          EMIT_TS_FLOAT(svga, i, curr->lod_bias, TEXTURE_LOD_BIAS, fail);
305          EMIT_TS(svga, i, curr->addressu, ADDRESSU, fail);
306          EMIT_TS(svga, i, curr->addressw, ADDRESSW, fail);
307          EMIT_TS(svga, i, curr->bordercolor, BORDERCOLOR, fail);
308          // TEXCOORDINDEX -- hopefully not needed
309
310          if (svga->curr.tex_flags.flag_1d & (1 << i)) {
311             EMIT_TS(svga, i, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV, fail);
312          }
313          else
314             EMIT_TS(svga, i, curr->addressv, ADDRESSV, fail);
315
316          if (svga->curr.tex_flags.flag_srgb & (1 << i))
317             EMIT_TS_FLOAT(svga, i, 2.2f, GAMMA, fail);
318          else
319             EMIT_TS_FLOAT(svga, i, 1.0f, GAMMA, fail);
320
321       }
322    }
323  
324    if (queue.ts_count) {
325       SVGA3dTextureState *ts;
326
327       if (SVGA3D_BeginSetTextureState( svga->swc,
328                                        &ts,
329                                        queue.ts_count ) != PIPE_OK)
330          goto fail;
331
332       memcpy( ts,
333               queue.ts,
334               queue.ts_count * sizeof queue.ts[0]);
335       
336       SVGA_FIFOCommitAll( svga->swc );
337    }
338
339    return PIPE_OK;
340
341 fail:
342    /* XXX: need to poison cached hardware state on failure to ensure
343     * dirty state gets re-emitted.  Fix this by re-instating partial
344     * FIFOCommit command and only updating cached hw state once the
345     * initial allocation has succeeded.
346     */
347    memset(svga->state.hw_draw.ts, 0xcd, sizeof(svga->state.hw_draw.ts));
348
349    return PIPE_ERROR_OUT_OF_MEMORY;
350 }
351
352
353 struct svga_tracked_state svga_hw_tss = {
354    "texture state emit",
355    (SVGA_NEW_SAMPLER |
356     SVGA_NEW_TEXTURE_FLAGS),
357    update_tss
358 };
359