st/mesa: use new _mesa_base_tex_image() helper
[mesa.git] / src / mesa / state_tracker / st_atom_texture.c
1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keithw@vmware.com>
31 * Brian Paul
32 */
33
34
35 #include "main/macros.h"
36 #include "main/mtypes.h"
37 #include "main/samplerobj.h"
38 #include "main/teximage.h"
39 #include "main/texobj.h"
40 #include "program/prog_instruction.h"
41
42 #include "st_context.h"
43 #include "st_atom.h"
44 #include "st_texture.h"
45 #include "st_format.h"
46 #include "st_cb_texture.h"
47 #include "pipe/p_context.h"
48 #include "util/u_format.h"
49 #include "util/u_inlines.h"
50 #include "cso_cache/cso_context.h"
51
52
53 /**
54 * Return swizzle1(swizzle2)
55 */
56 static unsigned
57 swizzle_swizzle(unsigned swizzle1, unsigned swizzle2)
58 {
59 unsigned i, swz[4];
60
61 for (i = 0; i < 4; i++) {
62 unsigned s = GET_SWZ(swizzle1, i);
63 switch (s) {
64 case SWIZZLE_X:
65 case SWIZZLE_Y:
66 case SWIZZLE_Z:
67 case SWIZZLE_W:
68 swz[i] = GET_SWZ(swizzle2, s);
69 break;
70 case SWIZZLE_ZERO:
71 swz[i] = SWIZZLE_ZERO;
72 break;
73 case SWIZZLE_ONE:
74 swz[i] = SWIZZLE_ONE;
75 break;
76 default:
77 assert(!"Bad swizzle term");
78 swz[i] = SWIZZLE_X;
79 }
80 }
81
82 return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
83 }
84
85
86 /**
87 * Given a user-specified texture base format, the actual gallium texture
88 * format and the current GL_DEPTH_MODE, return a texture swizzle.
89 *
90 * Consider the case where the user requests a GL_RGB internal texture
91 * format the driver actually uses an RGBA format. The A component should
92 * be ignored and sampling from the texture should always return (r,g,b,1).
93 * But if we rendered to the texture we might have written A values != 1.
94 * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
95 * This function computes the texture swizzle needed to get the expected
96 * values.
97 *
98 * In the case of depth textures, the GL_DEPTH_MODE state determines the
99 * texture swizzle.
100 *
101 * This result must be composed with the user-specified swizzle to get
102 * the final swizzle.
103 */
104 static unsigned
105 compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
106 enum pipe_format actualFormat)
107 {
108 switch (baseFormat) {
109 case GL_RGBA:
110 return SWIZZLE_XYZW;
111 case GL_RGB:
112 if (util_format_has_alpha(actualFormat))
113 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
114 else
115 return SWIZZLE_XYZW;
116 case GL_RG:
117 if (util_format_get_nr_components(actualFormat) > 2)
118 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
119 else
120 return SWIZZLE_XYZW;
121 case GL_RED:
122 if (util_format_get_nr_components(actualFormat) > 1)
123 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
124 SWIZZLE_ZERO, SWIZZLE_ONE);
125 else
126 return SWIZZLE_XYZW;
127 case GL_ALPHA:
128 if (util_format_get_nr_components(actualFormat) > 1)
129 return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
130 SWIZZLE_ZERO, SWIZZLE_W);
131 else
132 return SWIZZLE_XYZW;
133 case GL_LUMINANCE:
134 if (util_format_get_nr_components(actualFormat) > 1)
135 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
136 else
137 return SWIZZLE_XYZW;
138 case GL_LUMINANCE_ALPHA:
139 if (util_format_get_nr_components(actualFormat) > 2)
140 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
141 else
142 return SWIZZLE_XYZW;
143 case GL_INTENSITY:
144 if (util_format_get_nr_components(actualFormat) > 1)
145 return SWIZZLE_XXXX;
146 else
147 return SWIZZLE_XYZW;
148 case GL_STENCIL_INDEX:
149 return SWIZZLE_XYZW;
150 case GL_DEPTH_STENCIL:
151 /* fall-through */
152 case GL_DEPTH_COMPONENT:
153 /* Now examine the depth mode */
154 switch (depthMode) {
155 case GL_LUMINANCE:
156 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
157 case GL_INTENSITY:
158 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
159 case GL_ALPHA:
160 return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
161 SWIZZLE_ZERO, SWIZZLE_X);
162 case GL_RED:
163 return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
164 SWIZZLE_ZERO, SWIZZLE_ONE);
165 default:
166 assert(!"Unexpected depthMode");
167 return SWIZZLE_XYZW;
168 }
169 default:
170 assert(!"Unexpected baseFormat");
171 return SWIZZLE_XYZW;
172 }
173 }
174
175
176 static unsigned
177 get_texture_format_swizzle(const struct st_texture_object *stObj)
178 {
179 const struct gl_texture_image *texImage =
180 _mesa_base_tex_image_const(&stObj->base);
181 unsigned tex_swizzle;
182
183 if (texImage) {
184 tex_swizzle = compute_texture_format_swizzle(texImage->_BaseFormat,
185 stObj->base.DepthMode,
186 stObj->pt->format);
187 }
188 else {
189 tex_swizzle = SWIZZLE_XYZW;
190 }
191
192 /* Combine the texture format swizzle with user's swizzle */
193 return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle);
194 }
195
196
197 /**
198 * Return TRUE if the texture's sampler view swizzle is not equal to
199 * the texture's swizzle.
200 *
201 * \param stObj the st texture object,
202 */
203 static boolean
204 check_sampler_swizzle(const struct st_texture_object *stObj,
205 struct pipe_sampler_view *sv)
206 {
207 unsigned swizzle = get_texture_format_swizzle(stObj);
208
209 return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
210 (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
211 (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
212 (sv->swizzle_a != GET_SWZ(swizzle, 3)));
213 }
214
215
216 static unsigned last_level(struct st_texture_object *stObj)
217 {
218 unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel,
219 stObj->pt->last_level);
220 if (stObj->base.Immutable)
221 ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1);
222 return ret;
223 }
224
225 static unsigned last_layer(struct st_texture_object *stObj)
226 {
227 if (stObj->base.Immutable && stObj->pt->array_size > 1)
228 return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1,
229 stObj->pt->array_size - 1);
230 return stObj->pt->array_size - 1;
231 }
232
233 static struct pipe_sampler_view *
234 st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
235 struct st_texture_object *stObj,
236 const struct gl_sampler_object *samp,
237 enum pipe_format format)
238 {
239 struct pipe_sampler_view templ;
240 unsigned swizzle = get_texture_format_swizzle(stObj);
241
242 u_sampler_view_default_template(&templ,
243 stObj->pt,
244 format);
245
246 if (stObj->pt->target == PIPE_BUFFER) {
247 unsigned base, size;
248 unsigned f, n;
249 const struct util_format_description *desc
250 = util_format_description(templ.format);
251
252 base = stObj->base.BufferOffset;
253 if (base >= stObj->pt->width0)
254 return NULL;
255 size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
256
257 f = ((base * 8) / desc->block.bits) * desc->block.width;
258 n = ((size * 8) / desc->block.bits) * desc->block.width;
259 if (!n)
260 return NULL;
261 templ.u.buf.first_element = f;
262 templ.u.buf.last_element = f + (n - 1);
263 } else {
264 templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
265 templ.u.tex.last_level = last_level(stObj);
266 assert(templ.u.tex.first_level <= templ.u.tex.last_level);
267 templ.u.tex.first_layer = stObj->base.MinLayer;
268 templ.u.tex.last_layer = last_layer(stObj);
269 assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
270 templ.target = gl_target_to_pipe(stObj->base.Target);
271 }
272
273 if (swizzle != SWIZZLE_NOOP) {
274 templ.swizzle_r = GET_SWZ(swizzle, 0);
275 templ.swizzle_g = GET_SWZ(swizzle, 1);
276 templ.swizzle_b = GET_SWZ(swizzle, 2);
277 templ.swizzle_a = GET_SWZ(swizzle, 3);
278 }
279
280 return pipe->create_sampler_view(pipe, stObj->pt, &templ);
281 }
282
283
284 static struct pipe_sampler_view *
285 st_get_texture_sampler_view_from_stobj(struct st_context *st,
286 struct st_texture_object *stObj,
287 const struct gl_sampler_object *samp,
288 enum pipe_format format)
289 {
290 struct pipe_sampler_view **sv;
291
292 if (!stObj || !stObj->pt) {
293 return NULL;
294 }
295
296 sv = st_texture_get_sampler_view(st, stObj);
297
298 if (stObj->base.StencilSampling &&
299 util_format_is_depth_and_stencil(format))
300 format = util_format_stencil_only(format);
301
302 /* if sampler view has changed dereference it */
303 if (*sv) {
304 if (check_sampler_swizzle(stObj, *sv) ||
305 (format != (*sv)->format) ||
306 gl_target_to_pipe(stObj->base.Target) != (*sv)->target ||
307 stObj->base.MinLevel + stObj->base.BaseLevel != (*sv)->u.tex.first_level ||
308 last_level(stObj) != (*sv)->u.tex.last_level ||
309 stObj->base.MinLayer != (*sv)->u.tex.first_layer ||
310 last_layer(stObj) != (*sv)->u.tex.last_layer) {
311 pipe_sampler_view_reference(sv, NULL);
312 }
313 }
314
315 if (!*sv) {
316 *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, samp, format);
317
318 } else if ((*sv)->context != st->pipe) {
319 /* Recreate view in correct context, use existing view as template */
320 struct pipe_sampler_view *new_sv =
321 st->pipe->create_sampler_view(st->pipe, stObj->pt, *sv);
322 pipe_sampler_view_reference(sv, NULL);
323 *sv = new_sv;
324 }
325
326 return *sv;
327 }
328
329 static GLboolean
330 update_single_texture(struct st_context *st,
331 struct pipe_sampler_view **sampler_view,
332 GLuint texUnit)
333 {
334 struct gl_context *ctx = st->ctx;
335 const struct gl_sampler_object *samp;
336 struct gl_texture_object *texObj;
337 struct st_texture_object *stObj;
338 enum pipe_format view_format;
339 GLboolean retval;
340
341 samp = _mesa_get_samplerobj(ctx, texUnit);
342
343 texObj = ctx->Texture.Unit[texUnit]._Current;
344
345 if (!texObj) {
346 texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
347 samp = &texObj->Sampler;
348 }
349 stObj = st_texture_object(texObj);
350
351 retval = st_finalize_texture(ctx, st->pipe, texObj);
352 if (!retval) {
353 /* out of mem */
354 return GL_FALSE;
355 }
356
357 /* Determine the format of the texture sampler view */
358 if (texObj->Target == GL_TEXTURE_BUFFER) {
359 view_format =
360 st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
361 }
362 else {
363 view_format =
364 stObj->surface_based ? stObj->surface_format : stObj->pt->format;
365
366 /* If sRGB decoding is off, use the linear format */
367 if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
368 view_format = util_format_linear(view_format);
369 }
370 }
371
372 *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp,
373 view_format);
374 return GL_TRUE;
375 }
376
377
378
379 static void
380 update_textures(struct st_context *st,
381 unsigned shader_stage,
382 const struct gl_program *prog,
383 unsigned max_units,
384 struct pipe_sampler_view **sampler_views,
385 unsigned *num_textures)
386 {
387 const GLuint old_max = *num_textures;
388 GLbitfield samplers_used = prog->SamplersUsed;
389 GLuint unit;
390
391 if (samplers_used == 0x0 && old_max == 0)
392 return;
393
394 *num_textures = 0;
395
396 /* loop over sampler units (aka tex image units) */
397 for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) {
398 struct pipe_sampler_view *sampler_view = NULL;
399
400 if (samplers_used & 1) {
401 const GLuint texUnit = prog->SamplerUnits[unit];
402 GLboolean retval;
403
404 retval = update_single_texture(st, &sampler_view, texUnit);
405 if (retval == GL_FALSE)
406 continue;
407
408 *num_textures = unit + 1;
409 }
410 else if (samplers_used == 0 && unit >= old_max) {
411 /* if we've reset all the old views and we have no more new ones */
412 break;
413 }
414
415 pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view);
416 }
417
418 cso_set_sampler_views(st->cso_context,
419 shader_stage,
420 *num_textures,
421 sampler_views);
422 }
423
424
425
426 static void
427 update_vertex_textures(struct st_context *st)
428 {
429 const struct gl_context *ctx = st->ctx;
430
431 if (ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits > 0) {
432 update_textures(st,
433 PIPE_SHADER_VERTEX,
434 &ctx->VertexProgram._Current->Base,
435 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits,
436 st->state.sampler_views[PIPE_SHADER_VERTEX],
437 &st->state.num_sampler_views[PIPE_SHADER_VERTEX]);
438 }
439 }
440
441
442 static void
443 update_fragment_textures(struct st_context *st)
444 {
445 const struct gl_context *ctx = st->ctx;
446
447 update_textures(st,
448 PIPE_SHADER_FRAGMENT,
449 &ctx->FragmentProgram._Current->Base,
450 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits,
451 st->state.sampler_views[PIPE_SHADER_FRAGMENT],
452 &st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
453 }
454
455
456 static void
457 update_geometry_textures(struct st_context *st)
458 {
459 const struct gl_context *ctx = st->ctx;
460
461 if (ctx->GeometryProgram._Current) {
462 update_textures(st,
463 PIPE_SHADER_GEOMETRY,
464 &ctx->GeometryProgram._Current->Base,
465 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits,
466 st->state.sampler_views[PIPE_SHADER_GEOMETRY],
467 &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]);
468 }
469 }
470
471
472 const struct st_tracked_state st_update_fragment_texture = {
473 "st_update_texture", /* name */
474 { /* dirty */
475 _NEW_TEXTURE, /* mesa */
476 ST_NEW_FRAGMENT_PROGRAM, /* st */
477 },
478 update_fragment_textures /* update */
479 };
480
481
482 const struct st_tracked_state st_update_vertex_texture = {
483 "st_update_vertex_texture", /* name */
484 { /* dirty */
485 _NEW_TEXTURE, /* mesa */
486 ST_NEW_VERTEX_PROGRAM, /* st */
487 },
488 update_vertex_textures /* update */
489 };
490
491
492 const struct st_tracked_state st_update_geometry_texture = {
493 "st_update_geometry_texture", /* name */
494 { /* dirty */
495 _NEW_TEXTURE, /* mesa */
496 ST_NEW_GEOMETRY_PROGRAM, /* st */
497 },
498 update_geometry_textures /* update */
499 };
500
501
502
503 static void
504 finalize_textures(struct st_context *st)
505 {
506 struct gl_context *ctx = st->ctx;
507 struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
508 const GLboolean prev_missing_textures = st->missing_textures;
509 GLuint su;
510
511 st->missing_textures = GL_FALSE;
512
513 for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) {
514 if (fprog->Base.SamplersUsed & (1 << su)) {
515 const GLuint texUnit = fprog->Base.SamplerUnits[su];
516 struct gl_texture_object *texObj
517 = ctx->Texture.Unit[texUnit]._Current;
518
519 if (texObj) {
520 GLboolean retval;
521
522 retval = st_finalize_texture(ctx, st->pipe, texObj);
523 if (!retval) {
524 /* out of mem */
525 st->missing_textures = GL_TRUE;
526 continue;
527 }
528 }
529 }
530 }
531
532 if (prev_missing_textures != st->missing_textures)
533 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
534 }
535
536
537 const struct st_tracked_state st_finalize_textures = {
538 "st_finalize_textures", /* name */
539 { /* dirty */
540 _NEW_TEXTURE, /* mesa */
541 0, /* st */
542 },
543 finalize_textures /* update */
544 };