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