1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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
]));
81 if (start
+ num
<= llvmpipe
->num_samplers
[shader
] &&
82 !memcmp(llvmpipe
->samplers
[shader
] + start
, samplers
,
83 num
* sizeof(void *))) {
87 draw_flush(llvmpipe
->draw
);
89 /* set the new samplers */
90 for (i
= 0; i
< num
; i
++) {
91 llvmpipe
->samplers
[shader
][start
+ i
] = samplers
[i
];
94 /* find highest non-null samplers[] entry */
96 unsigned j
= MAX2(llvmpipe
->num_samplers
[shader
], start
+ num
);
97 while (j
> 0 && llvmpipe
->samplers
[shader
][j
- 1] == NULL
)
99 llvmpipe
->num_samplers
[shader
] = j
;
102 if (shader
== PIPE_SHADER_VERTEX
|| shader
== PIPE_SHADER_GEOMETRY
) {
103 draw_set_samplers(llvmpipe
->draw
,
105 llvmpipe
->samplers
[shader
],
106 llvmpipe
->num_samplers
[shader
]);
109 llvmpipe
->dirty
|= LP_NEW_SAMPLER
;
114 llvmpipe_bind_fragment_sampler_states(struct pipe_context
*pipe
,
115 unsigned num
, void **samplers
)
117 llvmpipe_bind_sampler_states(pipe
, PIPE_SHADER_FRAGMENT
, 0, num
, samplers
);
122 llvmpipe_bind_vertex_sampler_states(struct pipe_context
*pipe
,
123 unsigned num
, void **samplers
)
125 llvmpipe_bind_sampler_states(pipe
, PIPE_SHADER_VERTEX
, 0, num
, samplers
);
130 llvmpipe_bind_geometry_sampler_states(struct pipe_context
*pipe
,
131 unsigned num
, void **samplers
)
133 llvmpipe_bind_sampler_states(pipe
, PIPE_SHADER_GEOMETRY
, 0, num
, samplers
);
137 llvmpipe_set_sampler_views(struct pipe_context
*pipe
,
141 struct pipe_sampler_view
**views
)
143 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
146 assert(num
<= PIPE_MAX_SHADER_SAMPLER_VIEWS
);
148 assert(shader
< PIPE_SHADER_TYPES
);
149 assert(start
+ num
<= Elements(llvmpipe
->sampler_views
[shader
]));
151 /* Check for no-op */
152 if (start
+ num
<= llvmpipe
->num_sampler_views
[shader
] &&
153 !memcmp(llvmpipe
->sampler_views
[shader
] + start
, views
,
154 num
* sizeof(struct pipe_sampler_view
*))) {
158 draw_flush(llvmpipe
->draw
);
160 /* set the new sampler views */
161 for (i
= 0; i
< num
; i
++) {
162 pipe_sampler_view_reference(&llvmpipe
->sampler_views
[shader
][start
+ i
],
166 /* find highest non-null sampler_views[] entry */
168 unsigned j
= MAX2(llvmpipe
->num_sampler_views
[shader
], start
+ num
);
169 while (j
> 0 && llvmpipe
->sampler_views
[shader
][j
- 1] == NULL
)
171 llvmpipe
->num_sampler_views
[shader
] = j
;
174 if (shader
== PIPE_SHADER_VERTEX
|| shader
== PIPE_SHADER_GEOMETRY
) {
175 draw_set_sampler_views(llvmpipe
->draw
,
177 llvmpipe
->sampler_views
[shader
],
178 llvmpipe
->num_sampler_views
[shader
]);
181 llvmpipe
->dirty
|= LP_NEW_SAMPLER_VIEW
;
186 llvmpipe_set_fragment_sampler_views(struct pipe_context
*pipe
,
188 struct pipe_sampler_view
**views
)
190 llvmpipe_set_sampler_views(pipe
, PIPE_SHADER_FRAGMENT
, 0, num
, views
);
195 llvmpipe_set_vertex_sampler_views(struct pipe_context
*pipe
,
197 struct pipe_sampler_view
**views
)
199 llvmpipe_set_sampler_views(pipe
, PIPE_SHADER_VERTEX
, 0, num
, views
);
204 llvmpipe_set_geometry_sampler_views(struct pipe_context
*pipe
,
206 struct pipe_sampler_view
**views
)
208 llvmpipe_set_sampler_views(pipe
, PIPE_SHADER_GEOMETRY
, 0, num
, views
);
211 static struct pipe_sampler_view
*
212 llvmpipe_create_sampler_view(struct pipe_context
*pipe
,
213 struct pipe_resource
*texture
,
214 const struct pipe_sampler_view
*templ
)
216 struct pipe_sampler_view
*view
= CALLOC_STRUCT(pipe_sampler_view
);
220 view
->reference
.count
= 1;
221 view
->texture
= NULL
;
222 pipe_resource_reference(&view
->texture
, texture
);
223 view
->context
= pipe
;
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 * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
251 llvmpipe_prepare_vertex_sampling(struct llvmpipe_context
*lp
,
253 struct pipe_sampler_view
**views
)
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
< PIPE_MAX_SHADER_SAMPLER_VIEWS
; 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
);
273 if (tex
->target
== PIPE_TEXTURE_3D
) {
274 num_layers
= tex
->depth0
;
277 num_layers
= tex
->array_size
;
280 /* We're referencing the texture's internal data, so save a
283 pipe_resource_reference(&lp
->mapped_vs_tex
[i
], tex
);
286 /* regular texture - setup array of mipmap level pointers */
287 /* XXX this may fail due to OOM ? */
290 /* must trigger allocation first before we can get base ptr */
291 mip_ptr
= llvmpipe_get_texture_image_all(lp_tex
, view
->u
.tex
.first_level
,
293 LP_TEX_LAYOUT_LINEAR
);
294 addr
= lp_tex
->linear_img
.data
;
295 for (j
= view
->u
.tex
.first_level
; j
<= tex
->last_level
; j
++) {
296 mip_ptr
= llvmpipe_get_texture_image_all(lp_tex
, j
,
298 LP_TEX_LAYOUT_LINEAR
);
299 mip_offsets
[j
] = (uint8_t *)mip_ptr
- (uint8_t *)addr
;
301 * could get mip offset directly but need call above to
302 * invoke tiled->linear conversion.
304 assert(lp_tex
->linear_mip_offsets
[j
] == mip_offsets
[j
]);
305 row_stride
[j
] = lp_tex
->row_stride
[j
];
306 img_stride
[j
] = lp_tex
->img_stride
[j
];
310 /* display target texture/surface */
312 * XXX: Where should this be unmapped?
314 struct llvmpipe_screen
*screen
= llvmpipe_screen(tex
->screen
);
315 struct sw_winsys
*winsys
= screen
->winsys
;
316 addr
= winsys
->displaytarget_map(winsys
, lp_tex
->dt
,
318 row_stride
[0] = lp_tex
->row_stride
[0];
319 img_stride
[0] = lp_tex
->img_stride
[0];
323 draw_set_mapped_texture(lp
->draw
,
326 tex
->width0
, tex
->height0
, num_layers
,
327 view
->u
.tex
.first_level
, tex
->last_level
,
329 row_stride
, img_stride
, mip_offsets
);
335 llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context
*ctx
)
338 for (i
= 0; i
< Elements(ctx
->mapped_vs_tex
); i
++) {
339 pipe_resource_reference(&ctx
->mapped_vs_tex
[i
], NULL
);
344 llvmpipe_init_sampler_funcs(struct llvmpipe_context
*llvmpipe
)
346 llvmpipe
->pipe
.create_sampler_state
= llvmpipe_create_sampler_state
;
348 llvmpipe
->pipe
.bind_fragment_sampler_states
= llvmpipe_bind_fragment_sampler_states
;
349 llvmpipe
->pipe
.bind_vertex_sampler_states
= llvmpipe_bind_vertex_sampler_states
;
350 llvmpipe
->pipe
.bind_geometry_sampler_states
= llvmpipe_bind_geometry_sampler_states
;
351 llvmpipe
->pipe
.set_fragment_sampler_views
= llvmpipe_set_fragment_sampler_views
;
352 llvmpipe
->pipe
.set_vertex_sampler_views
= llvmpipe_set_vertex_sampler_views
;
353 llvmpipe
->pipe
.set_geometry_sampler_views
= llvmpipe_set_geometry_sampler_views
;
354 llvmpipe
->pipe
.create_sampler_view
= llvmpipe_create_sampler_view
;
355 llvmpipe
->pipe
.sampler_view_destroy
= llvmpipe_sampler_view_destroy
;
356 llvmpipe
->pipe
.delete_sampler_state
= llvmpipe_delete_sampler_state
;