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 "state_tracker/sw_winsys.h"
45 llvmpipe_create_sampler_state(struct pipe_context
*pipe
,
46 const struct pipe_sampler_state
*sampler
)
48 struct pipe_sampler_state
*state
= mem_dup(sampler
, sizeof *sampler
);
50 if (LP_PERF
& PERF_NO_MIP_LINEAR
) {
51 if (state
->min_mip_filter
== PIPE_TEX_MIPFILTER_LINEAR
)
52 state
->min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
55 if (LP_PERF
& PERF_NO_MIPMAPS
)
56 state
->min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
58 if (LP_PERF
& PERF_NO_LINEAR
) {
59 state
->mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
60 state
->min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
68 llvmpipe_bind_sampler_states(struct pipe_context
*pipe
,
74 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
77 assert(shader
< PIPE_SHADER_TYPES
);
78 assert(start
+ num
<= Elements(llvmpipe
->samplers
[shader
]));
80 draw_flush(llvmpipe
->draw
);
82 /* set the new samplers */
83 for (i
= 0; i
< num
; i
++) {
84 llvmpipe
->samplers
[shader
][start
+ i
] = samplers
[i
];
87 /* find highest non-null samplers[] entry */
89 unsigned j
= MAX2(llvmpipe
->num_samplers
[shader
], start
+ num
);
90 while (j
> 0 && llvmpipe
->samplers
[shader
][j
- 1] == NULL
)
92 llvmpipe
->num_samplers
[shader
] = j
;
95 if (shader
== PIPE_SHADER_VERTEX
|| shader
== PIPE_SHADER_GEOMETRY
) {
96 draw_set_samplers(llvmpipe
->draw
,
98 llvmpipe
->samplers
[shader
],
99 llvmpipe
->num_samplers
[shader
]);
102 llvmpipe
->dirty
|= LP_NEW_SAMPLER
;
107 llvmpipe_set_sampler_views(struct pipe_context
*pipe
,
111 struct pipe_sampler_view
**views
)
113 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
116 assert(num
<= PIPE_MAX_SHADER_SAMPLER_VIEWS
);
118 assert(shader
< PIPE_SHADER_TYPES
);
119 assert(start
+ num
<= Elements(llvmpipe
->sampler_views
[shader
]));
121 draw_flush(llvmpipe
->draw
);
123 /* set the new sampler views */
124 for (i
= 0; i
< num
; i
++) {
125 /* Note: we're using pipe_sampler_view_release() here to work around
126 * a possible crash when the old view belongs to another context that
127 * was already destroyed.
129 pipe_sampler_view_release(pipe
,
130 &llvmpipe
->sampler_views
[shader
][start
+ i
]);
131 pipe_sampler_view_reference(&llvmpipe
->sampler_views
[shader
][start
+ i
],
135 /* find highest non-null sampler_views[] entry */
137 unsigned j
= MAX2(llvmpipe
->num_sampler_views
[shader
], start
+ num
);
138 while (j
> 0 && llvmpipe
->sampler_views
[shader
][j
- 1] == NULL
)
140 llvmpipe
->num_sampler_views
[shader
] = j
;
143 if (shader
== PIPE_SHADER_VERTEX
|| shader
== PIPE_SHADER_GEOMETRY
) {
144 draw_set_sampler_views(llvmpipe
->draw
,
146 llvmpipe
->sampler_views
[shader
],
147 llvmpipe
->num_sampler_views
[shader
]);
150 llvmpipe
->dirty
|= LP_NEW_SAMPLER_VIEW
;
154 static struct pipe_sampler_view
*
155 llvmpipe_create_sampler_view(struct pipe_context
*pipe
,
156 struct pipe_resource
*texture
,
157 const struct pipe_sampler_view
*templ
)
159 struct pipe_sampler_view
*view
= CALLOC_STRUCT(pipe_sampler_view
);
161 * XXX we REALLY want to see the correct bind flag here but the OpenGL
162 * state tracker can't guarantee that at least for texture buffer objects.
164 if (!(texture
->bind
& PIPE_BIND_SAMPLER_VIEW
))
165 debug_printf("Illegal sampler view creation without bind flag\n");
169 view
->reference
.count
= 1;
170 view
->texture
= NULL
;
171 pipe_resource_reference(&view
->texture
, texture
);
172 view
->context
= pipe
;
176 * This is possibly too lenient, but the primary reason is just
177 * to catch state trackers which forget to initialize this, so
178 * it only catches clearly impossible view targets.
180 if (view
->target
!= texture
->target
) {
181 if (view
->target
== PIPE_TEXTURE_1D
)
182 assert(texture
->target
== PIPE_TEXTURE_1D_ARRAY
);
183 else if (view
->target
== PIPE_TEXTURE_1D_ARRAY
)
184 assert(texture
->target
== PIPE_TEXTURE_1D
);
185 else if (view
->target
== PIPE_TEXTURE_2D
)
186 assert(texture
->target
== PIPE_TEXTURE_2D_ARRAY
||
187 texture
->target
== PIPE_TEXTURE_CUBE
||
188 texture
->target
== PIPE_TEXTURE_CUBE_ARRAY
);
189 else if (view
->target
== PIPE_TEXTURE_2D_ARRAY
)
190 assert(texture
->target
== PIPE_TEXTURE_2D
||
191 texture
->target
== PIPE_TEXTURE_CUBE
||
192 texture
->target
== PIPE_TEXTURE_CUBE_ARRAY
);
193 else if (view
->target
== PIPE_TEXTURE_CUBE
)
194 assert(texture
->target
== PIPE_TEXTURE_CUBE_ARRAY
||
195 texture
->target
== PIPE_TEXTURE_2D_ARRAY
);
196 else if (view
->target
== PIPE_TEXTURE_CUBE_ARRAY
)
197 assert(texture
->target
== PIPE_TEXTURE_CUBE
||
198 texture
->target
== PIPE_TEXTURE_2D_ARRAY
);
210 llvmpipe_sampler_view_destroy(struct pipe_context
*pipe
,
211 struct pipe_sampler_view
*view
)
213 pipe_resource_reference(&view
->texture
, NULL
);
219 llvmpipe_delete_sampler_state(struct pipe_context
*pipe
,
227 prepare_shader_sampling(
228 struct llvmpipe_context
*lp
,
230 struct pipe_sampler_view
**views
,
231 unsigned shader_type
,
232 struct pipe_resource
*mapped_tex
[PIPE_MAX_SHADER_SAMPLER_VIEWS
])
236 uint32_t row_stride
[PIPE_MAX_TEXTURE_LEVELS
];
237 uint32_t img_stride
[PIPE_MAX_TEXTURE_LEVELS
];
238 uint32_t mip_offsets
[PIPE_MAX_TEXTURE_LEVELS
];
241 assert(num
<= PIPE_MAX_SHADER_SAMPLER_VIEWS
);
245 for (i
= 0; i
< PIPE_MAX_SHADER_SAMPLER_VIEWS
; i
++) {
246 struct pipe_sampler_view
*view
= i
< num
? views
[i
] : NULL
;
249 struct pipe_resource
*tex
= view
->texture
;
250 struct llvmpipe_resource
*lp_tex
= llvmpipe_resource(tex
);
251 unsigned width0
= tex
->width0
;
252 unsigned num_layers
= tex
->depth0
;
253 unsigned first_level
= 0;
254 unsigned last_level
= 0;
256 /* We're referencing the texture's internal data, so save a
259 pipe_resource_reference(&mapped_tex
[i
], tex
);
262 /* regular texture - setup array of mipmap level offsets */
263 struct pipe_resource
*res
= view
->texture
;
266 if (llvmpipe_resource_is_texture(res
)) {
267 first_level
= view
->u
.tex
.first_level
;
268 last_level
= view
->u
.tex
.last_level
;
269 assert(first_level
<= last_level
);
270 assert(last_level
<= res
->last_level
);
271 addr
= lp_tex
->tex_data
;
273 for (j
= first_level
; j
<= last_level
; j
++) {
274 mip_offsets
[j
] = lp_tex
->mip_offsets
[j
];
275 row_stride
[j
] = lp_tex
->row_stride
[j
];
276 img_stride
[j
] = lp_tex
->img_stride
[j
];
278 if (view
->target
== PIPE_TEXTURE_1D_ARRAY
||
279 view
->target
== PIPE_TEXTURE_2D_ARRAY
||
280 view
->target
== PIPE_TEXTURE_CUBE
||
281 view
->target
== PIPE_TEXTURE_CUBE_ARRAY
) {
282 num_layers
= view
->u
.tex
.last_layer
- view
->u
.tex
.first_layer
+ 1;
283 for (j
= first_level
; j
<= last_level
; j
++) {
284 mip_offsets
[j
] += view
->u
.tex
.first_layer
*
285 lp_tex
->img_stride
[j
];
287 if (view
->target
== PIPE_TEXTURE_CUBE
||
288 view
->target
== PIPE_TEXTURE_CUBE_ARRAY
) {
289 assert(num_layers
% 6 == 0);
291 assert(view
->u
.tex
.first_layer
<= view
->u
.tex
.last_layer
);
292 assert(view
->u
.tex
.last_layer
< res
->array_size
);
296 unsigned view_blocksize
= util_format_get_blocksize(view
->format
);
298 /* probably don't really need to fill that out */
303 /* everything specified in number of elements here. */
304 width0
= view
->u
.buf
.last_element
- view
->u
.buf
.first_element
+ 1;
305 addr
= (uint8_t *)addr
+ view
->u
.buf
.first_element
*
307 assert(view
->u
.buf
.first_element
<= view
->u
.buf
.last_element
);
308 assert(view
->u
.buf
.last_element
* view_blocksize
< res
->width0
);
312 /* display target texture/surface */
314 * XXX: Where should this be unmapped?
316 struct llvmpipe_screen
*screen
= llvmpipe_screen(tex
->screen
);
317 struct sw_winsys
*winsys
= screen
->winsys
;
318 addr
= winsys
->displaytarget_map(winsys
, lp_tex
->dt
,
320 row_stride
[0] = lp_tex
->row_stride
[0];
321 img_stride
[0] = lp_tex
->img_stride
[0];
325 draw_set_mapped_texture(lp
->draw
,
328 width0
, tex
->height0
, num_layers
,
329 first_level
, last_level
,
331 row_stride
, img_stride
, mip_offsets
);
338 * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
341 llvmpipe_prepare_vertex_sampling(struct llvmpipe_context
*lp
,
343 struct pipe_sampler_view
**views
)
345 prepare_shader_sampling(lp
, num
, views
, PIPE_SHADER_VERTEX
,
350 llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context
*ctx
)
353 for (i
= 0; i
< Elements(ctx
->mapped_vs_tex
); i
++) {
354 pipe_resource_reference(&ctx
->mapped_vs_tex
[i
], NULL
);
360 * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
363 llvmpipe_prepare_geometry_sampling(struct llvmpipe_context
*lp
,
365 struct pipe_sampler_view
**views
)
367 prepare_shader_sampling(lp
, num
, views
, PIPE_SHADER_GEOMETRY
,
372 llvmpipe_cleanup_geometry_sampling(struct llvmpipe_context
*ctx
)
375 for (i
= 0; i
< Elements(ctx
->mapped_gs_tex
); i
++) {
376 pipe_resource_reference(&ctx
->mapped_gs_tex
[i
], NULL
);
381 llvmpipe_init_sampler_funcs(struct llvmpipe_context
*llvmpipe
)
383 llvmpipe
->pipe
.create_sampler_state
= llvmpipe_create_sampler_state
;
385 llvmpipe
->pipe
.bind_sampler_states
= llvmpipe_bind_sampler_states
;
386 llvmpipe
->pipe
.create_sampler_view
= llvmpipe_create_sampler_view
;
387 llvmpipe
->pipe
.set_sampler_views
= llvmpipe_set_sampler_views
;
388 llvmpipe
->pipe
.sampler_view_destroy
= llvmpipe_sampler_view_destroy
;
389 llvmpipe
->pipe
.delete_sampler_state
= llvmpipe_delete_sampler_state
;