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