blob: 455b1733b8968806d86042fb86a581b88479bf9e [file] [log] [blame]
Jakob Bornecrantz31926332009-11-16 19:56:18 +01001/**********************************************************
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
José Fonseca28486882010-02-02 14:42:17 +000026#include "util/u_inlines.h"
José Fonsecae33447a2011-10-31 19:26:53 +000027#include "util/u_memory.h"
Jakob Bornecrantz31926332009-11-16 19:56:18 +010028#include "pipe/p_defines.h"
29#include "util/u_math.h"
30
Charmaine Leedbb5d2a2017-06-27 10:47:01 -060031#include "svga_resource_texture.h"
Keith Whitwell287c94e2010-04-10 16:05:54 +010032#include "svga_sampler_view.h"
Jakob Bornecrantz31926332009-11-16 19:56:18 +010033#include "svga_winsys.h"
34#include "svga_context.h"
Brian Paule0542512015-08-13 11:00:58 -070035#include "svga_shader.h"
Jakob Bornecrantz31926332009-11-16 19:56:18 +010036#include "svga_state.h"
37#include "svga_cmd.h"
38
Jakob Bornecrantz31926332009-11-16 19:56:18 +010039
Brian Paule0542512015-08-13 11:00:58 -070040/**
41 * Called when tearing down a context to free resources and samplers.
42 */
Jakob Bornecrantz31926332009-11-16 19:56:18 +010043void svga_cleanup_tss_binding(struct svga_context *svga)
44{
Brian Paulf5602c22016-08-29 10:15:36 -060045 const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
Brian Paul25cd2c22012-10-16 17:54:37 -060046 unsigned i;
Jakob Bornecrantz31926332009-11-16 19:56:18 +010047
Brian Paule0184b32016-04-25 09:34:40 -060048 for (i = 0; i < ARRAY_SIZE(svga->state.hw_draw.views); i++) {
Jakob Bornecrantz31926332009-11-16 19:56:18 +010049 struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
Brian Paule0542512015-08-13 11:00:58 -070050 if (view) {
51 svga_sampler_view_reference(&view->v, NULL);
52 pipe_sampler_view_release(&svga->pipe,
53 &svga->curr.sampler_views[shader][i]);
54 pipe_resource_reference(&view->texture, NULL);
55 view->dirty = TRUE;
56 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +010057 }
58}
59
60
José Fonseca369ece12011-02-23 13:32:37 +000061struct bind_queue {
62 struct {
63 unsigned unit;
64 struct svga_hw_view_state *view;
65 } bind[PIPE_MAX_SAMPLERS];
66
67 unsigned bind_count;
68};
69
70
Brian Paule0542512015-08-13 11:00:58 -070071/**
72 * Update the texture binding for one texture unit.
73 */
74static void
75emit_tex_binding_unit(struct svga_context *svga,
76 unsigned unit,
77 const struct svga_sampler_state *s,
78 const struct pipe_sampler_view *sv,
79 struct svga_hw_view_state *view,
80 boolean reemit,
81 struct bind_queue *queue)
82{
83 struct pipe_resource *texture = NULL;
84 unsigned last_level, min_lod, max_lod;
85
86 /* get min max lod */
87 if (sv && s) {
88 if (s->mipfilter == SVGA3D_TEX_FILTER_NONE) {
89 /* just use the base level image */
90 min_lod = max_lod = sv->u.tex.first_level;
91 }
92 else {
93 last_level = MIN2(sv->u.tex.last_level, sv->texture->last_level);
Brian Paulece33f92015-09-08 09:40:29 -060094 min_lod = s->view_min_lod + sv->u.tex.first_level;
Brian Paule0542512015-08-13 11:00:58 -070095 min_lod = MIN2(min_lod, last_level);
96 max_lod = MIN2(s->view_max_lod + sv->u.tex.first_level, last_level);
97 }
98 texture = sv->texture;
99 }
100 else {
101 min_lod = 0;
102 max_lod = 0;
103 }
104
105 if (view->texture != texture ||
106 view->min_lod != min_lod ||
107 view->max_lod != max_lod) {
108
109 svga_sampler_view_reference(&view->v, NULL);
110 pipe_resource_reference( &view->texture, texture );
111
112 view->dirty = TRUE;
113 view->min_lod = min_lod;
114 view->max_lod = max_lod;
115
116 if (texture) {
117 view->v = svga_get_tex_sampler_view(&svga->pipe,
118 texture,
119 min_lod,
120 max_lod);
121 }
122 }
123
124 /*
125 * We need to reemit non-null texture bindings, even when they are not
126 * dirty, to ensure that the resources are paged in.
127 */
128 if (view->dirty || (reemit && view->v)) {
129 queue->bind[queue->bind_count].unit = unit;
130 queue->bind[queue->bind_count].view = view;
131 queue->bind_count++;
132 }
133
134 if (!view->dirty && view->v) {
135 svga_validate_sampler_view(svga, view->v);
136 }
137}
138
139
José Fonsecae8f646f2011-11-02 10:32:20 +0000140static enum pipe_error
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100141update_tss_binding(struct svga_context *svga,
142 unsigned dirty )
143{
Brian Paulf5602c22016-08-29 10:15:36 -0600144 const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
Brian Paule0542512015-08-13 11:00:58 -0700145 boolean reemit = svga->rebind.flags.texture_samplers;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100146 unsigned i;
Brian Paule0542512015-08-13 11:00:58 -0700147 unsigned count = MAX2( svga->curr.num_sampler_views[shader],
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100148 svga->state.hw_draw.num_views );
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100149
José Fonseca369ece12011-02-23 13:32:37 +0000150 struct bind_queue queue;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100151
Brian Paule0542512015-08-13 11:00:58 -0700152 if (svga_have_vgpu10(svga))
153 return PIPE_OK;
154
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100155 queue.bind_count = 0;
156
157 for (i = 0; i < count; i++) {
Brian Paule0542512015-08-13 11:00:58 -0700158 emit_tex_binding_unit(svga, i,
159 svga->curr.sampler[shader][i],
160 svga->curr.sampler_views[shader][i],
161 &svga->state.hw_draw.views[i],
162 reemit,
163 &queue);
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100164 }
165
Brian Paule0542512015-08-13 11:00:58 -0700166 svga->state.hw_draw.num_views = svga->curr.num_sampler_views[shader];
167
168 /* Polygon stipple */
169 if (svga->curr.rast->templ.poly_stipple_enable) {
170 const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
171 emit_tex_binding_unit(svga, unit,
172 svga->polygon_stipple.sampler,
173 &svga->polygon_stipple.sampler_view->base,
174 &svga->state.hw_draw.views[unit],
175 reemit,
176 &queue);
177 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100178
Charmaine Leedbb5d2a2017-06-27 10:47:01 -0600179 svga->state.hw_draw.num_backed_views = 0;
180
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100181 if (queue.bind_count) {
182 SVGA3dTextureState *ts;
183
184 if (SVGA3D_BeginSetTextureState( svga->swc,
185 &ts,
186 queue.bind_count ) != PIPE_OK)
187 goto fail;
188
189 for (i = 0; i < queue.bind_count; i++) {
José Fonseca04094b22010-08-15 13:36:02 +0100190 struct svga_winsys_surface *handle;
Charmaine Leedbb5d2a2017-06-27 10:47:01 -0600191 struct svga_hw_view_state *view = queue.bind[i].view;
José Fonseca04094b22010-08-15 13:36:02 +0100192
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100193 ts[i].stage = queue.bind[i].unit;
194 ts[i].name = SVGA3D_TS_BIND_TEXTURE;
195
Charmaine Leedbb5d2a2017-06-27 10:47:01 -0600196 if (view->v) {
197 handle = view->v->handle;
198
199 /* Keep track of number of views with a backing copy
200 * of texture.
201 */
202 if (handle != svga_texture(view->texture)->handle)
203 svga->state.hw_draw.num_backed_views++;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100204 }
205 else {
José Fonseca04094b22010-08-15 13:36:02 +0100206 handle = NULL;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100207 }
José Fonseca04094b22010-08-15 13:36:02 +0100208 svga->swc->surface_relocation(svga->swc,
209 &ts[i].value,
Brian Pauld993ada2014-02-08 09:51:14 -0800210 NULL,
José Fonseca04094b22010-08-15 13:36:02 +0100211 handle,
212 SVGA_RELOC_READ);
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100213
214 queue.bind[i].view->dirty = FALSE;
215 }
216
217 SVGA_FIFOCommitAll( svga->swc );
218 }
219
Brian Paule0542512015-08-13 11:00:58 -0700220 svga->rebind.flags.texture_samplers = FALSE;
José Fonseca6b95cfb2011-04-07 16:54:37 +0100221
Brian Paul92cbfde2013-08-26 15:49:16 -0600222 return PIPE_OK;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100223
224fail:
225 return PIPE_ERROR_OUT_OF_MEMORY;
226}
227
228
José Fonseca369ece12011-02-23 13:32:37 +0000229/*
230 * Rebind textures.
231 *
232 * Similar to update_tss_binding, but without any state checking/update.
233 *
234 * Called at the beginning of every new command buffer to ensure that
235 * non-dirty textures are properly paged-in.
236 */
237enum pipe_error
238svga_reemit_tss_bindings(struct svga_context *svga)
239{
240 unsigned i;
241 enum pipe_error ret;
242 struct bind_queue queue;
243
Brian Paule0542512015-08-13 11:00:58 -0700244 assert(!svga_have_vgpu10(svga));
245 assert(svga->rebind.flags.texture_samplers);
José Fonseca6b95cfb2011-04-07 16:54:37 +0100246
José Fonseca369ece12011-02-23 13:32:37 +0000247 queue.bind_count = 0;
248
249 for (i = 0; i < svga->state.hw_draw.num_views; i++) {
250 struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
251
252 if (view->v) {
253 queue.bind[queue.bind_count].unit = i;
254 queue.bind[queue.bind_count].view = view;
255 queue.bind_count++;
256 }
257 }
258
Brian Paule0542512015-08-13 11:00:58 -0700259 /* Polygon stipple */
260 if (svga->curr.rast->templ.poly_stipple_enable) {
261 const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
262 struct svga_hw_view_state *view = &svga->state.hw_draw.views[unit];
263
264 if (view->v) {
265 queue.bind[queue.bind_count].unit = unit;
266 queue.bind[queue.bind_count].view = view;
267 queue.bind_count++;
268 }
269 }
270
José Fonseca369ece12011-02-23 13:32:37 +0000271 if (queue.bind_count) {
272 SVGA3dTextureState *ts;
273
274 ret = SVGA3D_BeginSetTextureState(svga->swc,
275 &ts,
276 queue.bind_count);
277 if (ret != PIPE_OK) {
278 return ret;
279 }
280
281 for (i = 0; i < queue.bind_count; i++) {
282 struct svga_winsys_surface *handle;
283
284 ts[i].stage = queue.bind[i].unit;
285 ts[i].name = SVGA3D_TS_BIND_TEXTURE;
286
287 assert(queue.bind[i].view->v);
288 handle = queue.bind[i].view->v->handle;
289 svga->swc->surface_relocation(svga->swc,
290 &ts[i].value,
Brian Pauld993ada2014-02-08 09:51:14 -0800291 NULL,
José Fonseca369ece12011-02-23 13:32:37 +0000292 handle,
293 SVGA_RELOC_READ);
294 }
295
296 SVGA_FIFOCommitAll(svga->swc);
297 }
298
Brian Paule0542512015-08-13 11:00:58 -0700299 svga->rebind.flags.texture_samplers = FALSE;
José Fonseca6b95cfb2011-04-07 16:54:37 +0100300
José Fonseca369ece12011-02-23 13:32:37 +0000301 return PIPE_OK;
302}
303
304
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100305struct svga_tracked_state svga_hw_tss_binding = {
306 "texture binding emit",
Brian Pauld4514212016-09-27 10:06:46 -0600307 SVGA_NEW_FRAME_BUFFER |
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100308 SVGA_NEW_TEXTURE_BINDING |
Brian Paule0542512015-08-13 11:00:58 -0700309 SVGA_NEW_STIPPLE |
José Fonseca6b95cfb2011-04-07 16:54:37 +0100310 SVGA_NEW_SAMPLER,
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100311 update_tss_binding
312};
313
314
315/***********************************************************************
316 */
317
318struct ts_queue {
319 unsigned ts_count;
320 SVGA3dTextureState ts[PIPE_MAX_SAMPLERS*SVGA3D_TS_MAX];
321};
322
323
Brian Paule0542512015-08-13 11:00:58 -0700324static inline void
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100325svga_queue_tss( struct ts_queue *q,
326 unsigned unit,
327 unsigned tss,
328 unsigned value )
329{
Edward O'Callaghan82871082015-12-04 15:31:40 +1100330 assert(q->ts_count < ARRAY_SIZE(q->ts));
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100331 q->ts[q->ts_count].stage = unit;
332 q->ts[q->ts_count].name = tss;
333 q->ts[q->ts_count].value = value;
334 q->ts_count++;
335}
336
337
Brian Paule0542512015-08-13 11:00:58 -0700338#define EMIT_TS(svga, unit, val, token) \
339do { \
Brian Paule0184b32016-04-25 09:34:40 -0600340 assert(unit < ARRAY_SIZE(svga->state.hw_draw.ts)); \
341 STATIC_ASSERT(SVGA3D_TS_##token < ARRAY_SIZE(svga->state.hw_draw.ts[unit])); \
Brian Paule0542512015-08-13 11:00:58 -0700342 if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) { \
343 svga_queue_tss( queue, unit, SVGA3D_TS_##token, val ); \
344 svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val; \
345 } \
346} while (0)
347
348#define EMIT_TS_FLOAT(svga, unit, fvalue, token) \
349do { \
350 unsigned val = fui(fvalue); \
Brian Paule0184b32016-04-25 09:34:40 -0600351 assert(unit < ARRAY_SIZE(svga->state.hw_draw.ts)); \
352 STATIC_ASSERT(SVGA3D_TS_##token < ARRAY_SIZE(svga->state.hw_draw.ts[unit])); \
Brian Paule0542512015-08-13 11:00:58 -0700353 if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) { \
354 svga_queue_tss( queue, unit, SVGA3D_TS_##token, val ); \
355 svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val; \
356 } \
357} while (0)
358
359
360/**
361 * Emit texture sampler state (tss) for one texture unit.
362 */
363static void
364emit_tss_unit(struct svga_context *svga, unsigned unit,
365 const struct svga_sampler_state *state,
366 struct ts_queue *queue)
367{
368 EMIT_TS(svga, unit, state->mipfilter, MIPFILTER);
369 EMIT_TS(svga, unit, state->min_lod, TEXTURE_MIPMAP_LEVEL);
370 EMIT_TS(svga, unit, state->magfilter, MAGFILTER);
371 EMIT_TS(svga, unit, state->minfilter, MINFILTER);
372 EMIT_TS(svga, unit, state->aniso_level, TEXTURE_ANISOTROPIC_LEVEL);
373 EMIT_TS_FLOAT(svga, unit, state->lod_bias, TEXTURE_LOD_BIAS);
374 EMIT_TS(svga, unit, state->addressu, ADDRESSU);
375 EMIT_TS(svga, unit, state->addressw, ADDRESSW);
376 EMIT_TS(svga, unit, state->bordercolor, BORDERCOLOR);
377 // TEXCOORDINDEX -- hopefully not needed
378
379 if (svga->curr.tex_flags.flag_1d & (1 << unit))
380 EMIT_TS(svga, unit, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV);
381 else
382 EMIT_TS(svga, unit, state->addressv, ADDRESSV);
383
384 if (svga->curr.tex_flags.flag_srgb & (1 << unit))
385 EMIT_TS_FLOAT(svga, unit, 2.2f, GAMMA);
386 else
387 EMIT_TS_FLOAT(svga, unit, 1.0f, GAMMA);
388}
389
José Fonsecae8f646f2011-11-02 10:32:20 +0000390static enum pipe_error
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100391update_tss(struct svga_context *svga,
392 unsigned dirty )
393{
Brian Paulf5602c22016-08-29 10:15:36 -0600394 const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100395 unsigned i;
396 struct ts_queue queue;
397
Brian Paule0542512015-08-13 11:00:58 -0700398 if (svga_have_vgpu10(svga))
399 return PIPE_OK;
400
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100401 queue.ts_count = 0;
Brian Paule0542512015-08-13 11:00:58 -0700402 for (i = 0; i < svga->curr.num_samplers[shader]; i++) {
403 if (svga->curr.sampler[shader][i]) {
404 const struct svga_sampler_state *curr = svga->curr.sampler[shader][i];
405 emit_tss_unit(svga, i, curr, &queue);
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100406 }
407 }
Brian Paule0542512015-08-13 11:00:58 -0700408
409 /* polygon stipple sampler */
410 if (svga->curr.rast->templ.poly_stipple_enable) {
411 emit_tss_unit(svga,
412 svga->state.hw_draw.fs->pstipple_sampler_unit,
413 svga->polygon_stipple.sampler,
414 &queue);
415 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100416
417 if (queue.ts_count) {
418 SVGA3dTextureState *ts;
419
420 if (SVGA3D_BeginSetTextureState( svga->swc,
421 &ts,
422 queue.ts_count ) != PIPE_OK)
423 goto fail;
424
425 memcpy( ts,
426 queue.ts,
427 queue.ts_count * sizeof queue.ts[0]);
428
429 SVGA_FIFOCommitAll( svga->swc );
430 }
431
José Fonsecae8f646f2011-11-02 10:32:20 +0000432 return PIPE_OK;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100433
434fail:
435 /* XXX: need to poison cached hardware state on failure to ensure
436 * dirty state gets re-emitted. Fix this by re-instating partial
437 * FIFOCommit command and only updating cached hw state once the
438 * initial allocation has succeeded.
439 */
440 memset(svga->state.hw_draw.ts, 0xcd, sizeof(svga->state.hw_draw.ts));
441
442 return PIPE_ERROR_OUT_OF_MEMORY;
443}
444
445
446struct svga_tracked_state svga_hw_tss = {
447 "texture state emit",
448 (SVGA_NEW_SAMPLER |
Brian Paule0542512015-08-13 11:00:58 -0700449 SVGA_NEW_STIPPLE |
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100450 SVGA_NEW_TEXTURE_FLAGS),
451 update_tss
452};
453