mesa: add KHR_no_error support for gl*Samplers()
[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 if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
784 return INVALID_VALUE;
785
786 flush(ctx);
787 samp->sRGBDecode = param;
788 return GL_TRUE;
789 }
790
791 static struct gl_sampler_object *
792 sampler_parameter_error_check(struct gl_context *ctx, GLuint sampler,
793 bool get, const char *name)
794 {
795 struct gl_sampler_object *sampObj;
796
797 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
798 if (!sampObj) {
799 /* OpenGL 4.5 spec, section "8.2 Sampler Objects", page 176 of the PDF
800 * states:
801 *
802 * "An INVALID_OPERATION error is generated if sampler is not the name
803 * of a sampler object previously returned from a call to
804 * GenSamplers."
805 */
806 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name);
807 return NULL;
808 }
809
810 if (!get && sampObj->HandleAllocated) {
811 /* The ARB_bindless_texture spec says:
812 *
813 * "The error INVALID_OPERATION is generated by SamplerParameter* if
814 * <sampler> identifies a sampler object referenced by one or more
815 * texture handles."
816 */
817 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sampler)", name);
818 return NULL;
819 }
820
821 return sampObj;
822 }
823
824 void GLAPIENTRY
825 _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
826 {
827 struct gl_sampler_object *sampObj;
828 GLuint res;
829 GET_CURRENT_CONTEXT(ctx);
830
831 sampObj = sampler_parameter_error_check(ctx, sampler, false,
832 "glSamplerParameteri");
833 if (!sampObj)
834 return;
835
836 switch (pname) {
837 case GL_TEXTURE_WRAP_S:
838 res = set_sampler_wrap_s(ctx, sampObj, param);
839 break;
840 case GL_TEXTURE_WRAP_T:
841 res = set_sampler_wrap_t(ctx, sampObj, param);
842 break;
843 case GL_TEXTURE_WRAP_R:
844 res = set_sampler_wrap_r(ctx, sampObj, param);
845 break;
846 case GL_TEXTURE_MIN_FILTER:
847 res = set_sampler_min_filter(ctx, sampObj, param);
848 break;
849 case GL_TEXTURE_MAG_FILTER:
850 res = set_sampler_mag_filter(ctx, sampObj, param);
851 break;
852 case GL_TEXTURE_MIN_LOD:
853 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
854 break;
855 case GL_TEXTURE_MAX_LOD:
856 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
857 break;
858 case GL_TEXTURE_LOD_BIAS:
859 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
860 break;
861 case GL_TEXTURE_COMPARE_MODE:
862 res = set_sampler_compare_mode(ctx, sampObj, param);
863 break;
864 case GL_TEXTURE_COMPARE_FUNC:
865 res = set_sampler_compare_func(ctx, sampObj, param);
866 break;
867 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
868 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
869 break;
870 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
871 res = set_sampler_cube_map_seamless(ctx, sampObj, param);
872 break;
873 case GL_TEXTURE_SRGB_DECODE_EXT:
874 res = set_sampler_srgb_decode(ctx, sampObj, param);
875 break;
876 case GL_TEXTURE_BORDER_COLOR:
877 /* fall-through */
878 default:
879 res = INVALID_PNAME;
880 }
881
882 switch (res) {
883 case GL_FALSE:
884 /* no change */
885 break;
886 case GL_TRUE:
887 /* state change - we do nothing special at this time */
888 break;
889 case INVALID_PNAME:
890 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
891 _mesa_enum_to_string(pname));
892 break;
893 case INVALID_PARAM:
894 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
895 param);
896 break;
897 case INVALID_VALUE:
898 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
899 param);
900 break;
901 default:
902 ;
903 }
904 }
905
906
907 void GLAPIENTRY
908 _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
909 {
910 struct gl_sampler_object *sampObj;
911 GLuint res;
912 GET_CURRENT_CONTEXT(ctx);
913
914 sampObj = sampler_parameter_error_check(ctx, sampler, false,
915 "glSamplerParameterf");
916 if (!sampObj)
917 return;
918
919 switch (pname) {
920 case GL_TEXTURE_WRAP_S:
921 res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
922 break;
923 case GL_TEXTURE_WRAP_T:
924 res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
925 break;
926 case GL_TEXTURE_WRAP_R:
927 res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
928 break;
929 case GL_TEXTURE_MIN_FILTER:
930 res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
931 break;
932 case GL_TEXTURE_MAG_FILTER:
933 res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
934 break;
935 case GL_TEXTURE_MIN_LOD:
936 res = set_sampler_min_lod(ctx, sampObj, param);
937 break;
938 case GL_TEXTURE_MAX_LOD:
939 res = set_sampler_max_lod(ctx, sampObj, param);
940 break;
941 case GL_TEXTURE_LOD_BIAS:
942 res = set_sampler_lod_bias(ctx, sampObj, param);
943 break;
944 case GL_TEXTURE_COMPARE_MODE:
945 res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
946 break;
947 case GL_TEXTURE_COMPARE_FUNC:
948 res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
949 break;
950 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
951 res = set_sampler_max_anisotropy(ctx, sampObj, param);
952 break;
953 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
954 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
955 break;
956 case GL_TEXTURE_SRGB_DECODE_EXT:
957 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
958 break;
959 case GL_TEXTURE_BORDER_COLOR:
960 /* fall-through */
961 default:
962 res = INVALID_PNAME;
963 }
964
965 switch (res) {
966 case GL_FALSE:
967 /* no change */
968 break;
969 case GL_TRUE:
970 /* state change - we do nothing special at this time */
971 break;
972 case INVALID_PNAME:
973 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
974 _mesa_enum_to_string(pname));
975 break;
976 case INVALID_PARAM:
977 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
978 param);
979 break;
980 case INVALID_VALUE:
981 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
982 param);
983 break;
984 default:
985 ;
986 }
987 }
988
989 void GLAPIENTRY
990 _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
991 {
992 struct gl_sampler_object *sampObj;
993 GLuint res;
994 GET_CURRENT_CONTEXT(ctx);
995
996 sampObj = sampler_parameter_error_check(ctx, sampler, false,
997 "glSamplerParameteriv");
998 if (!sampObj)
999 return;
1000
1001 switch (pname) {
1002 case GL_TEXTURE_WRAP_S:
1003 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1004 break;
1005 case GL_TEXTURE_WRAP_T:
1006 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1007 break;
1008 case GL_TEXTURE_WRAP_R:
1009 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1010 break;
1011 case GL_TEXTURE_MIN_FILTER:
1012 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1013 break;
1014 case GL_TEXTURE_MAG_FILTER:
1015 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1016 break;
1017 case GL_TEXTURE_MIN_LOD:
1018 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1019 break;
1020 case GL_TEXTURE_MAX_LOD:
1021 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1022 break;
1023 case GL_TEXTURE_LOD_BIAS:
1024 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1025 break;
1026 case GL_TEXTURE_COMPARE_MODE:
1027 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1028 break;
1029 case GL_TEXTURE_COMPARE_FUNC:
1030 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1031 break;
1032 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1033 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1034 break;
1035 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1036 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1037 break;
1038 case GL_TEXTURE_SRGB_DECODE_EXT:
1039 res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
1040 break;
1041 case GL_TEXTURE_BORDER_COLOR:
1042 {
1043 GLfloat c[4];
1044 c[0] = INT_TO_FLOAT(params[0]);
1045 c[1] = INT_TO_FLOAT(params[1]);
1046 c[2] = INT_TO_FLOAT(params[2]);
1047 c[3] = INT_TO_FLOAT(params[3]);
1048 res = set_sampler_border_colorf(ctx, sampObj, c);
1049 }
1050 break;
1051 default:
1052 res = INVALID_PNAME;
1053 }
1054
1055 switch (res) {
1056 case GL_FALSE:
1057 /* no change */
1058 break;
1059 case GL_TRUE:
1060 /* state change - we do nothing special at this time */
1061 break;
1062 case INVALID_PNAME:
1063 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
1064 _mesa_enum_to_string(pname));
1065 break;
1066 case INVALID_PARAM:
1067 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
1068 params[0]);
1069 break;
1070 case INVALID_VALUE:
1071 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
1072 params[0]);
1073 break;
1074 default:
1075 ;
1076 }
1077 }
1078
1079 void GLAPIENTRY
1080 _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
1081 {
1082 struct gl_sampler_object *sampObj;
1083 GLuint res;
1084 GET_CURRENT_CONTEXT(ctx);
1085
1086 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1087 "glSamplerParameterfv");
1088 if (!sampObj)
1089 return;
1090
1091 switch (pname) {
1092 case GL_TEXTURE_WRAP_S:
1093 res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
1094 break;
1095 case GL_TEXTURE_WRAP_T:
1096 res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
1097 break;
1098 case GL_TEXTURE_WRAP_R:
1099 res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
1100 break;
1101 case GL_TEXTURE_MIN_FILTER:
1102 res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
1103 break;
1104 case GL_TEXTURE_MAG_FILTER:
1105 res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
1106 break;
1107 case GL_TEXTURE_MIN_LOD:
1108 res = set_sampler_min_lod(ctx, sampObj, params[0]);
1109 break;
1110 case GL_TEXTURE_MAX_LOD:
1111 res = set_sampler_max_lod(ctx, sampObj, params[0]);
1112 break;
1113 case GL_TEXTURE_LOD_BIAS:
1114 res = set_sampler_lod_bias(ctx, sampObj, params[0]);
1115 break;
1116 case GL_TEXTURE_COMPARE_MODE:
1117 res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
1118 break;
1119 case GL_TEXTURE_COMPARE_FUNC:
1120 res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
1121 break;
1122 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1123 res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
1124 break;
1125 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1126 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
1127 break;
1128 case GL_TEXTURE_SRGB_DECODE_EXT:
1129 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1130 break;
1131 case GL_TEXTURE_BORDER_COLOR:
1132 res = set_sampler_border_colorf(ctx, sampObj, params);
1133 break;
1134 default:
1135 res = INVALID_PNAME;
1136 }
1137
1138 switch (res) {
1139 case GL_FALSE:
1140 /* no change */
1141 break;
1142 case GL_TRUE:
1143 /* state change - we do nothing special at this time */
1144 break;
1145 case INVALID_PNAME:
1146 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
1147 _mesa_enum_to_string(pname));
1148 break;
1149 case INVALID_PARAM:
1150 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
1151 params[0]);
1152 break;
1153 case INVALID_VALUE:
1154 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
1155 params[0]);
1156 break;
1157 default:
1158 ;
1159 }
1160 }
1161
1162 void GLAPIENTRY
1163 _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
1164 {
1165 struct gl_sampler_object *sampObj;
1166 GLuint res;
1167 GET_CURRENT_CONTEXT(ctx);
1168
1169 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1170 "glSamplerParameterIiv");
1171 if (!sampObj)
1172 return;
1173
1174 switch (pname) {
1175 case GL_TEXTURE_WRAP_S:
1176 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1177 break;
1178 case GL_TEXTURE_WRAP_T:
1179 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1180 break;
1181 case GL_TEXTURE_WRAP_R:
1182 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1183 break;
1184 case GL_TEXTURE_MIN_FILTER:
1185 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1186 break;
1187 case GL_TEXTURE_MAG_FILTER:
1188 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1189 break;
1190 case GL_TEXTURE_MIN_LOD:
1191 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1192 break;
1193 case GL_TEXTURE_MAX_LOD:
1194 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1195 break;
1196 case GL_TEXTURE_LOD_BIAS:
1197 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1198 break;
1199 case GL_TEXTURE_COMPARE_MODE:
1200 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1201 break;
1202 case GL_TEXTURE_COMPARE_FUNC:
1203 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1204 break;
1205 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1206 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1207 break;
1208 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1209 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1210 break;
1211 case GL_TEXTURE_SRGB_DECODE_EXT:
1212 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1213 break;
1214 case GL_TEXTURE_BORDER_COLOR:
1215 res = set_sampler_border_colori(ctx, sampObj, params);
1216 break;
1217 default:
1218 res = INVALID_PNAME;
1219 }
1220
1221 switch (res) {
1222 case GL_FALSE:
1223 /* no change */
1224 break;
1225 case GL_TRUE:
1226 /* state change - we do nothing special at this time */
1227 break;
1228 case INVALID_PNAME:
1229 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1230 _mesa_enum_to_string(pname));
1231 break;
1232 case INVALID_PARAM:
1233 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1234 params[0]);
1235 break;
1236 case INVALID_VALUE:
1237 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1238 params[0]);
1239 break;
1240 default:
1241 ;
1242 }
1243 }
1244
1245
1246 void GLAPIENTRY
1247 _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1248 {
1249 struct gl_sampler_object *sampObj;
1250 GLuint res;
1251 GET_CURRENT_CONTEXT(ctx);
1252
1253 sampObj = sampler_parameter_error_check(ctx, sampler, false,
1254 "glSamplerParameterIuiv");
1255 if (!sampObj)
1256 return;
1257
1258 switch (pname) {
1259 case GL_TEXTURE_WRAP_S:
1260 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1261 break;
1262 case GL_TEXTURE_WRAP_T:
1263 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1264 break;
1265 case GL_TEXTURE_WRAP_R:
1266 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1267 break;
1268 case GL_TEXTURE_MIN_FILTER:
1269 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1270 break;
1271 case GL_TEXTURE_MAG_FILTER:
1272 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1273 break;
1274 case GL_TEXTURE_MIN_LOD:
1275 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1276 break;
1277 case GL_TEXTURE_MAX_LOD:
1278 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1279 break;
1280 case GL_TEXTURE_LOD_BIAS:
1281 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1282 break;
1283 case GL_TEXTURE_COMPARE_MODE:
1284 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1285 break;
1286 case GL_TEXTURE_COMPARE_FUNC:
1287 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1288 break;
1289 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1290 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1291 break;
1292 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1293 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1294 break;
1295 case GL_TEXTURE_SRGB_DECODE_EXT:
1296 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1297 break;
1298 case GL_TEXTURE_BORDER_COLOR:
1299 res = set_sampler_border_colorui(ctx, sampObj, params);
1300 break;
1301 default:
1302 res = INVALID_PNAME;
1303 }
1304
1305 switch (res) {
1306 case GL_FALSE:
1307 /* no change */
1308 break;
1309 case GL_TRUE:
1310 /* state change - we do nothing special at this time */
1311 break;
1312 case INVALID_PNAME:
1313 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1314 _mesa_enum_to_string(pname));
1315 break;
1316 case INVALID_PARAM:
1317 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1318 params[0]);
1319 break;
1320 case INVALID_VALUE:
1321 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1322 params[0]);
1323 break;
1324 default:
1325 ;
1326 }
1327 }
1328
1329
1330 void GLAPIENTRY
1331 _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1332 {
1333 struct gl_sampler_object *sampObj;
1334 GET_CURRENT_CONTEXT(ctx);
1335
1336 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1337 "glGetSamplerParameteriv");
1338 if (!sampObj)
1339 return;
1340
1341 switch (pname) {
1342 case GL_TEXTURE_WRAP_S:
1343 *params = sampObj->WrapS;
1344 break;
1345 case GL_TEXTURE_WRAP_T:
1346 *params = sampObj->WrapT;
1347 break;
1348 case GL_TEXTURE_WRAP_R:
1349 *params = sampObj->WrapR;
1350 break;
1351 case GL_TEXTURE_MIN_FILTER:
1352 *params = sampObj->MinFilter;
1353 break;
1354 case GL_TEXTURE_MAG_FILTER:
1355 *params = sampObj->MagFilter;
1356 break;
1357 case GL_TEXTURE_MIN_LOD:
1358 /* GL spec 'Data Conversions' section specifies that floating-point
1359 * value in integer Get function is rounded to nearest integer
1360 */
1361 *params = IROUND(sampObj->MinLod);
1362 break;
1363 case GL_TEXTURE_MAX_LOD:
1364 /* GL spec 'Data Conversions' section specifies that floating-point
1365 * value in integer Get function is rounded to nearest integer
1366 */
1367 *params = IROUND(sampObj->MaxLod);
1368 break;
1369 case GL_TEXTURE_LOD_BIAS:
1370 /* GL spec 'Data Conversions' section specifies that floating-point
1371 * value in integer Get function is rounded to nearest integer
1372 */
1373 *params = IROUND(sampObj->LodBias);
1374 break;
1375 case GL_TEXTURE_COMPARE_MODE:
1376 *params = sampObj->CompareMode;
1377 break;
1378 case GL_TEXTURE_COMPARE_FUNC:
1379 *params = sampObj->CompareFunc;
1380 break;
1381 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1382 /* GL spec 'Data Conversions' section specifies that floating-point
1383 * value in integer Get function is rounded to nearest integer
1384 */
1385 *params = IROUND(sampObj->MaxAnisotropy);
1386 break;
1387 case GL_TEXTURE_BORDER_COLOR:
1388 params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
1389 params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
1390 params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
1391 params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
1392 break;
1393 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1394 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1395 goto invalid_pname;
1396 *params = sampObj->CubeMapSeamless;
1397 break;
1398 case GL_TEXTURE_SRGB_DECODE_EXT:
1399 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1400 goto invalid_pname;
1401 *params = (GLenum) sampObj->sRGBDecode;
1402 break;
1403 default:
1404 goto invalid_pname;
1405 }
1406 return;
1407
1408 invalid_pname:
1409 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1410 _mesa_enum_to_string(pname));
1411 }
1412
1413
1414 void GLAPIENTRY
1415 _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1416 {
1417 struct gl_sampler_object *sampObj;
1418 GET_CURRENT_CONTEXT(ctx);
1419
1420 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1421 "glGetSamplerParameterfv");
1422 if (!sampObj)
1423 return;
1424
1425 switch (pname) {
1426 case GL_TEXTURE_WRAP_S:
1427 *params = (GLfloat) sampObj->WrapS;
1428 break;
1429 case GL_TEXTURE_WRAP_T:
1430 *params = (GLfloat) sampObj->WrapT;
1431 break;
1432 case GL_TEXTURE_WRAP_R:
1433 *params = (GLfloat) sampObj->WrapR;
1434 break;
1435 case GL_TEXTURE_MIN_FILTER:
1436 *params = (GLfloat) sampObj->MinFilter;
1437 break;
1438 case GL_TEXTURE_MAG_FILTER:
1439 *params = (GLfloat) sampObj->MagFilter;
1440 break;
1441 case GL_TEXTURE_MIN_LOD:
1442 *params = sampObj->MinLod;
1443 break;
1444 case GL_TEXTURE_MAX_LOD:
1445 *params = sampObj->MaxLod;
1446 break;
1447 case GL_TEXTURE_LOD_BIAS:
1448 *params = sampObj->LodBias;
1449 break;
1450 case GL_TEXTURE_COMPARE_MODE:
1451 *params = (GLfloat) sampObj->CompareMode;
1452 break;
1453 case GL_TEXTURE_COMPARE_FUNC:
1454 *params = (GLfloat) sampObj->CompareFunc;
1455 break;
1456 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1457 *params = sampObj->MaxAnisotropy;
1458 break;
1459 case GL_TEXTURE_BORDER_COLOR:
1460 params[0] = sampObj->BorderColor.f[0];
1461 params[1] = sampObj->BorderColor.f[1];
1462 params[2] = sampObj->BorderColor.f[2];
1463 params[3] = sampObj->BorderColor.f[3];
1464 break;
1465 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1466 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1467 goto invalid_pname;
1468 *params = (GLfloat) sampObj->CubeMapSeamless;
1469 break;
1470 case GL_TEXTURE_SRGB_DECODE_EXT:
1471 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1472 goto invalid_pname;
1473 *params = (GLfloat) sampObj->sRGBDecode;
1474 break;
1475 default:
1476 goto invalid_pname;
1477 }
1478 return;
1479
1480 invalid_pname:
1481 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1482 _mesa_enum_to_string(pname));
1483 }
1484
1485
1486 void GLAPIENTRY
1487 _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1488 {
1489 struct gl_sampler_object *sampObj;
1490 GET_CURRENT_CONTEXT(ctx);
1491
1492 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1493 "glGetSamplerParameterIiv");
1494 if (!sampObj)
1495 return;
1496
1497 switch (pname) {
1498 case GL_TEXTURE_WRAP_S:
1499 *params = sampObj->WrapS;
1500 break;
1501 case GL_TEXTURE_WRAP_T:
1502 *params = sampObj->WrapT;
1503 break;
1504 case GL_TEXTURE_WRAP_R:
1505 *params = sampObj->WrapR;
1506 break;
1507 case GL_TEXTURE_MIN_FILTER:
1508 *params = sampObj->MinFilter;
1509 break;
1510 case GL_TEXTURE_MAG_FILTER:
1511 *params = sampObj->MagFilter;
1512 break;
1513 case GL_TEXTURE_MIN_LOD:
1514 *params = (GLint) sampObj->MinLod;
1515 break;
1516 case GL_TEXTURE_MAX_LOD:
1517 *params = (GLint) sampObj->MaxLod;
1518 break;
1519 case GL_TEXTURE_LOD_BIAS:
1520 *params = (GLint) sampObj->LodBias;
1521 break;
1522 case GL_TEXTURE_COMPARE_MODE:
1523 *params = sampObj->CompareMode;
1524 break;
1525 case GL_TEXTURE_COMPARE_FUNC:
1526 *params = sampObj->CompareFunc;
1527 break;
1528 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1529 *params = (GLint) sampObj->MaxAnisotropy;
1530 break;
1531 case GL_TEXTURE_BORDER_COLOR:
1532 params[0] = sampObj->BorderColor.i[0];
1533 params[1] = sampObj->BorderColor.i[1];
1534 params[2] = sampObj->BorderColor.i[2];
1535 params[3] = sampObj->BorderColor.i[3];
1536 break;
1537 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1538 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1539 goto invalid_pname;
1540 *params = sampObj->CubeMapSeamless;
1541 break;
1542 case GL_TEXTURE_SRGB_DECODE_EXT:
1543 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1544 goto invalid_pname;
1545 *params = (GLenum) sampObj->sRGBDecode;
1546 break;
1547 default:
1548 goto invalid_pname;
1549 }
1550 return;
1551
1552 invalid_pname:
1553 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1554 _mesa_enum_to_string(pname));
1555 }
1556
1557
1558 void GLAPIENTRY
1559 _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1560 {
1561 struct gl_sampler_object *sampObj;
1562 GET_CURRENT_CONTEXT(ctx);
1563
1564 sampObj = sampler_parameter_error_check(ctx, sampler, true,
1565 "glGetSamplerParameterIuiv");
1566 if (!sampObj)
1567 return;
1568
1569 switch (pname) {
1570 case GL_TEXTURE_WRAP_S:
1571 *params = sampObj->WrapS;
1572 break;
1573 case GL_TEXTURE_WRAP_T:
1574 *params = sampObj->WrapT;
1575 break;
1576 case GL_TEXTURE_WRAP_R:
1577 *params = sampObj->WrapR;
1578 break;
1579 case GL_TEXTURE_MIN_FILTER:
1580 *params = sampObj->MinFilter;
1581 break;
1582 case GL_TEXTURE_MAG_FILTER:
1583 *params = sampObj->MagFilter;
1584 break;
1585 case GL_TEXTURE_MIN_LOD:
1586 *params = (GLuint) sampObj->MinLod;
1587 break;
1588 case GL_TEXTURE_MAX_LOD:
1589 *params = (GLuint) sampObj->MaxLod;
1590 break;
1591 case GL_TEXTURE_LOD_BIAS:
1592 *params = (GLuint) sampObj->LodBias;
1593 break;
1594 case GL_TEXTURE_COMPARE_MODE:
1595 *params = sampObj->CompareMode;
1596 break;
1597 case GL_TEXTURE_COMPARE_FUNC:
1598 *params = sampObj->CompareFunc;
1599 break;
1600 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1601 *params = (GLuint) sampObj->MaxAnisotropy;
1602 break;
1603 case GL_TEXTURE_BORDER_COLOR:
1604 params[0] = sampObj->BorderColor.ui[0];
1605 params[1] = sampObj->BorderColor.ui[1];
1606 params[2] = sampObj->BorderColor.ui[2];
1607 params[3] = sampObj->BorderColor.ui[3];
1608 break;
1609 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1610 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1611 goto invalid_pname;
1612 *params = sampObj->CubeMapSeamless;
1613 break;
1614 case GL_TEXTURE_SRGB_DECODE_EXT:
1615 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1616 goto invalid_pname;
1617 *params = (GLenum) sampObj->sRGBDecode;
1618 break;
1619 default:
1620 goto invalid_pname;
1621 }
1622 return;
1623
1624 invalid_pname:
1625 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1626 _mesa_enum_to_string(pname));
1627 }
1628
1629
1630 void
1631 _mesa_init_sampler_object_functions(struct dd_function_table *driver)
1632 {
1633 driver->NewSamplerObject = _mesa_new_sampler_object;
1634 }