1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
32 #include "util/u_inlines.h"
33 #include "util/u_memory.h"
35 #include "draw/draw_context.h"
37 #include "lp_context.h"
38 #include "lp_screen.h"
41 #include "frontend/sw_winsys.h"
46 llvmpipe_create_sampler_state(struct pipe_context
*pipe
,
47 const struct pipe_sampler_state
*sampler
)
49 struct pipe_sampler_state
*state
= mem_dup(sampler
, sizeof *sampler
);
51 if (LP_PERF
& PERF_NO_MIP_LINEAR
) {
52 if (state
->min_mip_filter
== PIPE_TEX_MIPFILTER_LINEAR
)
53 state
->min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
56 if (LP_PERF
& PERF_NO_MIPMAPS
)
57 state
->min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
59 if (LP_PERF
& PERF_NO_LINEAR
) {
60 state
->mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
61 state
->min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
69 llvmpipe_bind_sampler_states(struct pipe_context
*pipe
,
70 enum pipe_shader_type shader
,
75 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
78 assert(shader
< PIPE_SHADER_TYPES
);
79 assert(start
+ num
<= ARRAY_SIZE(llvmpipe
->samplers
[shader
]));
81 draw_flush(llvmpipe
->draw
);
83 /* set the new samplers */
84 for (i
= 0; i
< num
; i
++) {
85 llvmpipe
->samplers
[shader
][start
+ i
] = samplers
[i
];
88 /* find highest non-null samplers[] entry */
90 unsigned j
= MAX2(llvmpipe
->num_samplers
[shader
], start
+ num
);
91 while (j
> 0 && llvmpipe
->samplers
[shader
][j
- 1] == NULL
)
93 llvmpipe
->num_samplers
[shader
] = j
;
96 if (shader
== PIPE_SHADER_VERTEX
||
97 shader
== PIPE_SHADER_GEOMETRY
||
98 shader
== PIPE_SHADER_TESS_CTRL
||
99 shader
== PIPE_SHADER_TESS_EVAL
) {
100 draw_set_samplers(llvmpipe
->draw
,
102 llvmpipe
->samplers
[shader
],
103 llvmpipe
->num_samplers
[shader
]);
105 else if (shader
== PIPE_SHADER_COMPUTE
) {
106 llvmpipe
->cs_dirty
|= LP_CSNEW_SAMPLER
;
108 llvmpipe
->dirty
|= LP_NEW_SAMPLER
;
114 llvmpipe_set_sampler_views(struct pipe_context
*pipe
,
115 enum pipe_shader_type shader
,
118 struct pipe_sampler_view
**views
)
120 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
123 assert(num
<= PIPE_MAX_SHADER_SAMPLER_VIEWS
);
125 assert(shader
< PIPE_SHADER_TYPES
);
126 assert(start
+ num
<= ARRAY_SIZE(llvmpipe
->sampler_views
[shader
]));
128 draw_flush(llvmpipe
->draw
);
130 /* set the new sampler views */
131 for (i
= 0; i
< num
; i
++) {
133 * Warn if someone tries to set a view created in a different context
134 * (which is why we need the hack above in the first place).
135 * An assert would be better but st/mesa relies on it...
137 if (views
[i
] && views
[i
]->context
!= pipe
) {
138 debug_printf("Illegal setting of sampler_view %d created in another "
143 llvmpipe_flush_resource(pipe
, views
[i
]->texture
, 0, true, false, false, "sampler_view");
144 pipe_sampler_view_reference(&llvmpipe
->sampler_views
[shader
][start
+ i
],
148 /* find highest non-null sampler_views[] entry */
150 unsigned j
= MAX2(llvmpipe
->num_sampler_views
[shader
], start
+ num
);
151 while (j
> 0 && llvmpipe
->sampler_views
[shader
][j
- 1] == NULL
)
153 llvmpipe
->num_sampler_views
[shader
] = j
;
156 if (shader
== PIPE_SHADER_VERTEX
||
157 shader
== PIPE_SHADER_GEOMETRY
||
158 shader
== PIPE_SHADER_TESS_CTRL
||
159 shader
== PIPE_SHADER_TESS_EVAL
) {
160 draw_set_sampler_views(llvmpipe
->draw
,
162 llvmpipe
->sampler_views
[shader
],
163 llvmpipe
->num_sampler_views
[shader
]);
165 else if (shader
== PIPE_SHADER_COMPUTE
) {
166 llvmpipe
->cs_dirty
|= LP_CSNEW_SAMPLER_VIEW
;
168 llvmpipe
->dirty
|= LP_NEW_SAMPLER_VIEW
;
173 static struct pipe_sampler_view
*
174 llvmpipe_create_sampler_view(struct pipe_context
*pipe
,
175 struct pipe_resource
*texture
,
176 const struct pipe_sampler_view
*templ
)
178 struct pipe_sampler_view
*view
= CALLOC_STRUCT(pipe_sampler_view
);
180 * XXX: bind flags from OpenGL state tracker are notoriously unreliable.
181 * This looks unfixable, so fix the bind flags instead when it happens.
183 if (!(texture
->bind
& PIPE_BIND_SAMPLER_VIEW
)) {
184 debug_printf("Illegal sampler view creation without bind flag\n");
185 texture
->bind
|= PIPE_BIND_SAMPLER_VIEW
;
190 view
->reference
.count
= 1;
191 view
->texture
= NULL
;
192 pipe_resource_reference(&view
->texture
, texture
);
193 view
->context
= pipe
;
197 * This is possibly too lenient, but the primary reason is just
198 * to catch gallium frontends which forget to initialize this, so
199 * it only catches clearly impossible view targets.
201 if (view
->target
!= texture
->target
) {
202 if (view
->target
== PIPE_TEXTURE_1D
)
203 assert(texture
->target
== PIPE_TEXTURE_1D_ARRAY
);
204 else if (view
->target
== PIPE_TEXTURE_1D_ARRAY
)
205 assert(texture
->target
== PIPE_TEXTURE_1D
);
206 else if (view
->target
== PIPE_TEXTURE_2D
)
207 assert(texture
->target
== PIPE_TEXTURE_2D_ARRAY
||
208 texture
->target
== PIPE_TEXTURE_CUBE
||
209 texture
->target
== PIPE_TEXTURE_CUBE_ARRAY
);
210 else if (view
->target
== PIPE_TEXTURE_2D_ARRAY
)
211 assert(texture
->target
== PIPE_TEXTURE_2D
||
212 texture
->target
== PIPE_TEXTURE_CUBE
||
213 texture
->target
== PIPE_TEXTURE_CUBE_ARRAY
);
214 else if (view
->target
== PIPE_TEXTURE_CUBE
)
215 assert(texture
->target
== PIPE_TEXTURE_CUBE_ARRAY
||
216 texture
->target
== PIPE_TEXTURE_2D_ARRAY
);
217 else if (view
->target
== PIPE_TEXTURE_CUBE_ARRAY
)
218 assert(texture
->target
== PIPE_TEXTURE_CUBE
||
219 texture
->target
== PIPE_TEXTURE_2D_ARRAY
);
231 llvmpipe_sampler_view_destroy(struct pipe_context
*pipe
,
232 struct pipe_sampler_view
*view
)
234 pipe_resource_reference(&view
->texture
, NULL
);
240 llvmpipe_delete_sampler_state(struct pipe_context
*pipe
,
248 prepare_shader_sampling(
249 struct llvmpipe_context
*lp
,
251 struct pipe_sampler_view
**views
,
252 enum pipe_shader_type shader_type
)
256 uint32_t row_stride
[PIPE_MAX_TEXTURE_LEVELS
];
257 uint32_t img_stride
[PIPE_MAX_TEXTURE_LEVELS
];
258 uint32_t mip_offsets
[PIPE_MAX_TEXTURE_LEVELS
];
261 assert(num
<= PIPE_MAX_SHADER_SAMPLER_VIEWS
);
265 for (i
= 0; i
< num
; i
++) {
266 struct pipe_sampler_view
*view
= i
< num
? views
[i
] : NULL
;
269 struct pipe_resource
*tex
= view
->texture
;
270 struct llvmpipe_resource
*lp_tex
= llvmpipe_resource(tex
);
271 unsigned width0
= tex
->width0
;
272 unsigned num_layers
= tex
->depth0
;
273 unsigned first_level
= 0;
274 unsigned last_level
= 0;
275 unsigned sample_stride
= 0;
276 unsigned num_samples
= tex
->nr_samples
;
279 /* regular texture - setup array of mipmap level offsets */
280 struct pipe_resource
*res
= view
->texture
;
283 if (llvmpipe_resource_is_texture(res
)) {
284 first_level
= view
->u
.tex
.first_level
;
285 last_level
= view
->u
.tex
.last_level
;
286 assert(first_level
<= last_level
);
287 assert(last_level
<= res
->last_level
);
288 addr
= lp_tex
->tex_data
;
290 sample_stride
= lp_tex
->sample_stride
;
292 for (j
= first_level
; j
<= last_level
; j
++) {
293 mip_offsets
[j
] = lp_tex
->mip_offsets
[j
];
294 row_stride
[j
] = lp_tex
->row_stride
[j
];
295 img_stride
[j
] = lp_tex
->img_stride
[j
];
297 if (tex
->target
== PIPE_TEXTURE_1D_ARRAY
||
298 tex
->target
== PIPE_TEXTURE_2D_ARRAY
||
299 tex
->target
== PIPE_TEXTURE_CUBE
||
300 tex
->target
== PIPE_TEXTURE_CUBE_ARRAY
) {
301 num_layers
= view
->u
.tex
.last_layer
- view
->u
.tex
.first_layer
+ 1;
302 for (j
= first_level
; j
<= last_level
; j
++) {
303 mip_offsets
[j
] += view
->u
.tex
.first_layer
*
304 lp_tex
->img_stride
[j
];
306 if (view
->target
== PIPE_TEXTURE_CUBE
||
307 view
->target
== PIPE_TEXTURE_CUBE_ARRAY
) {
308 assert(num_layers
% 6 == 0);
310 assert(view
->u
.tex
.first_layer
<= view
->u
.tex
.last_layer
);
311 assert(view
->u
.tex
.last_layer
< res
->array_size
);
315 unsigned view_blocksize
= util_format_get_blocksize(view
->format
);
317 /* probably don't really need to fill that out */
322 /* everything specified in number of elements here. */
323 width0
= view
->u
.buf
.size
/ view_blocksize
;
324 addr
= (uint8_t *)addr
+ view
->u
.buf
.offset
;
325 assert(view
->u
.buf
.offset
+ view
->u
.buf
.size
<= res
->width0
);
329 /* display target texture/surface */
331 * XXX: Where should this be unmapped?
333 struct llvmpipe_screen
*screen
= llvmpipe_screen(tex
->screen
);
334 struct sw_winsys
*winsys
= screen
->winsys
;
335 addr
= winsys
->displaytarget_map(winsys
, lp_tex
->dt
,
337 row_stride
[0] = lp_tex
->row_stride
[0];
338 img_stride
[0] = lp_tex
->img_stride
[0];
342 draw_set_mapped_texture(lp
->draw
,
345 width0
, tex
->height0
, num_layers
,
346 first_level
, last_level
,
347 num_samples
, sample_stride
,
349 row_stride
, img_stride
, mip_offsets
);
356 * Called whenever we're about to draw (no dirty flag, FIXME?).
359 llvmpipe_prepare_vertex_sampling(struct llvmpipe_context
*lp
,
361 struct pipe_sampler_view
**views
)
363 prepare_shader_sampling(lp
, num
, views
, PIPE_SHADER_VERTEX
);
368 * Called whenever we're about to draw (no dirty flag, FIXME?).
371 llvmpipe_prepare_geometry_sampling(struct llvmpipe_context
*lp
,
373 struct pipe_sampler_view
**views
)
375 prepare_shader_sampling(lp
, num
, views
, PIPE_SHADER_GEOMETRY
);
379 * Called whenever we're about to draw (no dirty flag, FIXME?).
382 llvmpipe_prepare_tess_ctrl_sampling(struct llvmpipe_context
*lp
,
384 struct pipe_sampler_view
**views
)
386 prepare_shader_sampling(lp
, num
, views
, PIPE_SHADER_TESS_CTRL
);
390 * Called whenever we're about to draw (no dirty flag, FIXME?).
393 llvmpipe_prepare_tess_eval_sampling(struct llvmpipe_context
*lp
,
395 struct pipe_sampler_view
**views
)
397 prepare_shader_sampling(lp
, num
, views
, PIPE_SHADER_TESS_EVAL
);
401 prepare_shader_images(
402 struct llvmpipe_context
*lp
,
404 struct pipe_image_view
*views
,
405 enum pipe_shader_type shader_type
)
411 uint32_t sample_stride
;
414 assert(num
<= PIPE_MAX_SHADER_SAMPLER_VIEWS
);
418 for (i
= 0; i
< num
; i
++) {
419 struct pipe_image_view
*view
= i
< num
? &views
[i
] : NULL
;
422 struct pipe_resource
*img
= view
->resource
;
423 struct llvmpipe_resource
*lp_img
= llvmpipe_resource(img
);
427 unsigned width
= u_minify(img
->width0
, view
->u
.tex
.level
);
428 unsigned height
= u_minify(img
->height0
, view
->u
.tex
.level
);
429 unsigned num_layers
= img
->depth0
;
430 unsigned num_samples
= img
->nr_samples
;
433 /* regular texture - setup array of mipmap level offsets */
434 struct pipe_resource
*res
= view
->resource
;
436 if (llvmpipe_resource_is_texture(res
)) {
437 uint32_t mip_offset
= lp_img
->mip_offsets
[view
->u
.tex
.level
];
438 addr
= lp_img
->tex_data
;
440 if (img
->target
== PIPE_TEXTURE_1D_ARRAY
||
441 img
->target
== PIPE_TEXTURE_2D_ARRAY
||
442 img
->target
== PIPE_TEXTURE_3D
||
443 img
->target
== PIPE_TEXTURE_CUBE
||
444 img
->target
== PIPE_TEXTURE_CUBE_ARRAY
) {
445 num_layers
= view
->u
.tex
.last_layer
- view
->u
.tex
.first_layer
+ 1;
446 assert(view
->u
.tex
.first_layer
<= view
->u
.tex
.last_layer
);
447 mip_offset
+= view
->u
.tex
.first_layer
* lp_img
->img_stride
[view
->u
.tex
.level
];
450 row_stride
= lp_img
->row_stride
[view
->u
.tex
.level
];
451 img_stride
= lp_img
->img_stride
[view
->u
.tex
.level
];
452 sample_stride
= lp_img
->sample_stride
;
453 addr
= (uint8_t *)addr
+ mip_offset
;
456 unsigned view_blocksize
= util_format_get_blocksize(view
->format
);
458 /* probably don't really need to fill that out */
463 /* everything specified in number of elements here. */
464 width
= view
->u
.buf
.size
/ view_blocksize
;
465 addr
= (uint8_t *)addr
+ view
->u
.buf
.offset
;
466 assert(view
->u
.buf
.offset
+ view
->u
.buf
.size
<= res
->width0
);
470 /* display target texture/surface */
472 * XXX: Where should this be unmapped?
474 struct llvmpipe_screen
*screen
= llvmpipe_screen(img
->screen
);
475 struct sw_winsys
*winsys
= screen
->winsys
;
476 addr
= winsys
->displaytarget_map(winsys
, lp_img
->dt
,
478 row_stride
= lp_img
->row_stride
[0];
479 img_stride
= lp_img
->img_stride
[0];
483 draw_set_mapped_image(lp
->draw
,
486 width
, height
, num_layers
,
488 row_stride
, img_stride
,
489 num_samples
, sample_stride
);
496 * Called whenever we're about to draw (no dirty flag, FIXME?).
499 llvmpipe_prepare_vertex_images(struct llvmpipe_context
*lp
,
501 struct pipe_image_view
*views
)
503 prepare_shader_images(lp
, num
, views
, PIPE_SHADER_VERTEX
);
508 * Called whenever we're about to draw (no dirty flag, FIXME?).
511 llvmpipe_prepare_geometry_images(struct llvmpipe_context
*lp
,
513 struct pipe_image_view
*views
)
515 prepare_shader_images(lp
, num
, views
, PIPE_SHADER_GEOMETRY
);
519 * Called whenever we're about to draw (no dirty flag, FIXME?).
522 llvmpipe_prepare_tess_ctrl_images(struct llvmpipe_context
*lp
,
524 struct pipe_image_view
*views
)
526 prepare_shader_images(lp
, num
, views
, PIPE_SHADER_TESS_CTRL
);
530 * Called whenever we're about to draw (no dirty flag, FIXME?).
533 llvmpipe_prepare_tess_eval_images(struct llvmpipe_context
*lp
,
535 struct pipe_image_view
*views
)
537 prepare_shader_images(lp
, num
, views
, PIPE_SHADER_TESS_EVAL
);
541 llvmpipe_init_sampler_funcs(struct llvmpipe_context
*llvmpipe
)
543 llvmpipe
->pipe
.create_sampler_state
= llvmpipe_create_sampler_state
;
545 llvmpipe
->pipe
.bind_sampler_states
= llvmpipe_bind_sampler_states
;
546 llvmpipe
->pipe
.create_sampler_view
= llvmpipe_create_sampler_view
;
547 llvmpipe
->pipe
.set_sampler_views
= llvmpipe_set_sampler_views
;
548 llvmpipe
->pipe
.sampler_view_destroy
= llvmpipe_sampler_view_destroy
;
549 llvmpipe
->pipe
.delete_sampler_state
= llvmpipe_delete_sampler_state
;