1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2011 VMware, Inc. 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 "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file samplerobj.c
28 * \brief Functions for the GL_ARB_sampler_objects extension.
29 * \author Brian Paul
30 */
31
32
33 #include "main/glheader.h"
34 #include "main/context.h"
35 #include "main/enums.h"
36 #include "main/hash.h"
37 #include "main/macros.h"
38 #include "main/mtypes.h"
39 #include "main/samplerobj.h"
40 #include "main/texturebindless.h"
41 #include "util/u_memory.h"
42 #include "api_exec_decl.h"
43
44 /* Take advantage of how the enums are defined. */
45 const enum pipe_tex_wrap wrap_to_gallium_table[32] = {
46 [GL_REPEAT & 0x1f] = PIPE_TEX_WRAP_REPEAT,
47 [GL_CLAMP & 0x1f] = PIPE_TEX_WRAP_CLAMP,
48 [GL_CLAMP_TO_EDGE & 0x1f] = PIPE_TEX_WRAP_CLAMP_TO_EDGE,
49 [GL_CLAMP_TO_BORDER & 0x1f] = PIPE_TEX_WRAP_CLAMP_TO_BORDER,
50 [GL_MIRRORED_REPEAT & 0x1f] = PIPE_TEX_WRAP_MIRROR_REPEAT,
51 [GL_MIRROR_CLAMP_EXT & 0x1f] = PIPE_TEX_WRAP_MIRROR_CLAMP,
52 [GL_MIRROR_CLAMP_TO_EDGE & 0x1f] = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE,
53 [GL_MIRROR_CLAMP_TO_BORDER_EXT & 0x1f] = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER,
54 };
55
56 struct gl_sampler_object *
_mesa_lookup_samplerobj(struct gl_context * ctx,GLuint name)57 _mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
58 {
59 if (name == 0)
60 return NULL;
61 else
62 return (struct gl_sampler_object *)
63 _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
64 }
65
66 static inline struct gl_sampler_object *
lookup_samplerobj_locked(struct gl_context * ctx,GLuint name)67 lookup_samplerobj_locked(struct gl_context *ctx, GLuint name)
68 {
69 return (struct gl_sampler_object *)
70 _mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name);
71 }
72
73 static void
delete_sampler_object(struct gl_context * ctx,struct gl_sampler_object * sampObj)74 delete_sampler_object(struct gl_context *ctx,
75 struct gl_sampler_object *sampObj)
76 {
77 _mesa_delete_sampler_handles(ctx, sampObj);
78 free(sampObj->Label);
79 FREE(sampObj);
80 }
81
82 /**
83 * Handle reference counting.
84 */
85 void
_mesa_reference_sampler_object_(struct gl_context * ctx,struct gl_sampler_object ** ptr,struct gl_sampler_object * samp)86 _mesa_reference_sampler_object_(struct gl_context *ctx,
87 struct gl_sampler_object **ptr,
88 struct gl_sampler_object *samp)
89 {
90 assert(*ptr != samp); /* The inline wrapper should prevent no-op calls */
91
92 if (*ptr) {
93 /* Unreference the old sampler */
94 struct gl_sampler_object *oldSamp = *ptr;
95
96 assert(oldSamp->RefCount > 0);
97
98 if (p_atomic_dec_zero(&oldSamp->RefCount))
99 delete_sampler_object(ctx, oldSamp);
100 }
101
102 if (samp) {
103 /* reference new sampler */
104 assert(samp->RefCount > 0);
105
106 p_atomic_inc(&samp->RefCount);
107 }
108
109 *ptr = samp;
110 }
111
112
113 /**
114 * Initialize the fields of the given sampler object.
115 */
116 static void
_mesa_init_sampler_object(struct gl_sampler_object * sampObj,GLuint name)117 _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
118 {
119 sampObj->Name = name;
120 sampObj->RefCount = 1;
121 sampObj->Attrib.WrapS = GL_REPEAT;
122 sampObj->Attrib.WrapT = GL_REPEAT;
123 sampObj->Attrib.WrapR = GL_REPEAT;
124 sampObj->Attrib.state.wrap_s = PIPE_TEX_WRAP_REPEAT;
125 sampObj->Attrib.state.wrap_t = PIPE_TEX_WRAP_REPEAT;
126 sampObj->Attrib.state.wrap_r = PIPE_TEX_WRAP_REPEAT;
127 sampObj->Attrib.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
128 sampObj->Attrib.MagFilter = GL_LINEAR;
129 sampObj->Attrib.state.min_img_filter = PIPE_TEX_FILTER_NEAREST;
130 sampObj->Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
131 sampObj->Attrib.state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
132 sampObj->Attrib.state.border_color.f[0] = 0;
133 sampObj->Attrib.state.border_color.f[1] = 0;
134 sampObj->Attrib.state.border_color.f[2] = 0;
135 sampObj->Attrib.state.border_color.f[3] = 0;
136 _mesa_update_is_border_color_nonzero(sampObj);
137 sampObj->Attrib.MinLod = -1000.0F;
138 sampObj->Attrib.MaxLod = 1000.0F;
139 sampObj->Attrib.state.min_lod = 0; /* Gallium doesn't allow negative numbers */
140 sampObj->Attrib.state.max_lod = 1000;
141 sampObj->Attrib.LodBias = 0.0F;
142 sampObj->Attrib.state.lod_bias = 0;
143 sampObj->Attrib.MaxAnisotropy = 1.0F;
144 sampObj->Attrib.state.max_anisotropy = 0; /* Gallium uses 0 instead of 1. */
145 sampObj->Attrib.CompareMode = GL_NONE;
146 sampObj->Attrib.CompareFunc = GL_LEQUAL;
147 sampObj->Attrib.state.compare_mode = PIPE_TEX_COMPARE_NONE;
148 sampObj->Attrib.state.compare_func = PIPE_FUNC_LEQUAL;
149 sampObj->Attrib.sRGBDecode = GL_DECODE_EXT;
150 sampObj->Attrib.CubeMapSeamless = GL_FALSE;
151 sampObj->Attrib.state.seamless_cube_map = false;
152 sampObj->Attrib.ReductionMode = GL_WEIGHTED_AVERAGE_EXT;
153 sampObj->Attrib.state.reduction_mode = PIPE_TEX_REDUCTION_WEIGHTED_AVERAGE;
154 sampObj->HandleAllocated = GL_FALSE;
155
156 /* GL_ARB_bindless_texture */
157 _mesa_init_sampler_handles(sampObj);
158 }
159
160 static struct gl_sampler_object *
_mesa_new_sampler_object(struct gl_context * ctx,GLuint name)161 _mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
162 {
163 struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
164 if (sampObj) {
165 _mesa_init_sampler_object(sampObj, name);
166 }
167 return sampObj;
168 }
169
170 static void
create_samplers(struct gl_context * ctx,GLsizei count,GLuint * samplers,const char * caller)171 create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
172 const char *caller)
173 {
174 GLint i;
175
176 if (!samplers)
177 return;
178
179 _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
180
181 _mesa_HashFindFreeKeys(ctx->Shared->SamplerObjects, samplers, count);
182
183 /* Insert the ID and pointer to new sampler object into hash table */
184 for (i = 0; i < count; i++) {
185 struct gl_sampler_object *sampObj;
186
187 sampObj = _mesa_new_sampler_object(ctx, samplers[i]);
188 if (!sampObj) {
189 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
190 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
191 return;
192 }
193
194 _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, samplers[i],
195 sampObj, true);
196 }
197
198 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
199 }
200
201 static void
create_samplers_err(struct gl_context * ctx,GLsizei count,GLuint * samplers,const char * caller)202 create_samplers_err(struct gl_context *ctx, GLsizei count, GLuint *samplers,
203 const char *caller)
204 {
205
206 if (MESA_VERBOSE & VERBOSE_API)
207 _mesa_debug(ctx, "%s(%d)\n", caller, count);
208
209 if (count < 0) {
210 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller);
211 return;
212 }
213
214 create_samplers(ctx, count, samplers, caller);
215 }
216
217 void GLAPIENTRY
_mesa_GenSamplers_no_error(GLsizei count,GLuint * samplers)218 _mesa_GenSamplers_no_error(GLsizei count, GLuint *samplers)
219 {
220 GET_CURRENT_CONTEXT(ctx);
221 create_samplers(ctx, count, samplers, "glGenSamplers");
222 }
223
224 void GLAPIENTRY
_mesa_GenSamplers(GLsizei count,GLuint * samplers)225 _mesa_GenSamplers(GLsizei count, GLuint *samplers)
226 {
227 GET_CURRENT_CONTEXT(ctx);
228 create_samplers_err(ctx, count, samplers, "glGenSamplers");
229 }
230
231 void GLAPIENTRY
_mesa_CreateSamplers_no_error(GLsizei count,GLuint * samplers)232 _mesa_CreateSamplers_no_error(GLsizei count, GLuint *samplers)
233 {
234 GET_CURRENT_CONTEXT(ctx);
235 create_samplers(ctx, count, samplers, "glCreateSamplers");
236 }
237
238 void GLAPIENTRY
_mesa_CreateSamplers(GLsizei count,GLuint * samplers)239 _mesa_CreateSamplers(GLsizei count, GLuint *samplers)
240 {
241 GET_CURRENT_CONTEXT(ctx);
242 create_samplers_err(ctx, count, samplers, "glCreateSamplers");
243 }
244
245
246 static void
delete_samplers(struct gl_context * ctx,GLsizei count,const GLuint * samplers)247 delete_samplers(struct gl_context *ctx, GLsizei count, const GLuint *samplers)
248 {
249 FLUSH_VERTICES(ctx, 0, 0);
250
251 _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
252
253 for (GLsizei i = 0; i < count; i++) {
254 if (samplers[i]) {
255 GLuint j;
256 struct gl_sampler_object *sampObj =
257 lookup_samplerobj_locked(ctx, samplers[i]);
258
259 if (sampObj) {
260 /* If the sampler is currently bound, unbind it. */
261 for (j = 0; j < ctx->Const.MaxCombinedTextureImageUnits; j++) {
262 if (ctx->Texture.Unit[j].Sampler == sampObj) {
263 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT);
264 _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL);
265 }
266 }
267
268 /* The ID is immediately freed for re-use */
269 _mesa_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]);
270 /* But the object exists until its reference count goes to zero */
271 _mesa_reference_sampler_object(ctx, &sampObj, NULL);
272 }
273 }
274 }
275
276 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
277 }
278
279
280 void GLAPIENTRY
_mesa_DeleteSamplers_no_error(GLsizei count,const GLuint * samplers)281 _mesa_DeleteSamplers_no_error(GLsizei count, const GLuint *samplers)
282 {
283 GET_CURRENT_CONTEXT(ctx);
284 delete_samplers(ctx, count, samplers);
285 }
286
287
288 void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count,const GLuint * samplers)289 _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
290 {
291 GET_CURRENT_CONTEXT(ctx);
292
293 if (count < 0) {
294 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
295 return;
296 }
297
298 delete_samplers(ctx, count, samplers);
299 }
300
301
302 GLboolean GLAPIENTRY
_mesa_IsSampler(GLuint sampler)303 _mesa_IsSampler(GLuint sampler)
304 {
305 GET_CURRENT_CONTEXT(ctx);
306
307 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
308
309 return _mesa_lookup_samplerobj(ctx, sampler) != NULL;
310 }
311
312 void
_mesa_bind_sampler(struct gl_context * ctx,GLuint unit,struct gl_sampler_object * sampObj)313 _mesa_bind_sampler(struct gl_context *ctx, GLuint unit,
314 struct gl_sampler_object *sampObj)
315 {
316 if (ctx->Texture.Unit[unit].Sampler != sampObj) {
317 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT);
318 }
319
320 _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
321 sampObj);
322 }
323
324 static ALWAYS_INLINE void
bind_sampler(struct gl_context * ctx,GLuint unit,GLuint sampler,bool no_error)325 bind_sampler(struct gl_context *ctx, GLuint unit, GLuint sampler, bool no_error)
326 {
327 struct gl_sampler_object *sampObj;
328
329 if (sampler == 0) {
330 /* Use the default sampler object, the one contained in the texture
331 * object.
332 */
333 sampObj = NULL;
334 } else {
335 /* user-defined sampler object */
336 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
337 if (!no_error && !sampObj) {
338 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
339 return;
340 }
341 }
342
343 /* bind new sampler */
344 _mesa_bind_sampler(ctx, unit, sampObj);
345 }
346
347 void GLAPIENTRY
_mesa_BindSampler_no_error(GLuint unit,GLuint sampler)348 _mesa_BindSampler_no_error(GLuint unit, GLuint sampler)
349 {
350 GET_CURRENT_CONTEXT(ctx);
351 bind_sampler(ctx, unit, sampler, true);
352 }
353
354 void GLAPIENTRY
_mesa_BindSampler(GLuint unit,GLuint sampler)355 _mesa_BindSampler(GLuint unit, GLuint sampler)
356 {
357 GET_CURRENT_CONTEXT(ctx);
358
359 if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
360 _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
361 return;
362 }
363
364 bind_sampler(ctx, unit, sampler, false);
365 }
366
367
368 static ALWAYS_INLINE void
bind_samplers(struct gl_context * ctx,GLuint first,GLsizei count,const GLuint * samplers,bool no_error)369 bind_samplers(struct gl_context *ctx, GLuint first, GLsizei count,
370 const GLuint *samplers, bool no_error)
371 {
372 GLsizei i;
373
374 FLUSH_VERTICES(ctx, 0, 0);
375
376 if (samplers) {
377 /* Note that the error semantics for multi-bind commands differ from
378 * those of other GL commands.
379 *
380 * The Issues section in the ARB_multi_bind spec says:
381 *
382 * "(11) Typically, OpenGL specifies that if an error is generated by
383 * a command, that command has no effect. This is somewhat
384 * unfortunate for multi-bind commands, because it would require
385 * a first pass to scan the entire list of bound objects for
386 * errors and then a second pass to actually perform the
387 * bindings. Should we have different error semantics?
388 *
389 * RESOLVED: Yes. In this specification, when the parameters for
390 * one of the <count> binding points are invalid, that binding
391 * point is not updated and an error will be generated. However,
392 * other binding points in the same command will be updated if
393 * their parameters are valid and no other error occurs."
394 */
395
396 _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
397
398 for (i = 0; i < count; i++) {
399 const GLuint unit = first + i;
400 struct gl_sampler_object * const currentSampler =
401 ctx->Texture.Unit[unit].Sampler;
402 struct gl_sampler_object *sampObj;
403
404 if (samplers[i] != 0) {
405 if (currentSampler && currentSampler->Name == samplers[i])
406 sampObj = currentSampler;
407 else
408 sampObj = lookup_samplerobj_locked(ctx, samplers[i]);
409
410 /* The ARB_multi_bind spec says:
411 *
412 * "An INVALID_OPERATION error is generated if any value
413 * in <samplers> is not zero or the name of an existing
414 * sampler object (per binding)."
415 */
416 if (!no_error && !sampObj) {
417 _mesa_error(ctx, GL_INVALID_OPERATION,
418 "glBindSamplers(samplers[%d]=%u is not zero or "
419 "the name of an existing sampler object)",
420 i, samplers[i]);
421 continue;
422 }
423 } else {
424 sampObj = NULL;
425 }
426
427 /* Bind the new sampler */
428 if (sampObj != currentSampler) {
429 _mesa_reference_sampler_object(ctx,
430 &ctx->Texture.Unit[unit].Sampler,
431 sampObj);
432 ctx->NewState |= _NEW_TEXTURE_OBJECT;
433 ctx->PopAttribState |= GL_TEXTURE_BIT;
434 }
435 }
436
437 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
438 } else {
439 /* Unbind all samplers in the range <first> through <first>+<count>-1 */
440 for (i = 0; i < count; i++) {
441 const GLuint unit = first + i;
442
443 if (ctx->Texture.Unit[unit].Sampler) {
444 _mesa_reference_sampler_object(ctx,
445 &ctx->Texture.Unit[unit].Sampler,
446 NULL);
447 ctx->NewState |= _NEW_TEXTURE_OBJECT;
448 ctx->PopAttribState |= GL_TEXTURE_BIT;
449 }
450 }
451 }
452 }
453
454
455 void GLAPIENTRY
_mesa_BindSamplers_no_error(GLuint first,GLsizei count,const GLuint * samplers)456 _mesa_BindSamplers_no_error(GLuint first, GLsizei count, const GLuint *samplers)
457 {
458 GET_CURRENT_CONTEXT(ctx);
459 bind_samplers(ctx, first, count, samplers, true);
460 }
461
462
463 void GLAPIENTRY
_mesa_BindSamplers(GLuint first,GLsizei count,const GLuint * samplers)464 _mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
465 {
466 GET_CURRENT_CONTEXT(ctx);
467
468 /* The ARB_multi_bind spec says:
469 *
470 * "An INVALID_OPERATION error is generated if <first> + <count> is
471 * greater than the number of texture image units supported by
472 * the implementation."
473 */
474 if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
475 _mesa_error(ctx, GL_INVALID_OPERATION,
476 "glBindSamplers(first=%u + count=%d > the value of "
477 "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
478 first, count, ctx->Const.MaxCombinedTextureImageUnits);
479 return;
480 }
481
482 bind_samplers(ctx, first, count, samplers, false);
483 }
484
485
486 /**
487 * Check if a coordinate wrap mode is legal.
488 * \return GL_TRUE if legal, GL_FALSE otherwise
489 */
490 static GLboolean
validate_texture_wrap_mode(struct gl_context * ctx,GLenum wrap)491 validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
492 {
493 const struct gl_extensions * const e = &ctx->Extensions;
494
495 switch (wrap) {
496 case GL_CLAMP:
497 /* From GL 3.0 specification section E.1 "Profiles and Deprecated
498 * Features of OpenGL 3.0":
499 *
500 * - Texture wrap mode CLAMP - CLAMP is no longer accepted as a value of
501 * texture parameters TEXTURE_WRAP_S, TEXTURE_WRAP_T, or
502 * TEXTURE_WRAP_R.
503 */
504 return ctx->API == API_OPENGL_COMPAT;
505 case GL_CLAMP_TO_EDGE:
506 case GL_REPEAT:
507 case GL_MIRRORED_REPEAT:
508 case GL_CLAMP_TO_BORDER:
509 return GL_TRUE;
510 case GL_MIRROR_CLAMP_EXT:
511 return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
512 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
513 return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge;
514 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
515 return e->EXT_texture_mirror_clamp;
516 default:
517 return GL_FALSE;
518 }
519 }
520
521
522 /**
523 * This is called just prior to changing any sampler object state.
524 */
525 static inline void
flush(struct gl_context * ctx)526 flush(struct gl_context *ctx)
527 {
528 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT);
529 }
530
531 #define INVALID_PARAM 0x100
532 #define INVALID_PNAME 0x101
533 #define INVALID_VALUE 0x102
534
535 static GLuint
set_sampler_wrap_s(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)536 set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
537 GLint param)
538 {
539 if (samp->Attrib.WrapS == param)
540 return GL_FALSE;
541 if (validate_texture_wrap_mode(ctx, param)) {
542 flush(ctx);
543 update_sampler_gl_clamp(ctx, samp, is_wrap_gl_clamp(samp->Attrib.WrapS), is_wrap_gl_clamp(param), WRAP_S);
544 samp->Attrib.WrapS = param;
545 samp->Attrib.state.wrap_s = wrap_to_gallium(param);
546 _mesa_lower_gl_clamp(ctx, samp);
547 return GL_TRUE;
548 }
549 return INVALID_PARAM;
550 }
551
552
553 static GLuint
set_sampler_wrap_t(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)554 set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
555 GLint param)
556 {
557 if (samp->Attrib.WrapT == param)
558 return GL_FALSE;
559 if (validate_texture_wrap_mode(ctx, param)) {
560 flush(ctx);
561 update_sampler_gl_clamp(ctx, samp, is_wrap_gl_clamp(samp->Attrib.WrapT), is_wrap_gl_clamp(param), WRAP_T);
562 samp->Attrib.WrapT = param;
563 samp->Attrib.state.wrap_t = wrap_to_gallium(param);
564 _mesa_lower_gl_clamp(ctx, samp);
565 return GL_TRUE;
566 }
567 return INVALID_PARAM;
568 }
569
570
571 static GLuint
set_sampler_wrap_r(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)572 set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
573 GLint param)
574 {
575 if (samp->Attrib.WrapR == param)
576 return GL_FALSE;
577 if (validate_texture_wrap_mode(ctx, param)) {
578 flush(ctx);
579 update_sampler_gl_clamp(ctx, samp, is_wrap_gl_clamp(samp->Attrib.WrapR), is_wrap_gl_clamp(param), WRAP_R);
580 samp->Attrib.WrapR = param;
581 samp->Attrib.state.wrap_r = wrap_to_gallium(param);
582 _mesa_lower_gl_clamp(ctx, samp);
583 return GL_TRUE;
584 }
585 return INVALID_PARAM;
586 }
587
588 static GLuint
set_sampler_min_filter(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)589 set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
590 GLint param)
591 {
592 if (samp->Attrib.MinFilter == param)
593 return GL_FALSE;
594
595 switch (param) {
596 case GL_NEAREST:
597 case GL_LINEAR:
598 case GL_NEAREST_MIPMAP_NEAREST:
599 case GL_LINEAR_MIPMAP_NEAREST:
600 case GL_NEAREST_MIPMAP_LINEAR:
601 case GL_LINEAR_MIPMAP_LINEAR:
602 flush(ctx);
603 samp->Attrib.MinFilter = param;
604 samp->Attrib.state.min_img_filter = filter_to_gallium(param);
605 samp->Attrib.state.min_mip_filter = mipfilter_to_gallium(param);
606 _mesa_lower_gl_clamp(ctx, samp);
607 return GL_TRUE;
608 default:
609 return INVALID_PARAM;
610 }
611 }
612
613
614 static GLuint
set_sampler_mag_filter(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)615 set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
616 GLint param)
617 {
618 if (samp->Attrib.MagFilter == param)
619 return GL_FALSE;
620
621 switch (param) {
622 case GL_NEAREST:
623 case GL_LINEAR:
624 flush(ctx);
625 samp->Attrib.MagFilter = param;
626 samp->Attrib.state.mag_img_filter = filter_to_gallium(param);
627 _mesa_lower_gl_clamp(ctx, samp);
628 return GL_TRUE;
629 default:
630 return INVALID_PARAM;
631 }
632 }
633
634
635 static GLuint
set_sampler_lod_bias(struct gl_context * ctx,struct gl_sampler_object * samp,GLfloat param)636 set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
637 GLfloat param)
638 {
639 if (samp->Attrib.LodBias == param)
640 return GL_FALSE;
641
642 flush(ctx);
643 samp->Attrib.LodBias = param;
644 samp->Attrib.state.lod_bias = util_quantize_lod_bias(param);
645 return GL_TRUE;
646 }
647
648
649 static GLuint
set_sampler_border_colorf(struct gl_context * ctx,struct gl_sampler_object * samp,const GLfloat params[4])650 set_sampler_border_colorf(struct gl_context *ctx,
651 struct gl_sampler_object *samp,
652 const GLfloat params[4])
653 {
654 flush(ctx);
655 memcpy(samp->Attrib.state.border_color.f, params, 4 * sizeof(float));
656 _mesa_update_is_border_color_nonzero(samp);
657 return GL_TRUE;
658 }
659
660
661 static GLuint
set_sampler_border_colori(struct gl_context * ctx,struct gl_sampler_object * samp,const GLint params[4])662 set_sampler_border_colori(struct gl_context *ctx,
663 struct gl_sampler_object *samp,
664 const GLint params[4])
665 {
666 flush(ctx);
667 memcpy(samp->Attrib.state.border_color.i, params, 4 * sizeof(float));
668 _mesa_update_is_border_color_nonzero(samp);
669 return GL_TRUE;
670 }
671
672
673 static GLuint
set_sampler_border_colorui(struct gl_context * ctx,struct gl_sampler_object * samp,const GLuint params[4])674 set_sampler_border_colorui(struct gl_context *ctx,
675 struct gl_sampler_object *samp,
676 const GLuint params[4])
677 {
678 flush(ctx);
679 memcpy(samp->Attrib.state.border_color.ui, params, 4 * sizeof(float));
680 _mesa_update_is_border_color_nonzero(samp);
681 return GL_TRUE;
682 }
683
684
685 static GLuint
set_sampler_min_lod(struct gl_context * ctx,struct gl_sampler_object * samp,GLfloat param)686 set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
687 GLfloat param)
688 {
689 if (samp->Attrib.MinLod == param)
690 return GL_FALSE;
691
692 flush(ctx);
693 samp->Attrib.MinLod = param;
694 samp->Attrib.state.min_lod = MAX2(param, 0.0f); /* only positive */
695
696 return GL_TRUE;
697 }
698
699
700 static GLuint
set_sampler_max_lod(struct gl_context * ctx,struct gl_sampler_object * samp,GLfloat param)701 set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
702 GLfloat param)
703 {
704 if (samp->Attrib.MaxLod == param)
705 return GL_FALSE;
706
707 flush(ctx);
708 samp->Attrib.MaxLod = param;
709 samp->Attrib.state.max_lod = param;
710 return GL_TRUE;
711 }
712
713
714 static GLuint
set_sampler_compare_mode(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)715 set_sampler_compare_mode(struct gl_context *ctx,
716 struct gl_sampler_object *samp, GLint param)
717 {
718 /* If GL_ARB_shadow is not supported, don't report an error. The
719 * sampler object extension spec isn't clear on this extension interaction.
720 * Silences errors with Wine on older GPUs such as R200.
721 */
722 if (!ctx->Extensions.ARB_shadow)
723 return GL_FALSE;
724
725 if (samp->Attrib.CompareMode == param)
726 return GL_FALSE;
727
728 if (param == GL_NONE ||
729 param == GL_COMPARE_R_TO_TEXTURE_ARB) {
730 flush(ctx);
731 samp->Attrib.CompareMode = param;
732 return GL_TRUE;
733 }
734
735 return INVALID_PARAM;
736 }
737
738
739 static GLuint
set_sampler_compare_func(struct gl_context * ctx,struct gl_sampler_object * samp,GLint param)740 set_sampler_compare_func(struct gl_context *ctx,
741 struct gl_sampler_object *samp, GLint param)
742 {
743 /* If GL_ARB_shadow is not supported, don't report an error. The
744 * sampler object extension spec isn't clear on this extension interaction.
745 * Silences errors with Wine on older GPUs such as R200.
746 */
747 if (!ctx->Extensions.ARB_shadow)
748 return GL_FALSE;
749
750 if (samp->Attrib.CompareFunc == param)
751 return GL_FALSE;
752
753 switch (param) {
754 case GL_LEQUAL:
755 case GL_GEQUAL:
756 case GL_EQUAL:
757 case GL_NOTEQUAL:
758 case GL_LESS:
759 case GL_GREATER:
760 case GL_ALWAYS:
761 case GL_NEVER:
762 flush(ctx);
763 samp->Attrib.CompareFunc = param;
764 samp->Attrib.state.compare_func = func_to_gallium(param);
765 return GL_TRUE;
766 default:
767 return INVALID_PARAM;
768 }
769 }
770
771
772 static GLuint
set_sampler_max_anisotropy(struct gl_context * ctx,struct gl_sampler_object * samp,GLfloat param)773 set_sampler_max_anisotropy(struct gl_context *ctx,
774 struct gl_sampler_object *samp, GLfloat param)
775 {
776 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
777 return INVALID_PNAME;
778
779 if (samp->Attrib.MaxAnisotropy == param)
780 return GL_FALSE;
781
782 if (param < 1.0F)
783 return INVALID_VALUE;
784
785 flush(ctx);
786 /* clamp to max, that's what NVIDIA does */
787 samp->Attrib.MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
788 /* gallium sets 0 for 1 */
789 samp->Attrib.state.max_anisotropy = samp->Attrib.MaxAnisotropy == 1 ?
790 0 : samp->Attrib.MaxAnisotropy;
791 return GL_TRUE;
792 }
793
794
795 static GLuint
set_sampler_cube_map_seamless(struct gl_context * ctx,struct gl_sampler_object * samp,GLboolean param)796 set_sampler_cube_map_seamless(struct gl_context *ctx,
797 struct gl_sampler_object *samp, GLboolean param)
798 {
799 if (!_mesa_is_desktop_gl(ctx)
800 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
801 return INVALID_PNAME;
802
803 if (samp->Attrib.CubeMapSeamless == param)
804 return GL_FALSE;
805
806 if (param != GL_TRUE && param != GL_FALSE)
807 return INVALID_VALUE;
808
809 flush(ctx);
810 samp->Attrib.CubeMapSeamless = param;
811 samp->Attrib.state.seamless_cube_map = param;
812 return GL_TRUE;
813 }
814
815 static GLuint
set_sampler_srgb_decode(struct gl_context * ctx,struct gl_sampler_object * samp,GLenum param)816 set_sampler_srgb_decode(struct gl_context *ctx,
817 struct gl_sampler_object *samp, GLenum param)
818 {
819 if (!ctx->Extensions.EXT_texture_sRGB_decode)
820 return INVALID_PNAME;
821
822 if (samp->Attrib.sRGBDecode == param)
823 return GL_FALSE;
824
825 /* The EXT_texture_sRGB_decode spec says:
826 *
827 * "INVALID_ENUM is generated if the <pname> parameter of
828 * TexParameter[i,f,Ii,Iui][v][EXT],
829 * MultiTexParameter[i,f,Ii,Iui][v]EXT,
830 * TextureParameter[i,f,Ii,Iui][v]EXT, SamplerParameter[i,f,Ii,Iui][v]
831 * is TEXTURE_SRGB_DECODE_EXT when the <param> parameter is not one of
832 * DECODE_EXT or SKIP_DECODE_EXT.
833 *
834 * Returning INVALID_PARAM makes that happen.
835 */
836 if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
837 return INVALID_PARAM;
838
839 flush(ctx);
840 samp->Attrib.sRGBDecode = param;
841 return GL_TRUE;
842 }
843
844 static GLuint
set_sampler_reduction_mode(struct gl_context * ctx,struct gl_sampler_object * samp,GLenum param)845 set_sampler_reduction_mode(struct gl_context *ctx,
846 struct gl_sampler_object *samp, GLenum param)
847 {
848 if (!ctx->Extensions.EXT_texture_filter_minmax &&
849 !_mesa_has_ARB_texture_filter_minmax(ctx))
850 return INVALID_PNAME;
851
852 if (samp->Attrib.ReductionMode == param)
853 return GL_FALSE;
854
855 if (param != GL_WEIGHTED_AVERAGE_EXT && param != GL_MIN && param != GL_MAX)
856 return INVALID_PARAM;
857
858 flush(ctx);
859 samp->Attrib.ReductionMode = param;
860 samp->Attrib.state.reduction_mode = reduction_to_gallium(param);
861 return GL_TRUE;
862 }
863
864 static struct gl_sampler_object *
sampler_parameter_error_check(struct gl_context * ctx,GLuint sampler,bool get,const char * name)865 sampler_parameter_error_check(struct gl_context *ctx, GLuint sampler,
866 bool get, const char *name)
867 {
868 struct gl_sampler_object *sampObj;
869
870 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
871 if (!sampObj) {
872 /* OpenGL 4.5 spec, section "8.2 Sampler Objects", page 176 of the PDF
873 * states:
874 *
875 * "An INVALID_OPERATION error is generated if sampler is not the name
876 * of a sampler object previously returned from a call to
877 * GenSamplers."
878 */
879 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name);
880 return NULL;
881 }
882
883 if (!get && sampObj->HandleAllocated) {
884 /* The ARB_bindless_texture spec says:
885 *
886 * "The error INVALID_OPERATION is generated by SamplerParameter* if
887 * <sampler> identifies a sampler object referenced by one or more
888 * texture handles."
889 */
890 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sampler)", name);
891 return NULL;
892 }
893
894 return sampObj;
895 }
896
897 void GLAPIENTRY
_mesa_SamplerParameteri(GLuint sampler,GLenum pname,GLint param)898 _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
899 {
900 struct gl_sampler_object *sampObj;
901 GLuint res;
902 GET_CURRENT_CONTEXT(ctx);
903
904 sampObj = sampler_parameter_error_check(ctx, sampler, false,
905 "glSamplerParameteri");
906 if (!sampObj)
907 return;
908
909 switch (pname) {
910 case GL_TEXTURE_WRAP_S:
911 res = set_sampler_wrap_s(ctx, sampObj, param);
912 break;
913 case GL_TEXTURE_WRAP_T:
914 res = set_sampler_wrap_t(ctx, sampObj, param);
915 break;
916 case GL_TEXTURE_WRAP_R:
917 res = set_sampler_wrap_r(ctx, sampObj, param);
918 break;
919 case GL_TEXTURE_MIN_FILTER:
920 res = set_sampler_min_filter(ctx, sampObj, param);
921 break;
922 case GL_TEXTURE_MAG_FILTER:
923 res = set_sampler_mag_filter(ctx, sampObj, param);
924 break;
925 case GL_TEXTURE_MIN_LOD:
926 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
927 break;
928 case GL_TEXTURE_MAX_LOD:
929 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
930 break;
931 case GL_TEXTURE_LOD_BIAS:
932 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
933 break;
934 case GL_TEXTURE_COMPARE_MODE:
935 res = set_sampler_compare_mode(ctx, sampObj, param);
936 break;
937 case GL_TEXTURE_COMPARE_FUNC:
938 res = set_sampler_compare_func(ctx, sampObj, param);
939 break;
940 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
941 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
942 break;
943 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
944 res = set_sampler_cube_map_seamless(ctx, sampObj, param);
945 break;
946 case GL_TEXTURE_SRGB_DECODE_EXT:
947 res = set_sampler_srgb_decode(ctx, sampObj, param);
948 break;
949 case GL_TEXTURE_REDUCTION_MODE_EXT:
950 res = set_sampler_reduction_mode(ctx, sampObj, param);
951 break;
952 case GL_TEXTURE_BORDER_COLOR:
953 FALLTHROUGH;
954 default:
955 res = INVALID_PNAME;
956 }
957
958 switch (res) {
959 case GL_FALSE:
960 /* no change */
961 break;
962 case GL_TRUE:
963 /* state change - we do nothing special at this time */
964 break;
965 case INVALID_PNAME:
966 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
967 _mesa_enum_to_string(pname));
968 break;
969 case INVALID_PARAM:
970 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
971 param);
972 break;
973 case INVALID_VALUE:
974 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
975 param);
976 break;
977 default:
978 ;
979 }
980 }
981
982
983 void GLAPIENTRY
_mesa_SamplerParameterf(GLuint sampler,GLenum pname,GLfloat param)984 _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
985 {
986 struct gl_sampler_object *sampObj;
987 GLuint res;
988 GET_CURRENT_CONTEXT(ctx);
989
990 sampObj = sampler_parameter_error_check(ctx, sampler, false,
991 "glSamplerParameterf");
992 if (!sampObj)
993 return;
994
995 switch (pname) {
996 case GL_TEXTURE_WRAP_S:
997 res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
998 break;
999 case GL_TEXTURE_WRAP_T:
1000 res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
1001 break;
1002 case GL_TEXTURE_WRAP_R:
1003 res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
1004 break;
1005 case GL_TEXTURE_MIN_FILTER:
1006 res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
1007 break;
1008 case GL_TEXTURE_MAG_FILTER:
1009 res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
1010 break;
1011 case GL_TEXTURE_MIN_LOD:
1012 res = set_sampler_min_lod(ctx, sampObj, param);
1013 break;
1014 case GL_TEXTURE_MAX_LOD:
1015 res = set_sampler_max_lod(ctx, sampObj, param);
1016 break;
1017 case GL_TEXTURE_LOD_BIAS:
1018 res = set_sampler_lod_bias(ctx, sampObj, param);
1019 break;
1020 case GL_TEXTURE_COMPARE_MODE:
1021 res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
1022 break;
1023 case GL_TEXTURE_COMPARE_FUNC:
1024 res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
1025 break;
1026 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1027 res = set_sampler_max_anisotropy(ctx, sampObj, param);
1028 break;
1029 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1030 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
1031 break;
1032 case GL_TEXTURE_SRGB_DECODE_EXT:
1033 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
1034 break;
1035 case GL_TEXTURE_REDUCTION_MODE_EXT:
1036 res = set_sampler_reduction_mode(ctx, sampObj, (GLenum) param);
1037 break;
1038 case GL_TEXTURE_BORDER_COLOR:
1039 FALLTHROUGH;
1040 default:
1041 res = INVALID_PNAME;
1042 }
1043
1044 switch (res) {
1045 case GL_FALSE:
1046 /* no change */
1047 break;
1048 case GL_TRUE:
1049 /* state change - we do nothing special at this time */
1050 break;
1051 case INVALID_PNAME:
1052 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
1053 _mesa_enum_to_string(pname));
1054 break;
1055 case INVALID_PARAM:
1056 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
1057 param);
1058 break;
1059 case INVALID_VALUE:
1060 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
1061 param);
1062 break;
1063 default:
1064 ;
1065 }
1066 }
1067
1068 void GLAPIENTRY
_mesa_SamplerParameteriv(GLuint sampler,GLenum pname,const GLint * params)1069 _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
1070 {
1071 struct gl_sampler_object *sampObj;
1072 GLuint res;
1073 GET_CURRENT_CONTEXT(ctx);
1074
1075 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1076 "glSamplerParameteriv");
1077 if (!sampObj)
1078 return;
1079
1080 switch (pname) {
1081 case GL_TEXTURE_WRAP_S:
1082 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1083 break;
1084 case GL_TEXTURE_WRAP_T:
1085 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1086 break;
1087 case GL_TEXTURE_WRAP_R:
1088 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1089 break;
1090 case GL_TEXTURE_MIN_FILTER:
1091 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1092 break;
1093 case GL_TEXTURE_MAG_FILTER:
1094 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1095 break;
1096 case GL_TEXTURE_MIN_LOD:
1097 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1098 break;
1099 case GL_TEXTURE_MAX_LOD:
1100 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1101 break;
1102 case GL_TEXTURE_LOD_BIAS:
1103 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1104 break;
1105 case GL_TEXTURE_COMPARE_MODE:
1106 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1107 break;
1108 case GL_TEXTURE_COMPARE_FUNC:
1109 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1110 break;
1111 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1112 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1113 break;
1114 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1115 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1116 break;
1117 case GL_TEXTURE_SRGB_DECODE_EXT:
1118 res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
1119 break;
1120 case GL_TEXTURE_REDUCTION_MODE_EXT:
1121 res = set_sampler_reduction_mode(ctx, sampObj, params[0]);
1122 break;
1123 case GL_TEXTURE_BORDER_COLOR:
1124 {
1125 GLfloat c[4];
1126 c[0] = INT_TO_FLOAT(params[0]);
1127 c[1] = INT_TO_FLOAT(params[1]);
1128 c[2] = INT_TO_FLOAT(params[2]);
1129 c[3] = INT_TO_FLOAT(params[3]);
1130 res = set_sampler_border_colorf(ctx, sampObj, c);
1131 }
1132 break;
1133 default:
1134 res = INVALID_PNAME;
1135 }
1136
1137 switch (res) {
1138 case GL_FALSE:
1139 /* no change */
1140 break;
1141 case GL_TRUE:
1142 /* state change - we do nothing special at this time */
1143 break;
1144 case INVALID_PNAME:
1145 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
1146 _mesa_enum_to_string(pname));
1147 break;
1148 case INVALID_PARAM:
1149 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
1150 params[0]);
1151 break;
1152 case INVALID_VALUE:
1153 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
1154 params[0]);
1155 break;
1156 default:
1157 ;
1158 }
1159 }
1160
1161 void GLAPIENTRY
_mesa_SamplerParameterfv(GLuint sampler,GLenum pname,const GLfloat * params)1162 _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
1163 {
1164 struct gl_sampler_object *sampObj;
1165 GLuint res;
1166 GET_CURRENT_CONTEXT(ctx);
1167
1168 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1169 "glSamplerParameterfv");
1170 if (!sampObj)
1171 return;
1172
1173 switch (pname) {
1174 case GL_TEXTURE_WRAP_S:
1175 res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
1176 break;
1177 case GL_TEXTURE_WRAP_T:
1178 res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
1179 break;
1180 case GL_TEXTURE_WRAP_R:
1181 res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
1182 break;
1183 case GL_TEXTURE_MIN_FILTER:
1184 res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
1185 break;
1186 case GL_TEXTURE_MAG_FILTER:
1187 res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
1188 break;
1189 case GL_TEXTURE_MIN_LOD:
1190 res = set_sampler_min_lod(ctx, sampObj, params[0]);
1191 break;
1192 case GL_TEXTURE_MAX_LOD:
1193 res = set_sampler_max_lod(ctx, sampObj, params[0]);
1194 break;
1195 case GL_TEXTURE_LOD_BIAS:
1196 res = set_sampler_lod_bias(ctx, sampObj, params[0]);
1197 break;
1198 case GL_TEXTURE_COMPARE_MODE:
1199 res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
1200 break;
1201 case GL_TEXTURE_COMPARE_FUNC:
1202 res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
1203 break;
1204 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1205 res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
1206 break;
1207 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1208 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
1209 break;
1210 case GL_TEXTURE_SRGB_DECODE_EXT:
1211 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1212 break;
1213 case GL_TEXTURE_REDUCTION_MODE_EXT:
1214 res = set_sampler_reduction_mode(ctx, sampObj, (GLenum) params[0]);
1215 break;
1216 case GL_TEXTURE_BORDER_COLOR:
1217 res = set_sampler_border_colorf(ctx, sampObj, params);
1218 break;
1219 default:
1220 res = INVALID_PNAME;
1221 }
1222
1223 switch (res) {
1224 case GL_FALSE:
1225 /* no change */
1226 break;
1227 case GL_TRUE:
1228 /* state change - we do nothing special at this time */
1229 break;
1230 case INVALID_PNAME:
1231 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
1232 _mesa_enum_to_string(pname));
1233 break;
1234 case INVALID_PARAM:
1235 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
1236 params[0]);
1237 break;
1238 case INVALID_VALUE:
1239 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
1240 params[0]);
1241 break;
1242 default:
1243 ;
1244 }
1245 }
1246
1247 void GLAPIENTRY
_mesa_SamplerParameterIiv(GLuint sampler,GLenum pname,const GLint * params)1248 _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
1249 {
1250 struct gl_sampler_object *sampObj;
1251 GLuint res;
1252 GET_CURRENT_CONTEXT(ctx);
1253
1254 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1255 "glSamplerParameterIiv");
1256 if (!sampObj)
1257 return;
1258
1259 switch (pname) {
1260 case GL_TEXTURE_WRAP_S:
1261 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1262 break;
1263 case GL_TEXTURE_WRAP_T:
1264 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1265 break;
1266 case GL_TEXTURE_WRAP_R:
1267 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1268 break;
1269 case GL_TEXTURE_MIN_FILTER:
1270 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1271 break;
1272 case GL_TEXTURE_MAG_FILTER:
1273 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1274 break;
1275 case GL_TEXTURE_MIN_LOD:
1276 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1277 break;
1278 case GL_TEXTURE_MAX_LOD:
1279 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1280 break;
1281 case GL_TEXTURE_LOD_BIAS:
1282 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1283 break;
1284 case GL_TEXTURE_COMPARE_MODE:
1285 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1286 break;
1287 case GL_TEXTURE_COMPARE_FUNC:
1288 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1289 break;
1290 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1291 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1292 break;
1293 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1294 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1295 break;
1296 case GL_TEXTURE_SRGB_DECODE_EXT:
1297 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1298 break;
1299 case GL_TEXTURE_REDUCTION_MODE_EXT:
1300 res = set_sampler_reduction_mode(ctx, sampObj, (GLenum) params[0]);
1301 break;
1302 case GL_TEXTURE_BORDER_COLOR:
1303 res = set_sampler_border_colori(ctx, sampObj, params);
1304 break;
1305 default:
1306 res = INVALID_PNAME;
1307 }
1308
1309 switch (res) {
1310 case GL_FALSE:
1311 /* no change */
1312 break;
1313 case GL_TRUE:
1314 /* state change - we do nothing special at this time */
1315 break;
1316 case INVALID_PNAME:
1317 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1318 _mesa_enum_to_string(pname));
1319 break;
1320 case INVALID_PARAM:
1321 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1322 params[0]);
1323 break;
1324 case INVALID_VALUE:
1325 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1326 params[0]);
1327 break;
1328 default:
1329 ;
1330 }
1331 }
1332
1333
1334 void GLAPIENTRY
_mesa_SamplerParameterIuiv(GLuint sampler,GLenum pname,const GLuint * params)1335 _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1336 {
1337 struct gl_sampler_object *sampObj;
1338 GLuint res;
1339 GET_CURRENT_CONTEXT(ctx);
1340
1341 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1342 "glSamplerParameterIuiv");
1343 if (!sampObj)
1344 return;
1345
1346 switch (pname) {
1347 case GL_TEXTURE_WRAP_S:
1348 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1349 break;
1350 case GL_TEXTURE_WRAP_T:
1351 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1352 break;
1353 case GL_TEXTURE_WRAP_R:
1354 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1355 break;
1356 case GL_TEXTURE_MIN_FILTER:
1357 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1358 break;
1359 case GL_TEXTURE_MAG_FILTER:
1360 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1361 break;
1362 case GL_TEXTURE_MIN_LOD:
1363 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1364 break;
1365 case GL_TEXTURE_MAX_LOD:
1366 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1367 break;
1368 case GL_TEXTURE_LOD_BIAS:
1369 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1370 break;
1371 case GL_TEXTURE_COMPARE_MODE:
1372 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1373 break;
1374 case GL_TEXTURE_COMPARE_FUNC:
1375 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1376 break;
1377 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1378 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1379 break;
1380 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1381 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1382 break;
1383 case GL_TEXTURE_SRGB_DECODE_EXT:
1384 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1385 break;
1386 case GL_TEXTURE_REDUCTION_MODE_EXT:
1387 res = set_sampler_reduction_mode(ctx, sampObj, (GLenum) params[0]);
1388 break;
1389 case GL_TEXTURE_BORDER_COLOR:
1390 res = set_sampler_border_colorui(ctx, sampObj, params);
1391 break;
1392 default:
1393 res = INVALID_PNAME;
1394 }
1395
1396 switch (res) {
1397 case GL_FALSE:
1398 /* no change */
1399 break;
1400 case GL_TRUE:
1401 /* state change - we do nothing special at this time */
1402 break;
1403 case INVALID_PNAME:
1404 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1405 _mesa_enum_to_string(pname));
1406 break;
1407 case INVALID_PARAM:
1408 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1409 params[0]);
1410 break;
1411 case INVALID_VALUE:
1412 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1413 params[0]);
1414 break;
1415 default:
1416 ;
1417 }
1418 }
1419
1420
1421 void GLAPIENTRY
_mesa_GetSamplerParameteriv(GLuint sampler,GLenum pname,GLint * params)1422 _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1423 {
1424 struct gl_sampler_object *sampObj;
1425 GET_CURRENT_CONTEXT(ctx);
1426
1427 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1428 "glGetSamplerParameteriv");
1429 if (!sampObj)
1430 return;
1431
1432 switch (pname) {
1433 case GL_TEXTURE_WRAP_S:
1434 *params = sampObj->Attrib.WrapS;
1435 break;
1436 case GL_TEXTURE_WRAP_T:
1437 *params = sampObj->Attrib.WrapT;
1438 break;
1439 case GL_TEXTURE_WRAP_R:
1440 *params = sampObj->Attrib.WrapR;
1441 break;
1442 case GL_TEXTURE_MIN_FILTER:
1443 *params = sampObj->Attrib.MinFilter;
1444 break;
1445 case GL_TEXTURE_MAG_FILTER:
1446 *params = sampObj->Attrib.MagFilter;
1447 break;
1448 case GL_TEXTURE_MIN_LOD:
1449 /* GL spec 'Data Conversions' section specifies that floating-point
1450 * value in integer Get function is rounded to nearest integer
1451 */
1452 *params = lroundf(sampObj->Attrib.MinLod);
1453 break;
1454 case GL_TEXTURE_MAX_LOD:
1455 /* GL spec 'Data Conversions' section specifies that floating-point
1456 * value in integer Get function is rounded to nearest integer
1457 */
1458 *params = lroundf(sampObj->Attrib.MaxLod);
1459 break;
1460 case GL_TEXTURE_LOD_BIAS:
1461 /* GL spec 'Data Conversions' section specifies that floating-point
1462 * value in integer Get function is rounded to nearest integer
1463 */
1464 *params = lroundf(sampObj->Attrib.LodBias);
1465 break;
1466 case GL_TEXTURE_COMPARE_MODE:
1467 if (!ctx->Extensions.ARB_shadow)
1468 goto invalid_pname;
1469 *params = sampObj->Attrib.CompareMode;
1470 break;
1471 case GL_TEXTURE_COMPARE_FUNC:
1472 if (!ctx->Extensions.ARB_shadow)
1473 goto invalid_pname;
1474 *params = sampObj->Attrib.CompareFunc;
1475 break;
1476 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1477 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1478 goto invalid_pname;
1479 /* GL spec 'Data Conversions' section specifies that floating-point
1480 * value in integer Get function is rounded to nearest integer
1481 */
1482 *params = lroundf(sampObj->Attrib.MaxAnisotropy);
1483 break;
1484 case GL_TEXTURE_BORDER_COLOR:
1485 params[0] = FLOAT_TO_INT(sampObj->Attrib.state.border_color.f[0]);
1486 params[1] = FLOAT_TO_INT(sampObj->Attrib.state.border_color.f[1]);
1487 params[2] = FLOAT_TO_INT(sampObj->Attrib.state.border_color.f[2]);
1488 params[3] = FLOAT_TO_INT(sampObj->Attrib.state.border_color.f[3]);
1489 break;
1490 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1491 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1492 goto invalid_pname;
1493 *params = sampObj->Attrib.CubeMapSeamless;
1494 break;
1495 case GL_TEXTURE_SRGB_DECODE_EXT:
1496 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1497 goto invalid_pname;
1498 *params = (GLenum) sampObj->Attrib.sRGBDecode;
1499 break;
1500 case GL_TEXTURE_REDUCTION_MODE_EXT:
1501 if (!ctx->Extensions.EXT_texture_filter_minmax &&
1502 !_mesa_has_ARB_texture_filter_minmax(ctx))
1503 goto invalid_pname;
1504 *params = (GLenum) sampObj->Attrib.ReductionMode;
1505 break;
1506 default:
1507 goto invalid_pname;
1508 }
1509 return;
1510
1511 invalid_pname:
1512 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1513 _mesa_enum_to_string(pname));
1514 }
1515
1516
1517 void GLAPIENTRY
_mesa_GetSamplerParameterfv(GLuint sampler,GLenum pname,GLfloat * params)1518 _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1519 {
1520 struct gl_sampler_object *sampObj;
1521 GET_CURRENT_CONTEXT(ctx);
1522
1523 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1524 "glGetSamplerParameterfv");
1525 if (!sampObj)
1526 return;
1527
1528 switch (pname) {
1529 case GL_TEXTURE_WRAP_S:
1530 *params = (GLfloat) sampObj->Attrib.WrapS;
1531 break;
1532 case GL_TEXTURE_WRAP_T:
1533 *params = (GLfloat) sampObj->Attrib.WrapT;
1534 break;
1535 case GL_TEXTURE_WRAP_R:
1536 *params = (GLfloat) sampObj->Attrib.WrapR;
1537 break;
1538 case GL_TEXTURE_MIN_FILTER:
1539 *params = (GLfloat) sampObj->Attrib.MinFilter;
1540 break;
1541 case GL_TEXTURE_MAG_FILTER:
1542 *params = (GLfloat) sampObj->Attrib.MagFilter;
1543 break;
1544 case GL_TEXTURE_MIN_LOD:
1545 *params = sampObj->Attrib.MinLod;
1546 break;
1547 case GL_TEXTURE_MAX_LOD:
1548 *params = sampObj->Attrib.MaxLod;
1549 break;
1550 case GL_TEXTURE_LOD_BIAS:
1551 *params = sampObj->Attrib.LodBias;
1552 break;
1553 case GL_TEXTURE_COMPARE_MODE:
1554 *params = (GLfloat) sampObj->Attrib.CompareMode;
1555 break;
1556 case GL_TEXTURE_COMPARE_FUNC:
1557 *params = (GLfloat) sampObj->Attrib.CompareFunc;
1558 break;
1559 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1560 *params = sampObj->Attrib.MaxAnisotropy;
1561 break;
1562 case GL_TEXTURE_BORDER_COLOR:
1563 params[0] = sampObj->Attrib.state.border_color.f[0];
1564 params[1] = sampObj->Attrib.state.border_color.f[1];
1565 params[2] = sampObj->Attrib.state.border_color.f[2];
1566 params[3] = sampObj->Attrib.state.border_color.f[3];
1567 break;
1568 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1569 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1570 goto invalid_pname;
1571 *params = (GLfloat) sampObj->Attrib.CubeMapSeamless;
1572 break;
1573 case GL_TEXTURE_SRGB_DECODE_EXT:
1574 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1575 goto invalid_pname;
1576 *params = (GLfloat) sampObj->Attrib.sRGBDecode;
1577 break;
1578 case GL_TEXTURE_REDUCTION_MODE_EXT:
1579 if (!ctx->Extensions.EXT_texture_filter_minmax &&
1580 !_mesa_has_ARB_texture_filter_minmax(ctx))
1581 goto invalid_pname;
1582 *params = (GLfloat) sampObj->Attrib.ReductionMode;
1583 break;
1584 default:
1585 goto invalid_pname;
1586 }
1587 return;
1588
1589 invalid_pname:
1590 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1591 _mesa_enum_to_string(pname));
1592 }
1593
1594
1595 void GLAPIENTRY
_mesa_GetSamplerParameterIiv(GLuint sampler,GLenum pname,GLint * params)1596 _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1597 {
1598 struct gl_sampler_object *sampObj;
1599 GET_CURRENT_CONTEXT(ctx);
1600
1601 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1602 "glGetSamplerParameterIiv");
1603 if (!sampObj)
1604 return;
1605
1606 switch (pname) {
1607 case GL_TEXTURE_WRAP_S:
1608 *params = sampObj->Attrib.WrapS;
1609 break;
1610 case GL_TEXTURE_WRAP_T:
1611 *params = sampObj->Attrib.WrapT;
1612 break;
1613 case GL_TEXTURE_WRAP_R:
1614 *params = sampObj->Attrib.WrapR;
1615 break;
1616 case GL_TEXTURE_MIN_FILTER:
1617 *params = sampObj->Attrib.MinFilter;
1618 break;
1619 case GL_TEXTURE_MAG_FILTER:
1620 *params = sampObj->Attrib.MagFilter;
1621 break;
1622 case GL_TEXTURE_MIN_LOD:
1623 *params = (GLint) sampObj->Attrib.MinLod;
1624 break;
1625 case GL_TEXTURE_MAX_LOD:
1626 *params = (GLint) sampObj->Attrib.MaxLod;
1627 break;
1628 case GL_TEXTURE_LOD_BIAS:
1629 *params = (GLint) sampObj->Attrib.LodBias;
1630 break;
1631 case GL_TEXTURE_COMPARE_MODE:
1632 *params = sampObj->Attrib.CompareMode;
1633 break;
1634 case GL_TEXTURE_COMPARE_FUNC:
1635 *params = sampObj->Attrib.CompareFunc;
1636 break;
1637 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1638 *params = (GLint) sampObj->Attrib.MaxAnisotropy;
1639 break;
1640 case GL_TEXTURE_BORDER_COLOR:
1641 params[0] = sampObj->Attrib.state.border_color.i[0];
1642 params[1] = sampObj->Attrib.state.border_color.i[1];
1643 params[2] = sampObj->Attrib.state.border_color.i[2];
1644 params[3] = sampObj->Attrib.state.border_color.i[3];
1645 break;
1646 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1647 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1648 goto invalid_pname;
1649 *params = sampObj->Attrib.CubeMapSeamless;
1650 break;
1651 case GL_TEXTURE_SRGB_DECODE_EXT:
1652 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1653 goto invalid_pname;
1654 *params = (GLenum) sampObj->Attrib.sRGBDecode;
1655 break;
1656 case GL_TEXTURE_REDUCTION_MODE_EXT:
1657 if (!ctx->Extensions.EXT_texture_filter_minmax &&
1658 !_mesa_has_ARB_texture_filter_minmax(ctx))
1659 goto invalid_pname;
1660 *params = (GLenum) sampObj->Attrib.ReductionMode;
1661 break;
1662 default:
1663 goto invalid_pname;
1664 }
1665 return;
1666
1667 invalid_pname:
1668 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1669 _mesa_enum_to_string(pname));
1670 }
1671
1672
1673 void GLAPIENTRY
_mesa_GetSamplerParameterIuiv(GLuint sampler,GLenum pname,GLuint * params)1674 _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1675 {
1676 struct gl_sampler_object *sampObj;
1677 GET_CURRENT_CONTEXT(ctx);
1678
1679 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1680 "glGetSamplerParameterIuiv");
1681 if (!sampObj)
1682 return;
1683
1684 switch (pname) {
1685 case GL_TEXTURE_WRAP_S:
1686 *params = sampObj->Attrib.WrapS;
1687 break;
1688 case GL_TEXTURE_WRAP_T:
1689 *params = sampObj->Attrib.WrapT;
1690 break;
1691 case GL_TEXTURE_WRAP_R:
1692 *params = sampObj->Attrib.WrapR;
1693 break;
1694 case GL_TEXTURE_MIN_FILTER:
1695 *params = sampObj->Attrib.MinFilter;
1696 break;
1697 case GL_TEXTURE_MAG_FILTER:
1698 *params = sampObj->Attrib.MagFilter;
1699 break;
1700 case GL_TEXTURE_MIN_LOD:
1701 *params = (GLuint) sampObj->Attrib.MinLod;
1702 break;
1703 case GL_TEXTURE_MAX_LOD:
1704 *params = (GLuint) sampObj->Attrib.MaxLod;
1705 break;
1706 case GL_TEXTURE_LOD_BIAS:
1707 *params = (GLuint) sampObj->Attrib.LodBias;
1708 break;
1709 case GL_TEXTURE_COMPARE_MODE:
1710 *params = sampObj->Attrib.CompareMode;
1711 break;
1712 case GL_TEXTURE_COMPARE_FUNC:
1713 *params = sampObj->Attrib.CompareFunc;
1714 break;
1715 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1716 *params = (GLuint) sampObj->Attrib.MaxAnisotropy;
1717 break;
1718 case GL_TEXTURE_BORDER_COLOR:
1719 params[0] = sampObj->Attrib.state.border_color.ui[0];
1720 params[1] = sampObj->Attrib.state.border_color.ui[1];
1721 params[2] = sampObj->Attrib.state.border_color.ui[2];
1722 params[3] = sampObj->Attrib.state.border_color.ui[3];
1723 break;
1724 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1725 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1726 goto invalid_pname;
1727 *params = sampObj->Attrib.CubeMapSeamless;
1728 break;
1729 case GL_TEXTURE_SRGB_DECODE_EXT:
1730 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1731 goto invalid_pname;
1732 *params = (GLenum) sampObj->Attrib.sRGBDecode;
1733 break;
1734 case GL_TEXTURE_REDUCTION_MODE_EXT:
1735 if (!ctx->Extensions.EXT_texture_filter_minmax &&
1736 !_mesa_has_ARB_texture_filter_minmax(ctx))
1737 goto invalid_pname;
1738 *params = (GLenum) sampObj->Attrib.ReductionMode;
1739 break;
1740 default:
1741 goto invalid_pname;
1742 }
1743 return;
1744
1745 invalid_pname:
1746 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1747 _mesa_enum_to_string(pname));
1748 }
1749