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