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