[0.4.13] Avoid regressions CORE-14955 "Ddraw fullscreen crashes", CORE-15652
[reactos.git] / dll / directx / wine / wined3d / glsl_shader.c
1 /*
2 * GLSL pixel and vertex shader implementation
3 *
4 * Copyright 2006 Jason Green
5 * Copyright 2006-2007 Henri Verbeet
6 * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
7 * Copyright 2009-2011 Henri Verbeet for CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 /*
25 * D3D shader asm has swizzles on source parameters, and write masks for
26 * destination parameters. GLSL uses swizzles for both. The result of this is
27 * that for example "mov dst.xw, src.zyxw" becomes "dst.xw = src.zw" in GLSL.
28 * Ie, to generate a proper GLSL source swizzle, we need to take the D3D write
29 * mask for the destination parameter into account.
30 */
31
32 #include "config.h"
33 #include "wine/port.h"
34
35 #include <limits.h>
36 #include <stdio.h>
37 #ifdef HAVE_FLOAT_H
38 # include <float.h>
39 #endif
40
41 #include "wined3d_private.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
44 WINE_DECLARE_DEBUG_CHANNEL(d3d);
45 WINE_DECLARE_DEBUG_CHANNEL(winediag);
46
47 #define WINED3D_GLSL_SAMPLE_PROJECTED 0x01
48 #define WINED3D_GLSL_SAMPLE_LOD 0x02
49 #define WINED3D_GLSL_SAMPLE_GRAD 0x04
50 #define WINED3D_GLSL_SAMPLE_LOAD 0x08
51 #define WINED3D_GLSL_SAMPLE_OFFSET 0x10
52
53 static const struct
54 {
55 unsigned int coord_size;
56 unsigned int resinfo_size;
57 const char *type_part;
58 }
59 resource_type_info[] =
60 {
61 {0, 0, ""}, /* WINED3D_SHADER_RESOURCE_NONE */
62 {1, 1, "Buffer"}, /* WINED3D_SHADER_RESOURCE_BUFFER */
63 {1, 1, "1D"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_1D */
64 {2, 2, "2D"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2D */
65 {2, 2, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2DMS */
66 {3, 3, "3D"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_3D */
67 {3, 2, "Cube"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_CUBE */
68 {2, 2, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY */
69 {3, 3, "2DArray"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY */
70 {3, 3, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */
71 {4, 3, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */
72 };
73
74 struct glsl_dst_param
75 {
76 char reg_name[150];
77 char mask_str[6];
78 };
79
80 struct glsl_src_param
81 {
82 char reg_name[150];
83 char param_str[200];
84 };
85
86 struct glsl_sample_function
87 {
88 struct wined3d_string_buffer *name;
89 unsigned int coord_mask;
90 unsigned int deriv_mask;
91 enum wined3d_data_type data_type;
92 BOOL output_single_component;
93 unsigned int offset_size;
94 enum wined3d_shader_resource_type emulate_lod;
95 };
96
97 enum heap_node_op
98 {
99 HEAP_NODE_TRAVERSE_LEFT,
100 HEAP_NODE_TRAVERSE_RIGHT,
101 HEAP_NODE_POP,
102 };
103
104 struct constant_entry
105 {
106 unsigned int idx;
107 unsigned int version;
108 };
109
110 struct constant_heap
111 {
112 struct constant_entry *entries;
113 BOOL *contained;
114 unsigned int *positions;
115 unsigned int size;
116 };
117
118 /* GLSL shader private data */
119 struct shader_glsl_priv
120 {
121 struct wined3d_string_buffer shader_buffer;
122 struct wined3d_string_buffer_list string_buffers;
123 struct wine_rb_tree program_lookup;
124 struct constant_heap vconst_heap;
125 struct constant_heap pconst_heap;
126 unsigned char *stack;
127 UINT next_constant_version;
128
129 const struct wined3d_vertex_pipe_ops *vertex_pipe;
130 const struct fragment_pipeline *fragment_pipe;
131 struct wine_rb_tree ffp_vertex_shaders;
132 struct wine_rb_tree ffp_fragment_shaders;
133 BOOL ffp_proj_control;
134 BOOL legacy_lighting;
135 };
136
137 struct glsl_vs_program
138 {
139 struct list shader_entry;
140 GLuint id;
141 GLenum vertex_color_clamp;
142 GLint uniform_f_locations[WINED3D_MAX_VS_CONSTS_F];
143 GLint uniform_i_locations[WINED3D_MAX_CONSTS_I];
144 GLint uniform_b_locations[WINED3D_MAX_CONSTS_B];
145 GLint pos_fixup_location;
146
147 GLint modelview_matrix_location[MAX_VERTEX_INDEX_BLENDS];
148 GLint normal_matrix_location[MAX_VERTEX_INDEX_BLENDS];
149 GLint projection_matrix_location;
150 GLint texture_matrix_location[MAX_TEXTURES];
151 GLint material_ambient_location;
152 GLint material_diffuse_location;
153 GLint material_specular_location;
154 GLint material_emissive_location;
155 GLint material_shininess_location;
156 GLint light_ambient_location;
157 struct
158 {
159 GLint diffuse;
160 GLint specular;
161 GLint ambient;
162 GLint position;
163 GLint direction;
164 GLint range;
165 GLint falloff;
166 GLint c_att;
167 GLint l_att;
168 GLint q_att;
169 GLint cos_htheta;
170 GLint cos_hphi;
171 } light_location[MAX_ACTIVE_LIGHTS];
172 GLint pointsize_location;
173 GLint pointsize_min_location;
174 GLint pointsize_max_location;
175 GLint pointsize_c_att_location;
176 GLint pointsize_l_att_location;
177 GLint pointsize_q_att_location;
178 GLint clip_planes_location;
179 };
180
181 struct glsl_hs_program
182 {
183 struct list shader_entry;
184 GLuint id;
185 };
186
187 struct glsl_ds_program
188 {
189 struct list shader_entry;
190 GLuint id;
191
192 GLint pos_fixup_location;
193 };
194
195 struct glsl_gs_program
196 {
197 struct list shader_entry;
198 GLuint id;
199
200 GLint pos_fixup_location;
201 };
202
203 struct glsl_ps_program
204 {
205 struct list shader_entry;
206 GLuint id;
207 GLint uniform_f_locations[WINED3D_MAX_PS_CONSTS_F];
208 GLint uniform_i_locations[WINED3D_MAX_CONSTS_I];
209 GLint uniform_b_locations[WINED3D_MAX_CONSTS_B];
210 GLint bumpenv_mat_location[MAX_TEXTURES];
211 GLint bumpenv_lum_scale_location[MAX_TEXTURES];
212 GLint bumpenv_lum_offset_location[MAX_TEXTURES];
213 GLint tss_constant_location[MAX_TEXTURES];
214 GLint tex_factor_location;
215 GLint specular_enable_location;
216 GLint fog_color_location;
217 GLint fog_density_location;
218 GLint fog_end_location;
219 GLint fog_scale_location;
220 GLint alpha_test_ref_location;
221 GLint ycorrection_location;
222 GLint np2_fixup_location;
223 GLint color_key_location;
224 const struct ps_np2fixup_info *np2_fixup_info;
225 };
226
227 struct glsl_cs_program
228 {
229 struct list shader_entry;
230 GLuint id;
231 };
232
233 /* Struct to maintain data about a linked GLSL program */
234 struct glsl_shader_prog_link
235 {
236 struct wine_rb_entry program_lookup_entry;
237 struct glsl_vs_program vs;
238 struct glsl_hs_program hs;
239 struct glsl_ds_program ds;
240 struct glsl_gs_program gs;
241 struct glsl_ps_program ps;
242 struct glsl_cs_program cs;
243 GLuint id;
244 DWORD constant_update_mask;
245 unsigned int constant_version;
246 DWORD shader_controlled_clip_distances : 1;
247 DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */
248 DWORD padding : 23;
249 };
250
251 struct glsl_program_key
252 {
253 GLuint vs_id;
254 GLuint hs_id;
255 GLuint ds_id;
256 GLuint gs_id;
257 GLuint ps_id;
258 GLuint cs_id;
259 };
260
261 struct shader_glsl_ctx_priv {
262 const struct vs_compile_args *cur_vs_args;
263 const struct ds_compile_args *cur_ds_args;
264 const struct ps_compile_args *cur_ps_args;
265 struct ps_np2fixup_info *cur_np2fixup_info;
266 struct wined3d_string_buffer_list *string_buffers;
267 };
268
269 struct glsl_context_data
270 {
271 struct glsl_shader_prog_link *glsl_program;
272 GLenum vertex_color_clamp;
273 BOOL rasterization_disabled;
274 };
275
276 struct glsl_ps_compiled_shader
277 {
278 struct ps_compile_args args;
279 struct ps_np2fixup_info np2fixup;
280 GLuint id;
281 };
282
283 struct glsl_vs_compiled_shader
284 {
285 struct vs_compile_args args;
286 GLuint id;
287 };
288
289 struct glsl_hs_compiled_shader
290 {
291 GLuint id;
292 };
293
294 struct glsl_ds_compiled_shader
295 {
296 struct ds_compile_args args;
297 GLuint id;
298 };
299
300 struct glsl_gs_compiled_shader
301 {
302 struct gs_compile_args args;
303 GLuint id;
304 };
305
306 struct glsl_cs_compiled_shader
307 {
308 GLuint id;
309 };
310
311 struct glsl_shader_private
312 {
313 union
314 {
315 struct glsl_vs_compiled_shader *vs;
316 struct glsl_hs_compiled_shader *hs;
317 struct glsl_ds_compiled_shader *ds;
318 struct glsl_gs_compiled_shader *gs;
319 struct glsl_ps_compiled_shader *ps;
320 struct glsl_cs_compiled_shader *cs;
321 } gl_shaders;
322 unsigned int num_gl_shaders, shader_array_size;
323 };
324
325 struct glsl_ffp_vertex_shader
326 {
327 struct wined3d_ffp_vs_desc desc;
328 GLuint id;
329 struct list linked_programs;
330 };
331
332 struct glsl_ffp_fragment_shader
333 {
334 struct ffp_frag_desc entry;
335 GLuint id;
336 struct list linked_programs;
337 };
338
339 struct glsl_ffp_destroy_ctx
340 {
341 struct shader_glsl_priv *priv;
342 const struct wined3d_gl_info *gl_info;
343 };
344
345 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx);
346
347 static const char *debug_gl_shader_type(GLenum type)
348 {
349 switch (type)
350 {
351 #define WINED3D_TO_STR(u) case u: return #u
352 WINED3D_TO_STR(GL_VERTEX_SHADER);
353 WINED3D_TO_STR(GL_TESS_CONTROL_SHADER);
354 WINED3D_TO_STR(GL_TESS_EVALUATION_SHADER);
355 WINED3D_TO_STR(GL_GEOMETRY_SHADER);
356 WINED3D_TO_STR(GL_FRAGMENT_SHADER);
357 WINED3D_TO_STR(GL_COMPUTE_SHADER);
358 #undef WINED3D_TO_STR
359 default:
360 return wine_dbg_sprintf("UNKNOWN(%#x)", type);
361 }
362 }
363
364 static const char *shader_glsl_get_prefix(enum wined3d_shader_type type)
365 {
366 switch (type)
367 {
368 case WINED3D_SHADER_TYPE_VERTEX:
369 return "vs";
370
371 case WINED3D_SHADER_TYPE_HULL:
372 return "hs";
373
374 case WINED3D_SHADER_TYPE_DOMAIN:
375 return "ds";
376
377 case WINED3D_SHADER_TYPE_GEOMETRY:
378 return "gs";
379
380 case WINED3D_SHADER_TYPE_PIXEL:
381 return "ps";
382
383 case WINED3D_SHADER_TYPE_COMPUTE:
384 return "cs";
385
386 default:
387 FIXME("Unhandled shader type %#x.\n", type);
388 return "unknown";
389 }
390 }
391
392 static unsigned int shader_glsl_get_version(const struct wined3d_gl_info *gl_info)
393 {
394 if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 40))
395 return 440;
396 else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50))
397 return 150;
398 else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 30))
399 return 130;
400 else
401 return 120;
402 }
403
404 static void shader_glsl_add_version_declaration(struct wined3d_string_buffer *buffer,
405 const struct wined3d_gl_info *gl_info)
406 {
407 shader_addline(buffer, "#version %u\n", shader_glsl_get_version(gl_info));
408 }
409
410 static void shader_glsl_append_imm_vec4(struct wined3d_string_buffer *buffer, const float *values)
411 {
412 char str[4][17];
413
414 wined3d_ftoa(values[0], str[0]);
415 wined3d_ftoa(values[1], str[1]);
416 wined3d_ftoa(values[2], str[2]);
417 wined3d_ftoa(values[3], str[3]);
418 shader_addline(buffer, "vec4(%s, %s, %s, %s)", str[0], str[1], str[2], str[3]);
419 }
420
421 static void shader_glsl_append_imm_ivec(struct wined3d_string_buffer *buffer,
422 const int *values, unsigned int size)
423 {
424 int i;
425
426 if (!size || size > 4)
427 {
428 ERR("Invalid vector size %u.\n", size);
429 return;
430 }
431
432 if (size > 1)
433 shader_addline(buffer, "ivec%u(", size);
434
435 for (i = 0; i < size; ++i)
436 shader_addline(buffer, i ? ", %#x" : "%#x", values[i]);
437
438 if (size > 1)
439 shader_addline(buffer, ")");
440 }
441
442 static const char *get_info_log_line(const char **ptr)
443 {
444 const char *p, *q;
445
446 p = *ptr;
447 if (!(q = strstr(p, "\n")))
448 {
449 if (!*p) return NULL;
450 *ptr += strlen(p);
451 return p;
452 }
453 *ptr = q + 1;
454
455 return p;
456 }
457
458 /* Context activation is done by the caller. */
459 void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program)
460 {
461 int length = 0;
462 char *log;
463
464 if (!WARN_ON(d3d_shader) && !FIXME_ON(d3d_shader))
465 return;
466
467 if (program)
468 GL_EXTCALL(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length));
469 else
470 GL_EXTCALL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
471
472 /* A size of 1 is just a null-terminated string, so the log should be bigger than
473 * that if there are errors. */
474 if (length > 1)
475 {
476 const char *ptr, *line;
477
478 log = heap_alloc(length);
479 /* The info log is supposed to be zero-terminated, but at least some
480 * versions of fglrx don't terminate the string properly. The reported
481 * length does include the terminator, so explicitly set it to zero
482 * here. */
483 log[length - 1] = 0;
484 if (program)
485 GL_EXTCALL(glGetProgramInfoLog(id, length, NULL, log));
486 else
487 GL_EXTCALL(glGetShaderInfoLog(id, length, NULL, log));
488
489 ptr = log;
490 if (gl_info->quirks & WINED3D_QUIRK_INFO_LOG_SPAM)
491 {
492 WARN("Info log received from GLSL shader #%u:\n", id);
493 while ((line = get_info_log_line(&ptr))) WARN(" %.*s", (int)(ptr - line), line);
494 }
495 else
496 {
497 FIXME("Info log received from GLSL shader #%u:\n", id);
498 while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line);
499 }
500 heap_free(log);
501 }
502 }
503
504 /* Context activation is done by the caller. */
505 static void shader_glsl_compile(const struct wined3d_gl_info *gl_info, GLuint shader, const char *src)
506 {
507 const char *ptr, *line;
508
509 TRACE("Compiling shader object %u.\n", shader);
510
511 if (TRACE_ON(d3d_shader))
512 {
513 ptr = src;
514 while ((line = get_info_log_line(&ptr))) TRACE_(d3d_shader)(" %.*s", (int)(ptr - line), line);
515 }
516
517 GL_EXTCALL(glShaderSource(shader, 1, &src, NULL));
518 checkGLcall("glShaderSource");
519 GL_EXTCALL(glCompileShader(shader));
520 checkGLcall("glCompileShader");
521 print_glsl_info_log(gl_info, shader, FALSE);
522 }
523
524 /* Context activation is done by the caller. */
525 static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLuint program)
526 {
527 GLint i, shader_count, source_size = -1;
528 GLuint *shaders;
529 char *source = NULL;
530
531 GL_EXTCALL(glGetProgramiv(program, GL_ATTACHED_SHADERS, &shader_count));
532 if (!(shaders = heap_calloc(shader_count, sizeof(*shaders))))
533 {
534 ERR("Failed to allocate shader array memory.\n");
535 return;
536 }
537
538 GL_EXTCALL(glGetAttachedShaders(program, shader_count, NULL, shaders));
539 for (i = 0; i < shader_count; ++i)
540 {
541 const char *ptr, *line;
542 GLint tmp;
543
544 GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &tmp));
545
546 if (source_size < tmp)
547 {
548 heap_free(source);
549
550 if (!(source = heap_alloc_zero(tmp)))
551 {
552 ERR("Failed to allocate %d bytes for shader source.\n", tmp);
553 heap_free(shaders);
554 return;
555 }
556 source_size = tmp;
557 }
558
559 FIXME("Shader %u:\n", shaders[i]);
560 GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_TYPE, &tmp));
561 FIXME(" GL_SHADER_TYPE: %s.\n", debug_gl_shader_type(tmp));
562 GL_EXTCALL(glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &tmp));
563 FIXME(" GL_COMPILE_STATUS: %d.\n", tmp);
564 FIXME("\n");
565
566 ptr = source;
567 GL_EXTCALL(glGetShaderSource(shaders[i], source_size, NULL, source));
568 while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line);
569 FIXME("\n");
570 }
571
572 heap_free(source);
573 heap_free(shaders);
574 }
575
576 /* Context activation is done by the caller. */
577 void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program)
578 {
579 GLint tmp;
580
581 if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader))
582 return;
583
584 GL_EXTCALL(glGetProgramiv(program, GL_LINK_STATUS, &tmp));
585 if (!tmp)
586 {
587 FIXME("Program %u link status invalid.\n", program);
588 shader_glsl_dump_program_source(gl_info, program);
589 }
590
591 print_glsl_info_log(gl_info, program, TRUE);
592 }
593
594 static BOOL shader_glsl_use_layout_qualifier(const struct wined3d_gl_info *gl_info)
595 {
596 /* Layout qualifiers were introduced in GLSL 1.40. The Nvidia Legacy GPU
597 * driver (series 340.xx) doesn't parse layout qualifiers in older GLSL
598 * versions. */
599 return shader_glsl_get_version(gl_info) >= 140;
600 }
601
602 static BOOL shader_glsl_use_layout_binding_qualifier(const struct wined3d_gl_info *gl_info)
603 {
604 return gl_info->supported[ARB_SHADING_LANGUAGE_420PACK] && shader_glsl_use_layout_qualifier(gl_info);
605 }
606
607 static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info,
608 struct shader_glsl_priv *priv, GLuint program_id,
609 const struct wined3d_shader_reg_maps *reg_maps)
610 {
611 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
612 struct wined3d_string_buffer *name;
613 unsigned int i, base, count;
614 GLuint block_idx;
615
616 if (shader_glsl_use_layout_binding_qualifier(gl_info))
617 return;
618
619 name = string_buffer_get(&priv->string_buffers);
620 wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, reg_maps->shader_version.type, &base, &count);
621 for (i = 0; i < count; ++i)
622 {
623 if (!reg_maps->cb_sizes[i])
624 continue;
625
626 string_buffer_sprintf(name, "block_%s_cb%u", prefix, i);
627 block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name->buffer));
628 GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i));
629 }
630 checkGLcall("glUniformBlockBinding");
631 string_buffer_release(&priv->string_buffers, name);
632 }
633
634 /* Context activation is done by the caller. */
635 static void shader_glsl_load_samplers_range(const struct wined3d_gl_info *gl_info,
636 struct shader_glsl_priv *priv, GLuint program_id, const char *prefix,
637 unsigned int base, unsigned int count, const DWORD *tex_unit_map)
638 {
639 struct wined3d_string_buffer *sampler_name = string_buffer_get(&priv->string_buffers);
640 unsigned int i, mapped_unit;
641 GLint name_loc;
642
643 for (i = 0; i < count; ++i)
644 {
645 string_buffer_sprintf(sampler_name, "%s_sampler%u", prefix, i);
646 name_loc = GL_EXTCALL(glGetUniformLocation(program_id, sampler_name->buffer));
647 if (name_loc == -1)
648 continue;
649
650 mapped_unit = tex_unit_map ? tex_unit_map[base + i] : base + i;
651 if (mapped_unit == WINED3D_UNMAPPED_STAGE || mapped_unit >= gl_info->limits.combined_samplers)
652 {
653 ERR("Trying to load sampler %s on unsupported unit %u.\n", sampler_name->buffer, mapped_unit);
654 continue;
655 }
656
657 TRACE("Loading sampler %s on unit %u.\n", sampler_name->buffer, mapped_unit);
658 GL_EXTCALL(glUniform1i(name_loc, mapped_unit));
659 }
660 checkGLcall("Load sampler bindings");
661 string_buffer_release(&priv->string_buffers, sampler_name);
662 }
663
664 static unsigned int shader_glsl_map_tex_unit(const struct wined3d_context *context,
665 const struct wined3d_shader_version *shader_version, unsigned int sampler_idx)
666 {
667 const DWORD *tex_unit_map;
668 unsigned int base, count;
669
670 tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count);
671 if (sampler_idx >= count)
672 return WINED3D_UNMAPPED_STAGE;
673 if (!tex_unit_map)
674 return base + sampler_idx;
675 return tex_unit_map[base + sampler_idx];
676 }
677
678 static void shader_glsl_append_sampler_binding_qualifier(struct wined3d_string_buffer *buffer,
679 const struct wined3d_context *context, const struct wined3d_shader_version *shader_version,
680 unsigned int sampler_idx)
681 {
682 unsigned int mapped_unit = shader_glsl_map_tex_unit(context, shader_version, sampler_idx);
683 if (mapped_unit != WINED3D_UNMAPPED_STAGE)
684 shader_addline(buffer, "layout(binding = %u)\n", mapped_unit);
685 else
686 ERR("Unmapped sampler %u.\n", sampler_idx);
687 }
688
689 /* Context activation is done by the caller. */
690 static void shader_glsl_load_samplers(const struct wined3d_context *context,
691 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
692 {
693 const struct wined3d_gl_info *gl_info = context->gl_info;
694 const struct wined3d_shader_version *shader_version;
695 const DWORD *tex_unit_map;
696 unsigned int base, count;
697 const char *prefix;
698
699 if (shader_glsl_use_layout_binding_qualifier(gl_info))
700 return;
701
702 shader_version = reg_maps ? &reg_maps->shader_version : NULL;
703 prefix = shader_glsl_get_prefix(shader_version ? shader_version->type : WINED3D_SHADER_TYPE_PIXEL);
704 tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count);
705 shader_glsl_load_samplers_range(gl_info, priv, program_id, prefix, base, count, tex_unit_map);
706 }
707
708 static void shader_glsl_load_icb(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv,
709 GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
710 {
711 const struct wined3d_shader_immediate_constant_buffer *icb = reg_maps->icb;
712
713 if (icb)
714 {
715 struct wined3d_string_buffer *icb_name = string_buffer_get(&priv->string_buffers);
716 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
717 GLint icb_location;
718
719 string_buffer_sprintf(icb_name, "%s_icb", prefix);
720 icb_location = GL_EXTCALL(glGetUniformLocation(program_id, icb_name->buffer));
721 GL_EXTCALL(glUniform4fv(icb_location, icb->vec4_count, (const GLfloat *)icb->data));
722 checkGLcall("Load immediate constant buffer");
723
724 string_buffer_release(&priv->string_buffers, icb_name);
725 }
726 }
727
728 /* Context activation is done by the caller. */
729 static void shader_glsl_load_images(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv,
730 GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
731 {
732 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
733 struct wined3d_string_buffer *name;
734 GLint location;
735 unsigned int i;
736
737 if (shader_glsl_use_layout_binding_qualifier(gl_info))
738 return;
739
740 name = string_buffer_get(&priv->string_buffers);
741 for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
742 {
743 if (!reg_maps->uav_resource_info[i].type)
744 continue;
745
746 string_buffer_sprintf(name, "%s_image%u", prefix, i);
747 location = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
748 if (location == -1)
749 continue;
750
751 TRACE("Loading image %s on unit %u.\n", name->buffer, i);
752 GL_EXTCALL(glUniform1i(location, i));
753 }
754 checkGLcall("Load image bindings");
755 string_buffer_release(&priv->string_buffers, name);
756 }
757
758 /* Context activation is done by the caller. */
759 static void shader_glsl_load_program_resources(const struct wined3d_context *context,
760 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader)
761 {
762 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
763
764 shader_glsl_init_uniform_block_bindings(context->gl_info, priv, program_id, reg_maps);
765 shader_glsl_load_icb(context->gl_info, priv, program_id, reg_maps);
766 /* Texture unit mapping is set up to be the same each time the shader
767 * program is used so we can hardcode the sampler uniform values. */
768 shader_glsl_load_samplers(context, priv, program_id, reg_maps);
769 }
770
771 static void append_transform_feedback_varying(const char **varyings, unsigned int *varying_count,
772 char **strings, unsigned int *strings_length, struct wined3d_string_buffer *buffer)
773 {
774 if (varyings && *strings)
775 {
776 char *ptr = *strings;
777
778 varyings[*varying_count] = ptr;
779
780 memcpy(ptr, buffer->buffer, buffer->content_size + 1);
781 ptr += buffer->content_size + 1;
782
783 *strings = ptr;
784 }
785
786 *strings_length += buffer->content_size + 1;
787 ++(*varying_count);
788 }
789
790 static void append_transform_feedback_skip_components(const char **varyings,
791 unsigned int *varying_count, char **strings, unsigned int *strings_length,
792 struct wined3d_string_buffer *buffer, unsigned int component_count)
793 {
794 unsigned int j;
795
796 for (j = 0; j < component_count / 4; ++j)
797 {
798 string_buffer_sprintf(buffer, "gl_SkipComponents4");
799 append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer);
800 }
801 if (component_count % 4)
802 {
803 string_buffer_sprintf(buffer, "gl_SkipComponents%u", component_count % 4);
804 append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer);
805 }
806 }
807
808 static void shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc,
809 struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count,
810 char *strings, unsigned int *strings_length, GLenum buffer_mode)
811 {
812 unsigned int i, buffer_idx, count, length, highest_output_slot, stride;
813
814 count = length = 0;
815 highest_output_slot = 0;
816 for (buffer_idx = 0; buffer_idx < WINED3D_MAX_STREAM_OUTPUT_BUFFERS; ++buffer_idx)
817 {
818 stride = 0;
819
820 for (i = 0; i < so_desc->element_count; ++i)
821 {
822 const struct wined3d_stream_output_element *e = &so_desc->elements[i];
823
824 highest_output_slot = max(highest_output_slot, e->output_slot);
825 if (e->output_slot != buffer_idx)
826 continue;
827
828 if (e->stream_idx)
829 {
830 FIXME("Unhandled stream %u.\n", e->stream_idx);
831 continue;
832 }
833
834 stride += e->component_count;
835
836 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
837 {
838 append_transform_feedback_skip_components(varyings, &count,
839 &strings, &length, buffer, e->component_count);
840 continue;
841 }
842
843 if (e->component_idx || e->component_count != 4)
844 {
845 if (so_desc->rasterizer_stream_idx != WINED3D_NO_RASTERIZER_STREAM)
846 {
847 FIXME("Unsupported component range %u-%u.\n", e->component_idx, e->component_count);
848 append_transform_feedback_skip_components(varyings, &count,
849 &strings, &length, buffer, e->component_count);
850 continue;
851 }
852
853 string_buffer_sprintf(buffer, "shader_in_out.reg%u_%u_%u",
854 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1);
855 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
856 }
857 else
858 {
859 string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx);
860 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
861 }
862 }
863
864 if (buffer_idx < so_desc->buffer_stride_count
865 && stride < so_desc->buffer_strides[buffer_idx] / 4)
866 {
867 unsigned int component_count = so_desc->buffer_strides[buffer_idx] / 4 - stride;
868 append_transform_feedback_skip_components(varyings, &count,
869 &strings, &length, buffer, component_count);
870 }
871
872 if (highest_output_slot <= buffer_idx)
873 break;
874
875 if (buffer_mode == GL_INTERLEAVED_ATTRIBS)
876 {
877 string_buffer_sprintf(buffer, "gl_NextBuffer");
878 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
879 }
880 }
881
882 if (varying_count)
883 *varying_count = count;
884 if (strings_length)
885 *strings_length = length;
886 }
887
888 static void shader_glsl_init_transform_feedback(const struct wined3d_context *context,
889 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader)
890 {
891 const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
892 const struct wined3d_gl_info *gl_info = context->gl_info;
893 struct wined3d_string_buffer *buffer;
894 unsigned int i, count, length;
895 const char **varyings;
896 char *strings;
897 GLenum mode;
898
899 if (!so_desc->element_count)
900 return;
901
902 if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
903 {
904 mode = GL_INTERLEAVED_ATTRIBS;
905 }
906 else
907 {
908 unsigned int element_count[WINED3D_MAX_STREAM_OUTPUT_BUFFERS] = {0};
909
910 for (i = 0; i < so_desc->element_count; ++i)
911 {
912 if (so_desc->elements[i].register_idx == WINED3D_STREAM_OUTPUT_GAP)
913 {
914 FIXME("ARB_transform_feedback3 is needed for stream output gaps.\n");
915 return;
916 }
917 ++element_count[so_desc->elements[i].output_slot];
918 }
919
920 if (element_count[0] == so_desc->element_count)
921 {
922 mode = GL_INTERLEAVED_ATTRIBS;
923 }
924 else
925 {
926 mode = GL_SEPARATE_ATTRIBS;
927 for (i = 0; i < ARRAY_SIZE(element_count); ++i)
928 {
929 if (element_count[i] != 1)
930 break;
931 }
932 for (; i < ARRAY_SIZE(element_count); ++i)
933 {
934 if (element_count[i])
935 {
936 FIXME("Only single element per buffer is allowed in separate mode.\n");
937 return;
938 }
939 }
940 }
941 }
942
943 buffer = string_buffer_get(&priv->string_buffers);
944
945 shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode);
946
947 if (!(varyings = heap_calloc(count, sizeof(*varyings))))
948 {
949 ERR("Out of memory.\n");
950 string_buffer_release(&priv->string_buffers, buffer);
951 return;
952 }
953 if (!(strings = heap_calloc(length, sizeof(*strings))))
954 {
955 ERR("Out of memory.\n");
956 heap_free(varyings);
957 string_buffer_release(&priv->string_buffers, buffer);
958 return;
959 }
960
961 shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL, mode);
962 GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, mode));
963 checkGLcall("glTransformFeedbackVaryings");
964
965 heap_free(varyings);
966 heap_free(strings);
967 string_buffer_release(&priv->string_buffers, buffer);
968 }
969
970 /* Context activation is done by the caller. */
971 static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants,
972 const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
973 {
974 unsigned int start = ~0U, end = 0;
975 int stack_idx = 0;
976 unsigned int heap_idx = 1;
977 unsigned int idx;
978
979 if (heap->entries[heap_idx].version <= version) return;
980
981 idx = heap->entries[heap_idx].idx;
982 if (constant_locations[idx] != -1)
983 start = end = idx;
984 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
985
986 while (stack_idx >= 0)
987 {
988 /* Note that we fall through to the next case statement. */
989 switch(stack[stack_idx])
990 {
991 case HEAP_NODE_TRAVERSE_LEFT:
992 {
993 unsigned int left_idx = heap_idx << 1;
994 if (left_idx < heap->size && heap->entries[left_idx].version > version)
995 {
996 heap_idx = left_idx;
997 idx = heap->entries[heap_idx].idx;
998 if (constant_locations[idx] != -1)
999 {
1000 if (start > idx)
1001 start = idx;
1002 if (end < idx)
1003 end = idx;
1004 }
1005
1006 stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
1007 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1008 break;
1009 }
1010 }
1011
1012 case HEAP_NODE_TRAVERSE_RIGHT:
1013 {
1014 unsigned int right_idx = (heap_idx << 1) + 1;
1015 if (right_idx < heap->size && heap->entries[right_idx].version > version)
1016 {
1017 heap_idx = right_idx;
1018 idx = heap->entries[heap_idx].idx;
1019 if (constant_locations[idx] != -1)
1020 {
1021 if (start > idx)
1022 start = idx;
1023 if (end < idx)
1024 end = idx;
1025 }
1026
1027 stack[stack_idx++] = HEAP_NODE_POP;
1028 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1029 break;
1030 }
1031 }
1032
1033 case HEAP_NODE_POP:
1034 heap_idx >>= 1;
1035 --stack_idx;
1036 break;
1037 }
1038 }
1039 if (start <= end)
1040 GL_EXTCALL(glUniform4fv(constant_locations[start], end - start + 1, &constants[start].x));
1041 checkGLcall("walk_constant_heap()");
1042 }
1043
1044 /* Context activation is done by the caller. */
1045 static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info,
1046 GLint location, const struct wined3d_vec4 *data)
1047 {
1048 GLfloat clamped_constant[4];
1049
1050 if (location == -1) return;
1051
1052 clamped_constant[0] = data->x < -1.0f ? -1.0f : data->x > 1.0f ? 1.0f : data->x;
1053 clamped_constant[1] = data->y < -1.0f ? -1.0f : data->y > 1.0f ? 1.0f : data->y;
1054 clamped_constant[2] = data->z < -1.0f ? -1.0f : data->z > 1.0f ? 1.0f : data->z;
1055 clamped_constant[3] = data->w < -1.0f ? -1.0f : data->w > 1.0f ? 1.0f : data->w;
1056
1057 GL_EXTCALL(glUniform4fv(location, 1, clamped_constant));
1058 }
1059
1060 /* Context activation is done by the caller. */
1061 static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info,
1062 const struct wined3d_vec4 *constants, const GLint *constant_locations,
1063 const struct constant_heap *heap, unsigned char *stack, DWORD version)
1064 {
1065 int stack_idx = 0;
1066 unsigned int heap_idx = 1;
1067 unsigned int idx;
1068
1069 if (heap->entries[heap_idx].version <= version) return;
1070
1071 idx = heap->entries[heap_idx].idx;
1072 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]);
1073 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1074
1075 while (stack_idx >= 0)
1076 {
1077 /* Note that we fall through to the next case statement. */
1078 switch(stack[stack_idx])
1079 {
1080 case HEAP_NODE_TRAVERSE_LEFT:
1081 {
1082 unsigned int left_idx = heap_idx << 1;
1083 if (left_idx < heap->size && heap->entries[left_idx].version > version)
1084 {
1085 heap_idx = left_idx;
1086 idx = heap->entries[heap_idx].idx;
1087 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]);
1088
1089 stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
1090 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1091 break;
1092 }
1093 }
1094
1095 case HEAP_NODE_TRAVERSE_RIGHT:
1096 {
1097 unsigned int right_idx = (heap_idx << 1) + 1;
1098 if (right_idx < heap->size && heap->entries[right_idx].version > version)
1099 {
1100 heap_idx = right_idx;
1101 idx = heap->entries[heap_idx].idx;
1102 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]);
1103
1104 stack[stack_idx++] = HEAP_NODE_POP;
1105 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1106 break;
1107 }
1108 }
1109
1110 case HEAP_NODE_POP:
1111 heap_idx >>= 1;
1112 --stack_idx;
1113 break;
1114 }
1115 }
1116 checkGLcall("walk_constant_heap_clamped()");
1117 }
1118
1119 /* Context activation is done by the caller. */
1120 static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
1121 const struct wined3d_vec4 *constants, const GLint *constant_locations, const struct constant_heap *heap,
1122 unsigned char *stack, unsigned int version)
1123 {
1124 const struct wined3d_shader_lconst *lconst;
1125
1126 /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
1127 if (shader->reg_maps.shader_version.major == 1
1128 && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
1129 walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
1130 else
1131 walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
1132
1133 if (!shader->load_local_constsF)
1134 {
1135 TRACE("No need to load local float constants for this shader.\n");
1136 return;
1137 }
1138
1139 /* Immediate constants are clamped to [-1;1] at shader creation time if needed */
1140 LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
1141 {
1142 GL_EXTCALL(glUniform4fv(constant_locations[lconst->idx], 1, (const GLfloat *)lconst->value));
1143 }
1144 checkGLcall("glUniform4fv()");
1145 }
1146
1147 /* Context activation is done by the caller. */
1148 static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
1149 const struct wined3d_ivec4 *constants, const GLint locations[WINED3D_MAX_CONSTS_I], WORD constants_set)
1150 {
1151 unsigned int i;
1152 struct list* ptr;
1153
1154 for (i = 0; constants_set; constants_set >>= 1, ++i)
1155 {
1156 if (!(constants_set & 1)) continue;
1157
1158 /* We found this uniform name in the program - go ahead and send the data */
1159 GL_EXTCALL(glUniform4iv(locations[i], 1, &constants[i].x));
1160 }
1161
1162 /* Load immediate constants */
1163 ptr = list_head(&shader->constantsI);
1164 while (ptr)
1165 {
1166 const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry);
1167 unsigned int idx = lconst->idx;
1168 const GLint *values = (const GLint *)lconst->value;
1169
1170 /* We found this uniform name in the program - go ahead and send the data */
1171 GL_EXTCALL(glUniform4iv(locations[idx], 1, values));
1172 ptr = list_next(&shader->constantsI, ptr);
1173 }
1174 checkGLcall("glUniform4iv()");
1175 }
1176
1177 /* Context activation is done by the caller. */
1178 static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
1179 const GLint locations[WINED3D_MAX_CONSTS_B], const BOOL *constants, WORD constants_set)
1180 {
1181 unsigned int i;
1182 struct list* ptr;
1183
1184 for (i = 0; constants_set; constants_set >>= 1, ++i)
1185 {
1186 if (!(constants_set & 1)) continue;
1187
1188 GL_EXTCALL(glUniform1iv(locations[i], 1, &constants[i]));
1189 }
1190
1191 /* Load immediate constants */
1192 ptr = list_head(&shader->constantsB);
1193 while (ptr)
1194 {
1195 const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry);
1196 unsigned int idx = lconst->idx;
1197 const GLint *values = (const GLint *)lconst->value;
1198
1199 GL_EXTCALL(glUniform1iv(locations[idx], 1, values));
1200 ptr = list_next(&shader->constantsB, ptr);
1201 }
1202 checkGLcall("glUniform1iv()");
1203 }
1204
1205 static void reset_program_constant_version(struct wine_rb_entry *entry, void *context)
1206 {
1207 WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0;
1208 }
1209
1210 /* Context activation is done by the caller (state handler). */
1211 static void shader_glsl_load_np2fixup_constants(const struct glsl_ps_program *ps,
1212 const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
1213 {
1214 struct
1215 {
1216 float sx, sy;
1217 }
1218 np2fixup_constants[MAX_FRAGMENT_SAMPLERS];
1219 UINT fixup = ps->np2_fixup_info->active;
1220 UINT i;
1221
1222 for (i = 0; fixup; fixup >>= 1, ++i)
1223 {
1224 const struct wined3d_texture *tex = state->textures[i];
1225 unsigned char idx = ps->np2_fixup_info->idx[i];
1226
1227 if (!tex)
1228 {
1229 ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n");
1230 continue;
1231 }
1232
1233 np2fixup_constants[idx].sx = tex->pow2_matrix[0];
1234 np2fixup_constants[idx].sy = tex->pow2_matrix[5];
1235 }
1236
1237 GL_EXTCALL(glUniform4fv(ps->np2_fixup_location, ps->np2_fixup_info->num_consts, &np2fixup_constants[0].sx));
1238 }
1239
1240 static void shader_glsl_ffp_vertex_texmatrix_uniform(const struct wined3d_context *context,
1241 const struct wined3d_state *state, unsigned int tex, struct glsl_shader_prog_link *prog)
1242 {
1243 const struct wined3d_gl_info *gl_info = context->gl_info;
1244 struct wined3d_matrix mat;
1245
1246 if (tex >= MAX_TEXTURES)
1247 return;
1248 if (prog->vs.texture_matrix_location[tex] == -1)
1249 return;
1250
1251 get_texture_matrix(context, state, tex, &mat);
1252 GL_EXTCALL(glUniformMatrix4fv(prog->vs.texture_matrix_location[tex], 1, FALSE, &mat._11));
1253 checkGLcall("glUniformMatrix4fv");
1254 }
1255
1256 static void shader_glsl_ffp_vertex_material_uniform(const struct wined3d_context *context,
1257 const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1258 {
1259 const struct wined3d_gl_info *gl_info = context->gl_info;
1260
1261 if (state->render_states[WINED3D_RS_SPECULARENABLE])
1262 {
1263 GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, &state->material.specular.r));
1264 GL_EXTCALL(glUniform1f(prog->vs.material_shininess_location, state->material.power));
1265 }
1266 else
1267 {
1268 static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1269
1270 GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, black));
1271 }
1272 GL_EXTCALL(glUniform4fv(prog->vs.material_ambient_location, 1, &state->material.ambient.r));
1273 GL_EXTCALL(glUniform4fv(prog->vs.material_diffuse_location, 1, &state->material.diffuse.r));
1274 GL_EXTCALL(glUniform4fv(prog->vs.material_emissive_location, 1, &state->material.emissive.r));
1275 checkGLcall("setting FFP material uniforms");
1276 }
1277
1278 static void shader_glsl_ffp_vertex_lightambient_uniform(const struct wined3d_context *context,
1279 const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1280 {
1281 const struct wined3d_gl_info *gl_info = context->gl_info;
1282 struct wined3d_color color;
1283
1284 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_AMBIENT]);
1285 GL_EXTCALL(glUniform3fv(prog->vs.light_ambient_location, 1, &color.r));
1286 checkGLcall("glUniform3fv");
1287 }
1288
1289 static void multiply_vector_matrix(struct wined3d_vec4 *dest, const struct wined3d_vec4 *src1,
1290 const struct wined3d_matrix *src2)
1291 {
1292 struct wined3d_vec4 temp;
1293
1294 temp.x = (src1->x * src2->_11) + (src1->y * src2->_21) + (src1->z * src2->_31) + (src1->w * src2->_41);
1295 temp.y = (src1->x * src2->_12) + (src1->y * src2->_22) + (src1->z * src2->_32) + (src1->w * src2->_42);
1296 temp.z = (src1->x * src2->_13) + (src1->y * src2->_23) + (src1->z * src2->_33) + (src1->w * src2->_43);
1297 temp.w = (src1->x * src2->_14) + (src1->y * src2->_24) + (src1->z * src2->_34) + (src1->w * src2->_44);
1298
1299 *dest = temp;
1300 }
1301
1302 static void shader_glsl_ffp_vertex_light_uniform(const struct wined3d_context *context,
1303 const struct wined3d_state *state, unsigned int light, const struct wined3d_light_info *light_info,
1304 struct glsl_shader_prog_link *prog)
1305 {
1306 const struct wined3d_matrix *view = &state->transforms[WINED3D_TS_VIEW];
1307 const struct wined3d_gl_info *gl_info = context->gl_info;
1308 struct wined3d_vec4 vec4;
1309
1310 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].diffuse, 1, &light_info->OriginalParms.diffuse.r));
1311 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].specular, 1, &light_info->OriginalParms.specular.r));
1312 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].ambient, 1, &light_info->OriginalParms.ambient.r));
1313
1314 switch (light_info->OriginalParms.type)
1315 {
1316 case WINED3D_LIGHT_POINT:
1317 multiply_vector_matrix(&vec4, &light_info->position, view);
1318 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x));
1319 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range));
1320 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0));
1321 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1));
1322 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2));
1323 break;
1324
1325 case WINED3D_LIGHT_SPOT:
1326 multiply_vector_matrix(&vec4, &light_info->position, view);
1327 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x));
1328
1329 multiply_vector_matrix(&vec4, &light_info->direction, view);
1330 GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x));
1331
1332 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range));
1333 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].falloff, light_info->OriginalParms.falloff));
1334 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0));
1335 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1));
1336 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2));
1337 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_htheta, cosf(light_info->OriginalParms.theta / 2.0f)));
1338 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_hphi, cosf(light_info->OriginalParms.phi / 2.0f)));
1339 break;
1340
1341 case WINED3D_LIGHT_DIRECTIONAL:
1342 multiply_vector_matrix(&vec4, &light_info->direction, view);
1343 GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x));
1344 break;
1345
1346 case WINED3D_LIGHT_PARALLELPOINT:
1347 multiply_vector_matrix(&vec4, &light_info->position, view);
1348 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x));
1349 break;
1350
1351 default:
1352 FIXME("Unrecognized light type %#x.\n", light_info->OriginalParms.type);
1353 }
1354 checkGLcall("setting FFP lights uniforms");
1355 }
1356
1357 static void shader_glsl_pointsize_uniform(const struct wined3d_context *context,
1358 const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1359 {
1360 const struct wined3d_gl_info *gl_info = context->gl_info;
1361 float min, max;
1362 float size, att[3];
1363
1364 get_pointsize_minmax(context, state, &min, &max);
1365
1366 GL_EXTCALL(glUniform1f(prog->vs.pointsize_min_location, min));
1367 checkGLcall("glUniform1f");
1368 GL_EXTCALL(glUniform1f(prog->vs.pointsize_max_location, max));
1369 checkGLcall("glUniform1f");
1370
1371 get_pointsize(context, state, &size, att);
1372
1373 GL_EXTCALL(glUniform1f(prog->vs.pointsize_location, size));
1374 checkGLcall("glUniform1f");
1375 GL_EXTCALL(glUniform1f(prog->vs.pointsize_c_att_location, att[0]));
1376 checkGLcall("glUniform1f");
1377 GL_EXTCALL(glUniform1f(prog->vs.pointsize_l_att_location, att[1]));
1378 checkGLcall("glUniform1f");
1379 GL_EXTCALL(glUniform1f(prog->vs.pointsize_q_att_location, att[2]));
1380 checkGLcall("glUniform1f");
1381 }
1382
1383 static void shader_glsl_load_fog_uniform(const struct wined3d_context *context,
1384 const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1385 {
1386 const struct wined3d_gl_info *gl_info = context->gl_info;
1387 struct wined3d_color color;
1388 float start, end, scale;
1389 union
1390 {
1391 DWORD d;
1392 float f;
1393 } tmpvalue;
1394
1395 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_FOGCOLOR]);
1396 GL_EXTCALL(glUniform4fv(prog->ps.fog_color_location, 1, &color.r));
1397 tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY];
1398 GL_EXTCALL(glUniform1f(prog->ps.fog_density_location, tmpvalue.f));
1399 get_fog_start_end(context, state, &start, &end);
1400 scale = 1.0f / (end - start);
1401 GL_EXTCALL(glUniform1f(prog->ps.fog_end_location, end));
1402 GL_EXTCALL(glUniform1f(prog->ps.fog_scale_location, scale));
1403 checkGLcall("fog emulation uniforms");
1404 }
1405
1406 static void shader_glsl_clip_plane_uniform(const struct wined3d_context *context,
1407 const struct wined3d_state *state, unsigned int index, struct glsl_shader_prog_link *prog)
1408 {
1409 const struct wined3d_gl_info *gl_info = context->gl_info;
1410 struct wined3d_matrix matrix;
1411 struct wined3d_vec4 plane;
1412
1413 plane = state->clip_planes[index];
1414
1415 /* Clip planes are affected by the view transform in d3d for FFP draws. */
1416 if (!use_vs(state))
1417 {
1418 invert_matrix(&matrix, &state->transforms[WINED3D_TS_VIEW]);
1419 transpose_matrix(&matrix, &matrix);
1420 multiply_vector_matrix(&plane, &plane, &matrix);
1421 }
1422
1423 GL_EXTCALL(glUniform4fv(prog->vs.clip_planes_location + index, 1, &plane.x));
1424 }
1425
1426 /* Context activation is done by the caller (state handler). */
1427 static void shader_glsl_load_color_key_constant(const struct glsl_ps_program *ps,
1428 const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
1429 {
1430 struct wined3d_color float_key[2];
1431 const struct wined3d_texture *texture = state->textures[0];
1432
1433 wined3d_format_get_float_color_key(texture->resource.format, &texture->async.src_blt_color_key, float_key);
1434 GL_EXTCALL(glUniform4fv(ps->color_key_location, 2, &float_key[0].r));
1435 }
1436
1437 /* Context activation is done by the caller. */
1438 static void get_normal_matrix(struct wined3d_context *context, struct wined3d_matrix *mat, float *normal)
1439 {
1440 int i, j;
1441
1442 if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING)
1443 invert_matrix_3d(mat, mat);
1444 else
1445 invert_matrix(mat, mat);
1446 /* Tests show that singular modelview matrices are used unchanged as normal
1447 * matrices on D3D3 and older. There seems to be no clearly consistent
1448 * behavior on newer D3D versions so always follow older ddraw behavior. */
1449 for (i = 0; i < 3; ++i)
1450 for (j = 0; j < 3; ++j)
1451 normal[i * 3 + j] = (&mat->_11)[j * 4 + i];
1452 }
1453
1454 /* Context activation is done by the caller (state handler). */
1455 static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context,
1456 const struct wined3d_state *state)
1457 {
1458 const struct glsl_context_data *ctx_data = context->shader_backend_data;
1459 const struct wined3d_shader *vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
1460 const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
1461 const struct wined3d_gl_info *gl_info = context->gl_info;
1462 struct shader_glsl_priv *priv = shader_priv;
1463 float position_fixup[4];
1464 float normal[3 * 3];
1465 DWORD update_mask;
1466
1467 struct glsl_shader_prog_link *prog = ctx_data->glsl_program;
1468 UINT constant_version;
1469 int i;
1470
1471 if (!prog) {
1472 /* No GLSL program set - nothing to do. */
1473 return;
1474 }
1475 constant_version = prog->constant_version;
1476 update_mask = context->constant_update_mask & prog->constant_update_mask;
1477
1478 if (update_mask & WINED3D_SHADER_CONST_VS_F)
1479 shader_glsl_load_constants_f(vshader, gl_info, state->vs_consts_f,
1480 prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
1481
1482 if (update_mask & WINED3D_SHADER_CONST_VS_I)
1483 shader_glsl_load_constants_i(vshader, gl_info, state->vs_consts_i,
1484 prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants);
1485
1486 if (update_mask & WINED3D_SHADER_CONST_VS_B)
1487 shader_glsl_load_constantsB(vshader, gl_info, prog->vs.uniform_b_locations, state->vs_consts_b,
1488 vshader->reg_maps.boolean_constants);
1489
1490 if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES)
1491 {
1492 for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
1493 shader_glsl_clip_plane_uniform(context, state, i, prog);
1494 }
1495
1496 if (update_mask & WINED3D_SHADER_CONST_VS_POINTSIZE)
1497 shader_glsl_pointsize_uniform(context, state, prog);
1498
1499 if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP)
1500 {
1501 shader_get_position_fixup(context, state, position_fixup);
1502 if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY])
1503 GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, 1, position_fixup));
1504 else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
1505 GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup));
1506 else
1507 GL_EXTCALL(glUniform4fv(prog->vs.pos_fixup_location, 1, position_fixup));
1508 checkGLcall("glUniform4fv");
1509 }
1510
1511 if (update_mask & WINED3D_SHADER_CONST_FFP_MODELVIEW)
1512 {
1513 struct wined3d_matrix mat;
1514
1515 get_modelview_matrix(context, state, 0, &mat);
1516 GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[0], 1, FALSE, &mat._11));
1517 checkGLcall("glUniformMatrix4fv");
1518
1519 get_normal_matrix(context, &mat, normal);
1520 GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[0], 1, FALSE, normal));
1521 checkGLcall("glUniformMatrix3fv");
1522 }
1523
1524 if (update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND)
1525 {
1526 struct wined3d_matrix mat;
1527
1528 for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i)
1529 {
1530 if (prog->vs.modelview_matrix_location[i] == -1)
1531 break;
1532 if (!(update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i)))
1533 continue;
1534
1535 get_modelview_matrix(context, state, i, &mat);
1536 GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11));
1537 checkGLcall("glUniformMatrix4fv");
1538
1539 get_normal_matrix(context, &mat, normal);
1540 GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[i], 1, FALSE, normal));
1541 checkGLcall("glUniformMatrix3fv");
1542 }
1543 }
1544
1545 if (update_mask & WINED3D_SHADER_CONST_FFP_PROJ)
1546 {
1547 struct wined3d_matrix projection;
1548
1549 get_projection_matrix(context, state, &projection);
1550 GL_EXTCALL(glUniformMatrix4fv(prog->vs.projection_matrix_location, 1, FALSE, &projection._11));
1551 checkGLcall("glUniformMatrix4fv");
1552 }
1553
1554 if (update_mask & WINED3D_SHADER_CONST_FFP_TEXMATRIX)
1555 {
1556 for (i = 0; i < MAX_TEXTURES; ++i)
1557 shader_glsl_ffp_vertex_texmatrix_uniform(context, state, i, prog);
1558 }
1559
1560 if (update_mask & WINED3D_SHADER_CONST_FFP_MATERIAL)
1561 shader_glsl_ffp_vertex_material_uniform(context, state, prog);
1562
1563 if (update_mask & WINED3D_SHADER_CONST_FFP_LIGHTS)
1564 {
1565 unsigned int point_idx, spot_idx, directional_idx, parallel_point_idx;
1566 DWORD point_count = 0;
1567 DWORD spot_count = 0;
1568 DWORD directional_count = 0;
1569 DWORD parallel_point_count = 0;
1570
1571 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
1572 {
1573 if (!state->lights[i])
1574 continue;
1575
1576 switch (state->lights[i]->OriginalParms.type)
1577 {
1578 case WINED3D_LIGHT_POINT:
1579 ++point_count;
1580 break;
1581 case WINED3D_LIGHT_SPOT:
1582 ++spot_count;
1583 break;
1584 case WINED3D_LIGHT_DIRECTIONAL:
1585 ++directional_count;
1586 break;
1587 case WINED3D_LIGHT_PARALLELPOINT:
1588 ++parallel_point_count;
1589 break;
1590 default:
1591 FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type);
1592 break;
1593 }
1594 }
1595 point_idx = 0;
1596 spot_idx = point_idx + point_count;
1597 directional_idx = spot_idx + spot_count;
1598 parallel_point_idx = directional_idx + directional_count;
1599
1600 shader_glsl_ffp_vertex_lightambient_uniform(context, state, prog);
1601 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
1602 {
1603 const struct wined3d_light_info *light_info = state->lights[i];
1604 unsigned int idx;
1605
1606 if (!light_info)
1607 continue;
1608
1609 switch (light_info->OriginalParms.type)
1610 {
1611 case WINED3D_LIGHT_POINT:
1612 idx = point_idx++;
1613 break;
1614 case WINED3D_LIGHT_SPOT:
1615 idx = spot_idx++;
1616 break;
1617 case WINED3D_LIGHT_DIRECTIONAL:
1618 idx = directional_idx++;
1619 break;
1620 case WINED3D_LIGHT_PARALLELPOINT:
1621 idx = parallel_point_idx++;
1622 break;
1623 default:
1624 FIXME("Unhandled light type %#x.\n", light_info->OriginalParms.type);
1625 continue;
1626 }
1627 shader_glsl_ffp_vertex_light_uniform(context, state, idx, light_info, prog);
1628 }
1629 }
1630
1631 if (update_mask & WINED3D_SHADER_CONST_PS_F)
1632 shader_glsl_load_constants_f(pshader, gl_info, state->ps_consts_f,
1633 prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
1634
1635 if (update_mask & WINED3D_SHADER_CONST_PS_I)
1636 shader_glsl_load_constants_i(pshader, gl_info, state->ps_consts_i,
1637 prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants);
1638
1639 if (update_mask & WINED3D_SHADER_CONST_PS_B)
1640 shader_glsl_load_constantsB(pshader, gl_info, prog->ps.uniform_b_locations, state->ps_consts_b,
1641 pshader->reg_maps.boolean_constants);
1642
1643 if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV)
1644 {
1645 for (i = 0; i < MAX_TEXTURES; ++i)
1646 {
1647 if (prog->ps.bumpenv_mat_location[i] == -1)
1648 continue;
1649
1650 GL_EXTCALL(glUniformMatrix2fv(prog->ps.bumpenv_mat_location[i], 1, 0,
1651 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00]));
1652
1653 if (prog->ps.bumpenv_lum_scale_location[i] != -1)
1654 {
1655 GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_scale_location[i], 1,
1656 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE]));
1657 GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_offset_location[i], 1,
1658 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET]));
1659 }
1660 }
1661
1662 checkGLcall("bump env uniforms");
1663 }
1664
1665 if (update_mask & WINED3D_SHADER_CONST_PS_Y_CORR)
1666 {
1667 const struct wined3d_vec4 correction_params =
1668 {
1669 /* Position is relative to the framebuffer, not the viewport. */
1670 context->render_offscreen ? 0.0f : (float)state->fb->render_targets[0]->height,
1671 context->render_offscreen ? 1.0f : -1.0f,
1672 0.0f,
1673 0.0f,
1674 };
1675
1676 GL_EXTCALL(glUniform4fv(prog->ps.ycorrection_location, 1, &correction_params.x));
1677 }
1678
1679 if (update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP)
1680 shader_glsl_load_np2fixup_constants(&prog->ps, gl_info, state);
1681 if (update_mask & WINED3D_SHADER_CONST_FFP_COLOR_KEY)
1682 shader_glsl_load_color_key_constant(&prog->ps, gl_info, state);
1683
1684 if (update_mask & WINED3D_SHADER_CONST_FFP_PS)
1685 {
1686 struct wined3d_color color;
1687
1688 if (prog->ps.tex_factor_location != -1)
1689 {
1690 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_TEXTUREFACTOR]);
1691 GL_EXTCALL(glUniform4fv(prog->ps.tex_factor_location, 1, &color.r));
1692 }
1693
1694 if (state->render_states[WINED3D_RS_SPECULARENABLE])
1695 GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 1.0f, 1.0f, 1.0f, 0.0f));
1696 else
1697 GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 0.0f, 0.0f, 0.0f, 0.0f));
1698
1699 for (i = 0; i < MAX_TEXTURES; ++i)
1700 {
1701 if (prog->ps.tss_constant_location[i] == -1)
1702 continue;
1703
1704 wined3d_color_from_d3dcolor(&color, state->texture_states[i][WINED3D_TSS_CONSTANT]);
1705 GL_EXTCALL(glUniform4fv(prog->ps.tss_constant_location[i], 1, &color.r));
1706 }
1707
1708 checkGLcall("fixed function uniforms");
1709 }
1710
1711 if (update_mask & WINED3D_SHADER_CONST_PS_FOG)
1712 shader_glsl_load_fog_uniform(context, state, prog);
1713
1714 if (update_mask & WINED3D_SHADER_CONST_PS_ALPHA_TEST)
1715 {
1716 float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f;
1717
1718 GL_EXTCALL(glUniform1f(prog->ps.alpha_test_ref_location, ref));
1719 checkGLcall("alpha test emulation uniform");
1720 }
1721
1722 if (priv->next_constant_version == UINT_MAX)
1723 {
1724 TRACE("Max constant version reached, resetting to 0.\n");
1725 wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL);
1726 priv->next_constant_version = 1;
1727 }
1728 else
1729 {
1730 prog->constant_version = priv->next_constant_version++;
1731 }
1732 }
1733
1734 static void update_heap_entry(struct constant_heap *heap, unsigned int idx, DWORD new_version)
1735 {
1736 struct constant_entry *entries = heap->entries;
1737 unsigned int *positions = heap->positions;
1738 unsigned int heap_idx, parent_idx;
1739
1740 if (!heap->contained[idx])
1741 {
1742 heap_idx = heap->size++;
1743 heap->contained[idx] = TRUE;
1744 }
1745 else
1746 {
1747 heap_idx = positions[idx];
1748 }
1749
1750 while (heap_idx > 1)
1751 {
1752 parent_idx = heap_idx >> 1;
1753
1754 if (new_version <= entries[parent_idx].version) break;
1755
1756 entries[heap_idx] = entries[parent_idx];
1757 positions[entries[parent_idx].idx] = heap_idx;
1758 heap_idx = parent_idx;
1759 }
1760
1761 entries[heap_idx].version = new_version;
1762 entries[heap_idx].idx = idx;
1763 positions[idx] = heap_idx;
1764 }
1765
1766 static void shader_glsl_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count)
1767 {
1768 struct shader_glsl_priv *priv = device->shader_priv;
1769 struct constant_heap *heap = &priv->vconst_heap;
1770 UINT i;
1771
1772 for (i = start; i < count + start; ++i)
1773 {
1774 update_heap_entry(heap, i, priv->next_constant_version);
1775 }
1776 }
1777
1778 static void shader_glsl_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count)
1779 {
1780 struct shader_glsl_priv *priv = device->shader_priv;
1781 struct constant_heap *heap = &priv->pconst_heap;
1782 UINT i;
1783
1784 for (i = start; i < count + start; ++i)
1785 {
1786 update_heap_entry(heap, i, priv->next_constant_version);
1787 }
1788 }
1789
1790 static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info)
1791 {
1792 unsigned int ret = gl_info->limits.glsl_varyings / 4;
1793 /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */
1794 if(shader_major > 3) return ret;
1795
1796 /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */
1797 if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1;
1798 return ret;
1799 }
1800
1801 static BOOL needs_legacy_glsl_syntax(const struct wined3d_gl_info *gl_info)
1802 {
1803 return gl_info->glsl_version < MAKEDWORD_VERSION(1, 30);
1804 }
1805
1806 static BOOL shader_glsl_use_explicit_attrib_location(const struct wined3d_gl_info *gl_info)
1807 {
1808 return gl_info->supported[ARB_EXPLICIT_ATTRIB_LOCATION]
1809 && shader_glsl_use_layout_qualifier(gl_info) && !needs_legacy_glsl_syntax(gl_info);
1810 }
1811
1812 static BOOL shader_glsl_use_interface_blocks(const struct wined3d_gl_info *gl_info)
1813 {
1814 return shader_glsl_get_version(gl_info) >= 150;
1815 }
1816
1817 static const char *get_attribute_keyword(const struct wined3d_gl_info *gl_info)
1818 {
1819 return needs_legacy_glsl_syntax(gl_info) ? "attribute" : "in";
1820 }
1821
1822 static void PRINTF_ATTR(4, 5) declare_in_varying(const struct wined3d_gl_info *gl_info,
1823 struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...)
1824 {
1825 va_list args;
1826 int ret;
1827
1828 shader_addline(buffer, "%s%s ", flat ? "flat " : "",
1829 needs_legacy_glsl_syntax(gl_info) ? "varying" : "in");
1830 for (;;)
1831 {
1832 va_start(args, format);
1833 ret = shader_vaddline(buffer, format, args);
1834 va_end(args);
1835 if (!ret)
1836 return;
1837 if (!string_buffer_resize(buffer, ret))
1838 return;
1839 }
1840 }
1841
1842 static void PRINTF_ATTR(4, 5) declare_out_varying(const struct wined3d_gl_info *gl_info,
1843 struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...)
1844 {
1845 va_list args;
1846 int ret;
1847
1848 shader_addline(buffer, "%s%s ", flat ? "flat " : "",
1849 needs_legacy_glsl_syntax(gl_info) ? "varying" : "out");
1850 for (;;)
1851 {
1852 va_start(args, format);
1853 ret = shader_vaddline(buffer, format, args);
1854 va_end(args);
1855 if (!ret)
1856 return;
1857 if (!string_buffer_resize(buffer, ret))
1858 return;
1859 }
1860 }
1861
1862 static const char *shader_glsl_shader_input_name(const struct wined3d_gl_info *gl_info)
1863 {
1864 return shader_glsl_use_interface_blocks(gl_info) ? "shader_in.reg" : "ps_link";
1865 }
1866
1867 static const char *shader_glsl_shader_output_name(const struct wined3d_gl_info *gl_info)
1868 {
1869 return shader_glsl_use_interface_blocks(gl_info) ? "shader_out.reg" : "ps_link";
1870 }
1871
1872 static const char *shader_glsl_interpolation_qualifiers(enum wined3d_shader_interpolation_mode mode)
1873 {
1874 switch (mode)
1875 {
1876 case WINED3DSIM_CONSTANT:
1877 return "flat";
1878 case WINED3DSIM_LINEAR_NOPERSPECTIVE:
1879 return "noperspective";
1880 default:
1881 FIXME("Unhandled interpolation mode %#x.\n", mode);
1882 case WINED3DSIM_NONE:
1883 case WINED3DSIM_LINEAR:
1884 return "";
1885 }
1886 }
1887
1888 static enum wined3d_shader_interpolation_mode wined3d_extract_interpolation_mode(
1889 const DWORD *packed_interpolation_mode, unsigned int register_idx)
1890 {
1891 return wined3d_extract_bits(packed_interpolation_mode,
1892 register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT);
1893 }
1894
1895 static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_info,
1896 struct wined3d_string_buffer *buffer, unsigned int element_count,
1897 const DWORD *interpolation_mode, BOOL unroll)
1898 {
1899 enum wined3d_shader_interpolation_mode mode;
1900 unsigned int i;
1901
1902 if (shader_glsl_use_interface_blocks(gl_info))
1903 {
1904 if (unroll)
1905 {
1906 shader_addline(buffer, "in shader_in_out {\n");
1907 for (i = 0; i < element_count; ++i)
1908 {
1909 mode = wined3d_extract_interpolation_mode(interpolation_mode, i);
1910 shader_addline(buffer, "%s vec4 reg%u;\n", shader_glsl_interpolation_qualifiers(mode), i);
1911 }
1912 shader_addline(buffer, "} shader_in;\n");
1913 }
1914 else
1915 {
1916 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in;\n", element_count);
1917 }
1918 }
1919 else
1920 {
1921 declare_in_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count);
1922 }
1923 }
1924
1925 static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_info,
1926 struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup,
1927 const DWORD *interpolation_mode)
1928 {
1929 enum wined3d_shader_interpolation_mode mode;
1930 unsigned int i;
1931
1932 if (shader_glsl_use_interface_blocks(gl_info))
1933 {
1934 if (rasterizer_setup)
1935 {
1936 shader_addline(buffer, "out shader_in_out {\n");
1937 for (i = 0; i < element_count; ++i)
1938 {
1939 const char *interpolation_qualifiers = "";
1940 if (needs_interpolation_qualifiers_for_shader_outputs(gl_info))
1941 {
1942 mode = wined3d_extract_interpolation_mode(interpolation_mode, i);
1943 interpolation_qualifiers = shader_glsl_interpolation_qualifiers(mode);
1944 }
1945 shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i);
1946 }
1947 shader_addline(buffer, "} shader_out;\n");
1948 }
1949 else
1950 {
1951 shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out;\n", element_count);
1952 }
1953 }
1954 else
1955 {
1956 declare_out_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count);
1957 }
1958 }
1959
1960 static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
1961 {
1962 switch (primitive_type)
1963 {
1964 case WINED3D_PT_POINTLIST:
1965 return "points";
1966
1967 case WINED3D_PT_LINELIST:
1968 return "lines";
1969
1970 case WINED3D_PT_LINESTRIP:
1971 return "line_strip";
1972
1973 case WINED3D_PT_TRIANGLELIST:
1974 return "triangles";
1975
1976 case WINED3D_PT_TRIANGLESTRIP:
1977 return "triangle_strip";
1978
1979 case WINED3D_PT_LINELIST_ADJ:
1980 return "lines_adjacency";
1981
1982 case WINED3D_PT_TRIANGLELIST_ADJ:
1983 return "triangles_adjacency";
1984
1985 default:
1986 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type));
1987 return "";
1988 }
1989 }
1990
1991 static BOOL glsl_is_color_reg_read(const struct wined3d_shader *shader, unsigned int idx)
1992 {
1993 const struct wined3d_shader_signature *input_signature = &shader->input_signature;
1994 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
1995 DWORD input_reg_used = shader->u.ps.input_reg_used;
1996 unsigned int i;
1997
1998 if (reg_maps->shader_version.major < 3)
1999 return input_reg_used & (1u << idx);
2000
2001 for (i = 0; i < input_signature->element_count; ++i)
2002 {
2003 const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
2004
2005 if (!(reg_maps->input_registers & (1u << input->register_idx)))
2006 continue;
2007
2008 if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_COLOR)
2009 && input->semantic_idx == idx)
2010 return input_reg_used & (1u << input->register_idx);
2011 }
2012 return FALSE;
2013 }
2014
2015 static BOOL glsl_is_shadow_sampler(const struct wined3d_shader *shader,
2016 const struct ps_compile_args *ps_args, unsigned int resource_idx, unsigned int sampler_idx)
2017 {
2018 const struct wined3d_shader_version *version = &shader->reg_maps.shader_version;
2019
2020 if (version->major >= 4)
2021 return shader->reg_maps.sampler_comparison_mode & (1u << sampler_idx);
2022 else
2023 return version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1u << resource_idx));
2024 }
2025
2026 static void shader_glsl_declare_typed_vertex_attribute(struct wined3d_string_buffer *buffer,
2027 const struct wined3d_gl_info *gl_info, const char *vector_type, const char *scalar_type,
2028 unsigned int index)
2029 {
2030 shader_addline(buffer, "%s %s4 vs_in_%s%u;\n",
2031 get_attribute_keyword(gl_info), vector_type, scalar_type, index);
2032 shader_addline(buffer, "vec4 vs_in%u = %sBitsToFloat(vs_in_%s%u);\n",
2033 index, scalar_type, scalar_type, index);
2034 }
2035
2036 static void shader_glsl_declare_generic_vertex_attribute(struct wined3d_string_buffer *buffer,
2037 const struct wined3d_gl_info *gl_info, const struct wined3d_shader_signature_element *e)
2038 {
2039 unsigned int index = e->register_idx;
2040
2041 if (e->sysval_semantic == WINED3D_SV_VERTEX_ID)
2042 {
2043 shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_VertexID), 0.0, 0.0, 0.0);\n",
2044 index);
2045 return;
2046 }
2047 if (e->sysval_semantic == WINED3D_SV_INSTANCE_ID)
2048 {
2049 shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_InstanceID), 0.0, 0.0, 0.0);\n",
2050 index);
2051 return;
2052 }
2053 if (e->sysval_semantic && e->sysval_semantic != WINED3D_SV_POSITION)
2054 FIXME("Unhandled sysval semantic %#x.\n", e->sysval_semantic);
2055
2056 if (shader_glsl_use_explicit_attrib_location(gl_info))
2057 shader_addline(buffer, "layout(location = %u) ", index);
2058
2059 switch (e->component_type)
2060 {
2061 case WINED3D_TYPE_UINT:
2062 shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "uvec", "uint", index);
2063 break;
2064 case WINED3D_TYPE_INT:
2065 shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "ivec", "int", index);
2066 break;
2067
2068 default:
2069 FIXME("Unhandled type %#x.\n", e->component_type);
2070 /* Fall through. */
2071 case WINED3D_TYPE_UNKNOWN:
2072 case WINED3D_TYPE_FLOAT:
2073 shader_addline(buffer, "%s vec4 vs_in%u;\n", get_attribute_keyword(gl_info), index);
2074 break;
2075 }
2076 }
2077
2078 /** Generate the variable & register declarations for the GLSL output target */
2079 static void shader_generate_glsl_declarations(const struct wined3d_context *context,
2080 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader,
2081 const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv)
2082 {
2083 const struct wined3d_shader_version *version = &reg_maps->shader_version;
2084 const struct vs_compile_args *vs_args = ctx_priv->cur_vs_args;
2085 const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args;
2086 const struct wined3d_gl_info *gl_info = context->gl_info;
2087 const struct wined3d_shader_indexable_temp *idx_temp_reg;
2088 unsigned int uniform_block_base, uniform_block_count;
2089 const struct wined3d_shader_lconst *lconst;
2090 const char *prefix;
2091 unsigned int i;
2092 DWORD map;
2093
2094 prefix = shader_glsl_get_prefix(version->type);
2095
2096 /* Prototype the subroutines */
2097 for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i)
2098 {
2099 if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i);
2100 }
2101
2102 /* Declare the constants (aka uniforms) */
2103 if (shader->limits->constant_float > 0)
2104 {
2105 unsigned max_constantsF;
2106
2107 /* Unless the shader uses indirect addressing, always declare the
2108 * maximum array size and ignore that we need some uniforms privately.
2109 * E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup
2110 * and immediate values, still declare VC[256]. If the shader needs
2111 * more uniforms than we have it won't work in any case. If it uses
2112 * less, the compiler will figure out which uniforms are really used
2113 * and strip them out. This allows a shader to use c255 on a dx9 card,
2114 * as long as it doesn't also use all the other constants.
2115 *
2116 * If the shader uses indirect addressing the compiler must assume
2117 * that all declared uniforms are used. In this case, declare only the
2118 * amount that we're assured to have.
2119 *
2120 * Thus we run into problems in these two cases:
2121 * 1) The shader really uses more uniforms than supported.
2122 * 2) The shader uses indirect addressing, less constants than
2123 * supported, but uses a constant index > #supported consts. */
2124 if (version->type == WINED3D_SHADER_TYPE_PIXEL)
2125 {
2126 /* No indirect addressing here. */
2127 max_constantsF = gl_info->limits.glsl_ps_float_constants;
2128 }
2129 else
2130 {
2131 if (reg_maps->usesrelconstF)
2132 {
2133 /* Subtract the other potential uniforms from the max
2134 * available (bools, ints, and 1 row of projection matrix).
2135 * Subtract another uniform for immediate values, which have
2136 * to be loaded via uniform by the driver as well. The shader
2137 * code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex
2138 * shader code, so one vec4 should be enough. (Unfortunately
2139 * the Nvidia driver doesn't store 128 and -128 in one float).
2140 *
2141 * Writing gl_ClipVertex requires one uniform for each
2142 * clipplane as well. */
2143 max_constantsF = gl_info->limits.glsl_vs_float_constants - 3;
2144 if (vs_args->clip_enabled)
2145 max_constantsF -= gl_info->limits.user_clip_distances;
2146 max_constantsF -= wined3d_popcount(reg_maps->integer_constants);
2147 /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
2148 * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
2149 * for now take this into account when calculating the number of available constants
2150 */
2151 max_constantsF -= wined3d_popcount(reg_maps->boolean_constants);
2152 /* Set by driver quirks in directx.c */
2153 max_constantsF -= gl_info->reserved_glsl_constants;
2154
2155 if (max_constantsF < shader->limits->constant_float)
2156 {
2157 static unsigned int once;
2158
2159 if (!once++)
2160 ERR_(winediag)("The hardware does not support enough uniform components to run this shader,"
2161 " it may not render correctly.\n");
2162 else
2163 WARN("The hardware does not support enough uniform components to run this shader.\n");
2164 }
2165 }
2166 else
2167 {
2168 max_constantsF = gl_info->limits.glsl_vs_float_constants;
2169 }
2170 }
2171 max_constantsF = min(shader->limits->constant_float, max_constantsF);
2172 shader_addline(buffer, "uniform vec4 %s_c[%u];\n", prefix, max_constantsF);
2173 }
2174
2175 /* Always declare the full set of constants, the compiler can remove the
2176 * unused ones because d3d doesn't (yet) support indirect int and bool
2177 * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */
2178 if (shader->limits->constant_int > 0 && reg_maps->integer_constants)
2179 shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits->constant_int);
2180
2181 if (shader->limits->constant_bool > 0 && reg_maps->boolean_constants)
2182 shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits->constant_bool);
2183
2184 /* Declare immediate constant buffer */
2185 if (reg_maps->icb)
2186 shader_addline(buffer, "uniform vec4 %s_icb[%u];\n", prefix, reg_maps->icb->vec4_count);
2187
2188 /* Declare constant buffers */
2189 wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, version->type,
2190 &uniform_block_base, &uniform_block_count);
2191 for (i = 0; i < min(uniform_block_count, WINED3D_MAX_CBS); ++i)
2192 {
2193 if (reg_maps->cb_sizes[i])
2194 {
2195 shader_addline(buffer, "layout(std140");
2196 if (shader_glsl_use_layout_binding_qualifier(gl_info))
2197 shader_addline(buffer, ", binding = %u", uniform_block_base + i);
2198 shader_addline(buffer, ") uniform block_%s_cb%u { vec4 %s_cb%u[%u]; };\n",
2199 prefix, i, prefix, i, reg_maps->cb_sizes[i]);
2200 }
2201 }
2202
2203 /* Declare texture samplers */
2204 for (i = 0; i < reg_maps->sampler_map.count; ++i)
2205 {
2206 struct wined3d_shader_sampler_map_entry *entry;
2207 const char *sampler_type_prefix, *sampler_type;
2208 BOOL shadow_sampler, tex_rect;
2209
2210 entry = &reg_maps->sampler_map.entries[i];
2211
2212 if (entry->resource_idx >= ARRAY_SIZE(reg_maps->resource_info))
2213 {
2214 ERR("Invalid resource index %u.\n", entry->resource_idx);
2215 continue;
2216 }
2217
2218 switch (reg_maps->resource_info[entry->resource_idx].data_type)
2219 {
2220 case WINED3D_DATA_FLOAT:
2221 case WINED3D_DATA_UNORM:
2222 case WINED3D_DATA_SNORM:
2223 sampler_type_prefix = "";
2224 break;
2225
2226 case WINED3D_DATA_INT:
2227 sampler_type_prefix = "i";
2228 break;
2229
2230 case WINED3D_DATA_UINT:
2231 sampler_type_prefix = "u";
2232 break;
2233
2234 default:
2235 sampler_type_prefix = "";
2236 ERR("Unhandled resource data type %#x.\n", reg_maps->resource_info[i].data_type);
2237 break;
2238 }
2239
2240 shadow_sampler = glsl_is_shadow_sampler(shader, ps_args, entry->resource_idx, entry->sampler_idx);
2241 switch (reg_maps->resource_info[entry->resource_idx].type)
2242 {
2243 case WINED3D_SHADER_RESOURCE_BUFFER:
2244 sampler_type = "samplerBuffer";
2245 break;
2246
2247 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2248 if (shadow_sampler)
2249 sampler_type = "sampler1DShadow";
2250 else
2251 sampler_type = "sampler1D";
2252 break;
2253
2254 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2255 tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL
2256 && (ps_args->np2_fixup & (1u << entry->resource_idx))
2257 && gl_info->supported[ARB_TEXTURE_RECTANGLE];
2258 if (shadow_sampler)
2259 {
2260 if (tex_rect)
2261 sampler_type = "sampler2DRectShadow";
2262 else
2263 sampler_type = "sampler2DShadow";
2264 }
2265 else
2266 {
2267 if (tex_rect)
2268 sampler_type = "sampler2DRect";
2269 else
2270 sampler_type = "sampler2D";
2271 }
2272 break;
2273
2274 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2275 if (shadow_sampler)
2276 FIXME("Unsupported 3D shadow sampler.\n");
2277 sampler_type = "sampler3D";
2278 break;
2279
2280 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2281 if (shadow_sampler)
2282 sampler_type = "samplerCubeShadow";
2283 else
2284 sampler_type = "samplerCube";
2285 break;
2286
2287 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
2288 if (shadow_sampler)
2289 sampler_type = "sampler1DArrayShadow";
2290 else
2291 sampler_type = "sampler1DArray";
2292 break;
2293
2294 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2295 if (shadow_sampler)
2296 sampler_type = "sampler2DArrayShadow";
2297 else
2298 sampler_type = "sampler2DArray";
2299 break;
2300
2301 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY:
2302 if (shadow_sampler)
2303 sampler_type = "samplerCubeArrayShadow";
2304 else
2305 sampler_type = "samplerCubeArray";
2306 break;
2307
2308 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2309 sampler_type = "sampler2DMS";
2310 break;
2311
2312 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2313 sampler_type = "sampler2DMSArray";
2314 break;
2315
2316 default:
2317 sampler_type = "unsupported_sampler";
2318 FIXME("Unhandled resource type %#x.\n", reg_maps->resource_info[entry->resource_idx].type);
2319 break;
2320 }
2321
2322 if (shader_glsl_use_layout_binding_qualifier(gl_info))
2323 shader_glsl_append_sampler_binding_qualifier(buffer, context, version, entry->bind_idx);
2324 shader_addline(buffer, "uniform %s%s %s_sampler%u;\n",
2325 sampler_type_prefix, sampler_type, prefix, entry->bind_idx);
2326 }
2327
2328 /* Declare images */
2329 for (i = 0; i < ARRAY_SIZE(reg_maps->uav_resource_info); ++i)
2330 {
2331 const char *image_type_prefix, *image_type, *read_format;
2332
2333 if (!reg_maps->uav_resource_info[i].type)
2334 continue;
2335
2336 switch (reg_maps->uav_resource_info[i].data_type)
2337 {
2338 case WINED3D_DATA_FLOAT:
2339 case WINED3D_DATA_UNORM:
2340 case WINED3D_DATA_SNORM:
2341 image_type_prefix = "";
2342 read_format = "r32f";
2343 break;
2344
2345 case WINED3D_DATA_INT:
2346 image_type_prefix = "i";
2347 read_format = "r32i";
2348 break;
2349
2350 case WINED3D_DATA_UINT:
2351 image_type_prefix = "u";
2352 read_format = "r32ui";
2353 break;
2354
2355 default:
2356 image_type_prefix = "";
2357 read_format = "";
2358 ERR("Unhandled resource data type %#x.\n", reg_maps->uav_resource_info[i].data_type);
2359 break;
2360 }
2361
2362 switch (reg_maps->uav_resource_info[i].type)
2363 {
2364 case WINED3D_SHADER_RESOURCE_BUFFER:
2365 image_type = "imageBuffer";
2366 break;
2367
2368 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2369 image_type = "image2D";
2370 break;
2371
2372 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2373 image_type = "image3D";
2374 break;
2375
2376 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2377 image_type = "image2DArray";
2378 break;
2379
2380 default:
2381 image_type = "unsupported_image";
2382 FIXME("Unhandled resource type %#x.\n", reg_maps->uav_resource_info[i].type);
2383 break;
2384 }
2385
2386 if (shader_glsl_use_layout_binding_qualifier(gl_info))
2387 shader_addline(buffer, "layout(binding = %u)\n", i);
2388 if (reg_maps->uav_read_mask & (1u << i))
2389 shader_addline(buffer, "layout(%s) uniform %s%s %s_image%u;\n",
2390 read_format, image_type_prefix, image_type, prefix, i);
2391 else
2392 shader_addline(buffer, "writeonly uniform %s%s %s_image%u;\n",
2393 image_type_prefix, image_type, prefix, i);
2394
2395 if (reg_maps->uav_counter_mask & (1u << i))
2396 shader_addline(buffer, "layout(binding = %u) uniform atomic_uint %s_counter%u;\n",
2397 i, prefix, i);
2398 }
2399
2400 /* Declare address variables */
2401 for (i = 0, map = reg_maps->address; map; map >>= 1, ++i)
2402 {
2403 if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i);
2404 }
2405
2406 /* Declare output register temporaries */
2407 if (shader->limits->packed_output)
2408 shader_addline(buffer, "vec4 %s_out[%u];\n", prefix, shader->limits->packed_output);
2409
2410 /* Declare temporary variables */
2411 if (reg_maps->temporary_count)
2412 {
2413 for (i = 0; i < reg_maps->temporary_count; ++i)
2414 shader_addline(buffer, "vec4 R%u;\n", i);
2415 }
2416 else if (version->major < 4)
2417 {
2418 for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
2419 {
2420 if (map & 1)
2421 shader_addline(buffer, "vec4 R%u;\n", i);
2422 }
2423 }
2424
2425 /* Declare indexable temporary variables */
2426 LIST_FOR_EACH_ENTRY(idx_temp_reg, &reg_maps->indexable_temps, struct wined3d_shader_indexable_temp, entry)
2427 {
2428 if (idx_temp_reg->component_count != 4)
2429 FIXME("Ignoring component count %u.\n", idx_temp_reg->component_count);
2430 shader_addline(buffer, "vec4 X%u[%u];\n", idx_temp_reg->register_idx, idx_temp_reg->register_size);
2431 }
2432
2433 /* Declare loop registers aLx */
2434 if (version->major < 4)
2435 {
2436 for (i = 0; i < reg_maps->loop_depth; ++i)
2437 {
2438 shader_addline(buffer, "int aL%u;\n", i);
2439 shader_addline(buffer, "int tmpInt%u;\n", i);
2440 }
2441 }
2442
2443 /* Temporary variables for matrix operations */
2444 shader_addline(buffer, "vec4 tmp0;\n");
2445 shader_addline(buffer, "vec4 tmp1;\n");
2446
2447 if (!shader->load_local_constsF)
2448 {
2449 LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
2450 {
2451 shader_addline(buffer, "const vec4 %s_lc%u = ", prefix, lconst->idx);
2452 shader_glsl_append_imm_vec4(buffer, (const float *)lconst->value);
2453 shader_addline(buffer, ";\n");
2454 }
2455 }
2456 }
2457
2458 /* Prototypes */
2459 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
2460 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src);
2461
2462 /** Used for opcode modifiers - They multiply the result by the specified amount */
2463 static const char * const shift_glsl_tab[] = {
2464 "", /* 0 (none) */
2465 "2.0 * ", /* 1 (x2) */
2466 "4.0 * ", /* 2 (x4) */
2467 "8.0 * ", /* 3 (x8) */
2468 "16.0 * ", /* 4 (x16) */
2469 "32.0 * ", /* 5 (x32) */
2470 "", /* 6 (x64) */
2471 "", /* 7 (x128) */
2472 "", /* 8 (d256) */
2473 "", /* 9 (d128) */
2474 "", /* 10 (d64) */
2475 "", /* 11 (d32) */
2476 "0.0625 * ", /* 12 (d16) */
2477 "0.125 * ", /* 13 (d8) */
2478 "0.25 * ", /* 14 (d4) */
2479 "0.5 * " /* 15 (d2) */
2480 };
2481
2482 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */
2483 static void shader_glsl_gen_modifier(enum wined3d_shader_src_modifier src_modifier,
2484 const char *in_reg, const char *in_regswizzle, char *out_str)
2485 {
2486 switch (src_modifier)
2487 {
2488 case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */
2489 case WINED3DSPSM_DW:
2490 case WINED3DSPSM_NONE:
2491 sprintf(out_str, "%s%s", in_reg, in_regswizzle);
2492 break;
2493 case WINED3DSPSM_NEG:
2494 sprintf(out_str, "-%s%s", in_reg, in_regswizzle);
2495 break;
2496 case WINED3DSPSM_NOT:
2497 sprintf(out_str, "!%s%s", in_reg, in_regswizzle);
2498 break;
2499 case WINED3DSPSM_BIAS:
2500 sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
2501 break;
2502 case WINED3DSPSM_BIASNEG:
2503 sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
2504 break;
2505 case WINED3DSPSM_SIGN:
2506 sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
2507 break;
2508 case WINED3DSPSM_SIGNNEG:
2509 sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
2510 break;
2511 case WINED3DSPSM_COMP:
2512 sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle);
2513 break;
2514 case WINED3DSPSM_X2:
2515 sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle);
2516 break;
2517 case WINED3DSPSM_X2NEG:
2518 sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle);
2519 break;
2520 case WINED3DSPSM_ABS:
2521 sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle);
2522 break;
2523 case WINED3DSPSM_ABSNEG:
2524 sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle);
2525 break;
2526 default:
2527 FIXME("Unhandled modifier %u\n", src_modifier);
2528 sprintf(out_str, "%s%s", in_reg, in_regswizzle);
2529 }
2530 }
2531
2532 static void shader_glsl_fixup_scalar_register_variable(char *register_name,
2533 const char *glsl_variable, const struct wined3d_gl_info *gl_info)
2534 {
2535 /* The ARB_shading_language_420pack extension allows swizzle operations on
2536 * scalars. */
2537 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK])
2538 sprintf(register_name, "%s", glsl_variable);
2539 else
2540 sprintf(register_name, "ivec2(%s, 0)", glsl_variable);
2541 }
2542
2543 /** Writes the GLSL variable name that corresponds to the register that the
2544 * DX opcode parameter is trying to access */
2545 static void shader_glsl_get_register_name(const struct wined3d_shader_register *reg,
2546 enum wined3d_data_type data_type, char *register_name, BOOL *is_color,
2547 const struct wined3d_shader_instruction *ins)
2548 {
2549 /* oPos, oFog and oPts in D3D */
2550 static const char * const hwrastout_reg_names[] = {"vs_out[10]", "vs_out[11].x", "vs_out[11].y"};
2551
2552 const struct wined3d_shader *shader = ins->ctx->shader;
2553 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
2554 const struct wined3d_shader_version *version = &reg_maps->shader_version;
2555 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
2556 const char *prefix = shader_glsl_get_prefix(version->type);
2557 struct glsl_src_param rel_param0, rel_param1;
2558 char imm_str[4][17];
2559
2560 if (reg->idx[0].offset != ~0U && reg->idx[0].rel_addr)
2561 shader_glsl_add_src_param(ins, reg->idx[0].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param0);
2562 if (reg->idx[1].offset != ~0U && reg->idx[1].rel_addr)
2563 shader_glsl_add_src_param(ins, reg->idx[1].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param1);
2564 *is_color = FALSE;
2565
2566 switch (reg->type)
2567 {
2568 case WINED3DSPR_TEMP:
2569 sprintf(register_name, "R%u", reg->idx[0].offset);
2570 break;
2571
2572 case WINED3DSPR_INPUT:
2573 case WINED3DSPR_INCONTROLPOINT:
2574 if (version->type == WINED3D_SHADER_TYPE_VERTEX)
2575 {
2576 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
2577
2578 if (reg->idx[0].rel_addr)
2579 FIXME("VS3 input registers relative addressing.\n");
2580 if (priv->cur_vs_args->swizzle_map & (1u << reg->idx[0].offset))
2581 *is_color = TRUE;
2582 if (reg->idx[0].rel_addr)
2583 {
2584 sprintf(register_name, "%s_in[%s + %u]",
2585 prefix, rel_param0.param_str, reg->idx[0].offset);
2586 }
2587 else
2588 {
2589 sprintf(register_name, "%s_in%u", prefix, reg->idx[0].offset);
2590 }
2591 break;
2592 }
2593
2594 if (version->type == WINED3D_SHADER_TYPE_HULL
2595 || version->type == WINED3D_SHADER_TYPE_DOMAIN
2596 || version->type == WINED3D_SHADER_TYPE_GEOMETRY)
2597 {
2598 if (reg->idx[0].rel_addr)
2599 {
2600 if (reg->idx[1].rel_addr)
2601 sprintf(register_name, "shader_in[%s + %u].reg[%s + %u]",
2602 rel_param0.param_str, reg->idx[0].offset,
2603 rel_param1.param_str, reg->idx[1].offset);
2604 else
2605 sprintf(register_name, "shader_in[%s + %u].reg[%u]",
2606 rel_param0.param_str, reg->idx[0].offset,
2607 reg->idx[1].offset);
2608 }
2609 else if (reg->idx[1].rel_addr)
2610 sprintf(register_name, "shader_in[%u].reg[%s + %u]", reg->idx[0].offset,
2611 rel_param1.param_str, reg->idx[1].offset);
2612 else
2613 sprintf(register_name, "shader_in[%u].reg[%u]",
2614 reg->idx[0].offset, reg->idx[1].offset);
2615 break;
2616 }
2617
2618 /* pixel shaders >= 3.0 */
2619 if (version->major >= 3)
2620 {
2621 DWORD idx = shader->u.ps.input_reg_map[reg->idx[0].offset];
2622 unsigned int in_count = vec4_varyings(version->major, gl_info);
2623
2624 if (reg->idx[0].rel_addr)
2625 {
2626 /* Removing a + 0 would be an obvious optimization, but
2627 * OS X doesn't see the NOP operation there. */
2628 if (idx)
2629 {
2630 if (needs_legacy_glsl_syntax(gl_info)
2631 && shader->u.ps.declared_in_count > in_count)
2632 {
2633 sprintf(register_name,
2634 "((%s + %u) > %u ? (%s + %u) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s + %u])",
2635 rel_param0.param_str, idx, in_count - 1, rel_param0.param_str, idx, in_count,
2636 prefix, rel_param0.param_str, idx);
2637 }
2638 else
2639 {
2640 sprintf(register_name, "%s_in[%s + %u]", prefix, rel_param0.param_str, idx);
2641 }
2642 }
2643 else
2644 {
2645 if (needs_legacy_glsl_syntax(gl_info)
2646 && shader->u.ps.declared_in_count > in_count)
2647 {
2648 sprintf(register_name, "((%s) > %u ? (%s) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s])",
2649 rel_param0.param_str, in_count - 1, rel_param0.param_str, in_count,
2650 prefix, rel_param0.param_str);
2651 }
2652 else
2653 {
2654 sprintf(register_name, "%s_in[%s]", prefix, rel_param0.param_str);
2655 }
2656 }
2657 }
2658 else
2659 {
2660 if (idx == in_count) sprintf(register_name, "gl_Color");
2661 else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor");
2662 else sprintf(register_name, "%s_in[%u]", prefix, idx);
2663 }
2664 }
2665 else
2666 {
2667 if (!reg->idx[0].offset)
2668 strcpy(register_name, "ffp_varying_diffuse");
2669 else
2670 strcpy(register_name, "ffp_varying_specular");
2671 break;
2672 }
2673 break;
2674
2675 case WINED3DSPR_CONST:
2676 {
2677 /* Relative addressing */
2678 if (reg->idx[0].rel_addr)
2679 {
2680 if (wined3d_settings.check_float_constants)
2681 sprintf(register_name, "(%s + %u >= 0 && %s + %u < %u ? %s_c[%s + %u] : vec4(0.0))",
2682 rel_param0.param_str, reg->idx[0].offset,
2683 rel_param0.param_str, reg->idx[0].offset, shader->limits->constant_float,
2684 prefix, rel_param0.param_str, reg->idx[0].offset);
2685 else if (reg->idx[0].offset)
2686 sprintf(register_name, "%s_c[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset);
2687 else
2688 sprintf(register_name, "%s_c[%s]", prefix, rel_param0.param_str);
2689 }
2690 else
2691 {
2692 if (shader_constant_is_local(shader, reg->idx[0].offset))
2693 sprintf(register_name, "%s_lc%u", prefix, reg->idx[0].offset);
2694 else
2695 sprintf(register_name, "%s_c[%u]", prefix, reg->idx[0].offset);
2696 }
2697 }
2698 break;
2699
2700 case WINED3DSPR_CONSTINT:
2701 sprintf(register_name, "%s_i[%u]", prefix, reg->idx[0].offset);
2702 break;
2703
2704 case WINED3DSPR_CONSTBOOL:
2705 sprintf(register_name, "%s_b[%u]", prefix, reg->idx[0].offset);
2706 break;
2707
2708 case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
2709 if (version->type == WINED3D_SHADER_TYPE_PIXEL)
2710 sprintf(register_name, "T%u", reg->idx[0].offset);
2711 else
2712 sprintf(register_name, "A%u", reg->idx[0].offset);
2713 break;
2714
2715 case WINED3DSPR_LOOP:
2716 sprintf(register_name, "aL%u", ins->ctx->state->current_loop_reg - 1);
2717 break;
2718
2719 case WINED3DSPR_SAMPLER:
2720 sprintf(register_name, "%s_sampler%u", prefix, reg->idx[0].offset);
2721 break;
2722
2723 case WINED3DSPR_COLOROUT:
2724 /* FIXME: should check dual_buffers when dual blending is enabled */
2725 if (reg->idx[0].offset >= gl_info->limits.buffers)
2726 WARN("Write to render target %u, only %d supported.\n",
2727 reg->idx[0].offset, gl_info->limits.buffers);
2728
2729 sprintf(register_name, needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[%u]" : "ps_out%u",
2730 reg->idx[0].offset);
2731 break;
2732
2733 case WINED3DSPR_RASTOUT:
2734 sprintf(register_name, "%s", hwrastout_reg_names[reg->idx[0].offset]);
2735 break;
2736
2737 case WINED3DSPR_DEPTHOUT:
2738 case WINED3DSPR_DEPTHOUTGE:
2739 case WINED3DSPR_DEPTHOUTLE:
2740 sprintf(register_name, "gl_FragDepth");
2741 break;
2742
2743 case WINED3DSPR_ATTROUT:
2744 if (!reg->idx[0].offset)
2745 sprintf(register_name, "%s_out[8]", prefix);
2746 else
2747 sprintf(register_name, "%s_out[9]", prefix);
2748 break;
2749
2750 case WINED3DSPR_TEXCRDOUT:
2751 /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
2752 if (reg->idx[0].rel_addr)
2753 sprintf(register_name, "%s_out[%s + %u]",
2754 prefix, rel_param0.param_str, reg->idx[0].offset);
2755 else
2756 sprintf(register_name, "%s_out[%u]", prefix, reg->idx[0].offset);
2757 break;
2758
2759 case WINED3DSPR_MISCTYPE:
2760 if (!reg->idx[0].offset)
2761 {
2762 /* vPos */
2763 sprintf(register_name, "vpos");
2764 }
2765 else if (reg->idx[0].offset == 1)
2766 {
2767 /* Note that gl_FrontFacing is a bool, while vFace is
2768 * a float for which the sign determines front/back */
2769 sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)");
2770 }
2771 else
2772 {
2773 FIXME("Unhandled misctype register %u.\n", reg->idx[0].offset);
2774 sprintf(register_name, "unrecognized_register");
2775 }
2776 break;
2777
2778 case WINED3DSPR_IMMCONST:
2779 switch (reg->immconst_type)
2780 {
2781 case WINED3D_IMMCONST_SCALAR:
2782 switch (data_type)
2783 {
2784 case WINED3D_DATA_FLOAT:
2785 if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
2786 sprintf(register_name, "uintBitsToFloat(%#xu)", reg->u.immconst_data[0]);
2787 else
2788 wined3d_ftoa(*(const float *)reg->u.immconst_data, register_name);
2789 break;
2790 case WINED3D_DATA_INT:
2791 sprintf(register_name, "%#x", reg->u.immconst_data[0]);
2792 break;
2793 case WINED3D_DATA_RESOURCE:
2794 case WINED3D_DATA_SAMPLER:
2795 case WINED3D_DATA_UINT:
2796 sprintf(register_name, "%#xu", reg->u.immconst_data[0]);
2797 break;
2798 default:
2799 sprintf(register_name, "<unhandled data type %#x>", data_type);
2800 break;
2801 }
2802 break;
2803
2804 case WINED3D_IMMCONST_VEC4:
2805 switch (data_type)
2806 {
2807 case WINED3D_DATA_FLOAT:
2808 if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
2809 {
2810 sprintf(register_name, "uintBitsToFloat(uvec4(%#xu, %#xu, %#xu, %#xu))",
2811 reg->u.immconst_data[0], reg->u.immconst_data[1],
2812 reg->u.immconst_data[2], reg->u.immconst_data[3]);
2813 }
2814 else
2815 {
2816 wined3d_ftoa(*(const float *)&reg->u.immconst_data[0], imm_str[0]);
2817 wined3d_ftoa(*(const float *)&reg->u.immconst_data[1], imm_str[1]);
2818 wined3d_ftoa(*(const float *)&reg->u.immconst_data[2], imm_str[2]);
2819 wined3d_ftoa(*(const float *)&reg->u.immconst_data[3], imm_str[3]);
2820 sprintf(register_name, "vec4(%s, %s, %s, %s)",
2821 imm_str[0], imm_str[1], imm_str[2], imm_str[3]);
2822 }
2823 break;
2824 case WINED3D_DATA_INT:
2825 sprintf(register_name, "ivec4(%#x, %#x, %#x, %#x)",
2826 reg->u.immconst_data[0], reg->u.immconst_data[1],
2827 reg->u.immconst_data[2], reg->u.immconst_data[3]);
2828 break;
2829 case WINED3D_DATA_RESOURCE:
2830 case WINED3D_DATA_SAMPLER:
2831 case WINED3D_DATA_UINT:
2832 sprintf(register_name, "uvec4(%#xu, %#xu, %#xu, %#xu)",
2833 reg->u.immconst_data[0], reg->u.immconst_data[1],
2834 reg->u.immconst_data[2], reg->u.immconst_data[3]);
2835 break;
2836 default:
2837 sprintf(register_name, "<unhandled data type %#x>", data_type);
2838 break;
2839 }
2840 break;
2841
2842 default:
2843 FIXME("Unhandled immconst type %#x\n", reg->immconst_type);
2844 sprintf(register_name, "<unhandled_immconst_type %#x>", reg->immconst_type);
2845 }
2846 break;
2847
2848 case WINED3DSPR_CONSTBUFFER:
2849 if (reg->idx[1].rel_addr)
2850 sprintf(register_name, "%s_cb%u[%s + %u]",
2851 prefix, reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
2852 else
2853 sprintf(register_name, "%s_cb%u[%u]", prefix, reg->idx[0].offset, reg->idx[1].offset);
2854 break;
2855
2856 case WINED3DSPR_IMMCONSTBUFFER:
2857 if (reg->idx[0].rel_addr)
2858 sprintf(register_name, "%s_icb[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset);
2859 else
2860 sprintf(register_name, "%s_icb[%u]", prefix, reg->idx[0].offset);
2861 break;
2862
2863 case WINED3DSPR_PRIMID:
2864 if (version->type == WINED3D_SHADER_TYPE_GEOMETRY)
2865 sprintf(register_name, "gl_PrimitiveIDIn");
2866 else
2867 sprintf(register_name, "gl_PrimitiveID");
2868 break;
2869
2870 case WINED3DSPR_IDXTEMP:
2871 if (reg->idx[1].rel_addr)
2872 sprintf(register_name, "X%u[%s + %u]", reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
2873 else
2874 sprintf(register_name, "X%u[%u]", reg->idx[0].offset, reg->idx[1].offset);
2875 break;
2876
2877 case WINED3DSPR_LOCALTHREADINDEX:
2878 shader_glsl_fixup_scalar_register_variable(register_name,
2879 "int(gl_LocalInvocationIndex)", gl_info);
2880 break;
2881
2882 case WINED3DSPR_GSINSTID:
2883 case WINED3DSPR_OUTPOINTID:
2884 shader_glsl_fixup_scalar_register_variable(register_name,
2885 "gl_InvocationID", gl_info);
2886 break;
2887
2888 case WINED3DSPR_THREADID:
2889 sprintf(register_name, "ivec3(gl_GlobalInvocationID)");
2890 break;
2891
2892 case WINED3DSPR_THREADGROUPID:
2893 sprintf(register_name, "ivec3(gl_WorkGroupID)");
2894 break;
2895
2896 case WINED3DSPR_LOCALTHREADID:
2897 sprintf(register_name, "ivec3(gl_LocalInvocationID)");
2898 break;
2899
2900 case WINED3DSPR_FORKINSTID:
2901 case WINED3DSPR_JOININSTID:
2902 shader_glsl_fixup_scalar_register_variable(register_name,
2903 "phase_instance_id", gl_info);
2904 break;
2905
2906 case WINED3DSPR_TESSCOORD:
2907 sprintf(register_name, "gl_TessCoord");
2908 break;
2909
2910 case WINED3DSPR_OUTCONTROLPOINT:
2911 if (reg->idx[0].rel_addr)
2912 {
2913 if (reg->idx[1].rel_addr)
2914 sprintf(register_name, "shader_out[%s + %u].reg[%s + %u]",
2915 rel_param0.param_str, reg->idx[0].offset,
2916 rel_param1.param_str, reg->idx[1].offset);
2917 else
2918 sprintf(register_name, "shader_out[%s + %u].reg[%u]",
2919 rel_param0.param_str, reg->idx[0].offset,
2920 reg->idx[1].offset);
2921 }
2922 else if (reg->idx[1].rel_addr)
2923 {
2924 sprintf(register_name, "shader_out[%u].reg[%s + %u]",
2925 reg->idx[0].offset, rel_param1.param_str,
2926 reg->idx[1].offset);
2927 }
2928 else
2929 {
2930 sprintf(register_name, "shader_out[%u].reg[%u]",
2931 reg->idx[0].offset, reg->idx[1].offset);
2932 }
2933 break;
2934
2935 case WINED3DSPR_PATCHCONST:
2936 if (version->type == WINED3D_SHADER_TYPE_HULL)
2937 sprintf(register_name, "hs_out[%u]", reg->idx[0].offset);
2938 else
2939 sprintf(register_name, "vpc[%u]", reg->idx[0].offset);
2940 break;
2941
2942 default:
2943 FIXME("Unhandled register type %#x.\n", reg->type);
2944 sprintf(register_name, "unrecognized_register");
2945 break;
2946 }
2947 }
2948
2949 static void shader_glsl_write_mask_to_str(DWORD write_mask, char *str)
2950 {
2951 *str++ = '.';
2952 if (write_mask & WINED3DSP_WRITEMASK_0) *str++ = 'x';
2953 if (write_mask & WINED3DSP_WRITEMASK_1) *str++ = 'y';
2954 if (write_mask & WINED3DSP_WRITEMASK_2) *str++ = 'z';
2955 if (write_mask & WINED3DSP_WRITEMASK_3) *str++ = 'w';
2956 *str = '\0';
2957 }
2958
2959 /* Get the GLSL write mask for the destination register */
2960 static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *param, char *write_mask)
2961 {
2962 DWORD mask = param->write_mask;
2963
2964 if (shader_is_scalar(&param->reg))
2965 {
2966 mask = WINED3DSP_WRITEMASK_0;
2967 *write_mask = '\0';
2968 }
2969 else
2970 {
2971 shader_glsl_write_mask_to_str(mask, write_mask);
2972 }
2973
2974 return mask;
2975 }
2976
2977 static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask)
2978 {
2979 unsigned int size = 0;
2980
2981 if (write_mask & WINED3DSP_WRITEMASK_0) ++size;
2982 if (write_mask & WINED3DSP_WRITEMASK_1) ++size;
2983 if (write_mask & WINED3DSP_WRITEMASK_2) ++size;
2984 if (write_mask & WINED3DSP_WRITEMASK_3) ++size;
2985
2986 return size;
2987 }
2988
2989 static unsigned int shader_glsl_swizzle_get_component(DWORD swizzle,
2990 unsigned int component_idx)
2991 {
2992 /* swizzle bits fields: wwzzyyxx */
2993 return (swizzle >> (2 * component_idx)) & 0x3;
2994 }
2995
2996 static void shader_glsl_swizzle_to_str(DWORD swizzle, BOOL fixup, DWORD mask, char *str)
2997 {
2998 /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
2999 * but addressed as "rgba". To fix this we need to swap the register's x
3000 * and z components. */
3001 const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
3002 unsigned int i;
3003
3004 *str++ = '.';
3005 for (i = 0; i < 4; ++i)
3006 {
3007 if (mask & (WINED3DSP_WRITEMASK_0 << i))
3008 *str++ = swizzle_chars[shader_glsl_swizzle_get_component(swizzle, i)];
3009 }
3010 *str = '\0';
3011 }
3012
3013 static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param,
3014 BOOL fixup, DWORD mask, char *swizzle_str)
3015 {
3016 if (shader_is_scalar(&param->reg))
3017 *swizzle_str = '\0';
3018 else
3019 shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str);
3020 }
3021
3022 static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, const char *src_param,
3023 enum wined3d_data_type dst_data_type, enum wined3d_data_type src_data_type)
3024 {
3025 if (dst_data_type == src_data_type)
3026 {
3027 string_buffer_sprintf(dst_param, "%s", src_param);
3028 return;
3029 }
3030
3031 if (src_data_type == WINED3D_DATA_FLOAT)
3032 {
3033 switch (dst_data_type)
3034 {
3035 case WINED3D_DATA_INT:
3036 string_buffer_sprintf(dst_param, "floatBitsToInt(%s)", src_param);
3037 return;
3038 case WINED3D_DATA_RESOURCE:
3039 case WINED3D_DATA_SAMPLER:
3040 case WINED3D_DATA_UINT:
3041 string_buffer_sprintf(dst_param, "floatBitsToUint(%s)", src_param);
3042 return;
3043 default:
3044 break;
3045 }
3046 }
3047
3048 if (src_data_type == WINED3D_DATA_UINT && dst_data_type == WINED3D_DATA_FLOAT)
3049 {
3050 string_buffer_sprintf(dst_param, "uintBitsToFloat(%s)", src_param);
3051 return;
3052 }
3053
3054 if (src_data_type == WINED3D_DATA_INT && dst_data_type == WINED3D_DATA_FLOAT)
3055 {
3056 string_buffer_sprintf(dst_param, "intBitsToFloat(%s)", src_param);
3057 return;
3058 }
3059
3060 FIXME("Unhandled cast from %#x to %#x.\n", src_data_type, dst_data_type);
3061 string_buffer_sprintf(dst_param, "%s", src_param);
3062 }
3063
3064 /* From a given parameter token, generate the corresponding GLSL string.
3065 * Also, return the actual register name and swizzle in case the
3066 * caller needs this information as well. */
3067 static void shader_glsl_add_src_param_ext(const struct wined3d_shader_instruction *ins,
3068 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src,
3069 enum wined3d_data_type data_type)
3070 {
3071 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
3072 struct wined3d_string_buffer *reg_name = string_buffer_get(priv->string_buffers);
3073 enum wined3d_data_type param_data_type;
3074 BOOL is_color = FALSE;
3075 char swizzle_str[6];
3076
3077 glsl_src->reg_name[0] = '\0';
3078 glsl_src->param_str[0] = '\0';
3079 swizzle_str[0] = '\0';
3080
3081 shader_glsl_get_register_name(&wined3d_src->reg, data_type, glsl_src->reg_name, &is_color, ins);
3082 shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str);
3083
3084 switch (wined3d_src->reg.type)
3085 {
3086 case WINED3DSPR_IMMCONST:
3087 param_data_type = data_type;
3088 break;
3089 case WINED3DSPR_FORKINSTID:
3090 case WINED3DSPR_GSINSTID:
3091 case WINED3DSPR_JOININSTID:
3092 case WINED3DSPR_LOCALTHREADID:
3093 case WINED3DSPR_LOCALTHREADINDEX:
3094 case WINED3DSPR_OUTPOINTID:
3095 case WINED3DSPR_PRIMID:
3096 case WINED3DSPR_THREADGROUPID:
3097 case WINED3DSPR_THREADID:
3098 param_data_type = WINED3D_DATA_INT;
3099 break;
3100 default:
3101 param_data_type = WINED3D_DATA_FLOAT;
3102 break;
3103 }
3104
3105 shader_glsl_sprintf_cast(reg_name, glsl_src->reg_name, data_type, param_data_type);
3106 shader_glsl_gen_modifier(wined3d_src->modifiers, reg_name->buffer, swizzle_str, glsl_src->param_str);
3107
3108 string_buffer_release(priv->string_buffers, reg_name);
3109 }
3110
3111 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
3112 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src)
3113 {
3114 shader_glsl_add_src_param_ext(ins, wined3d_src, mask, glsl_src, wined3d_src->reg.data_type);
3115 }
3116
3117 /* From a given parameter token, generate the corresponding GLSL string.
3118 * Also, return the actual register name and swizzle in case the
3119 * caller needs this information as well. */
3120 static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction *ins,
3121 const struct wined3d_shader_dst_param *wined3d_dst, struct glsl_dst_param *glsl_dst)
3122 {
3123 BOOL is_color = FALSE;
3124
3125 glsl_dst->mask_str[0] = '\0';
3126 glsl_dst->reg_name[0] = '\0';
3127
3128 shader_glsl_get_register_name(&wined3d_dst->reg, wined3d_dst->reg.data_type,
3129 glsl_dst->reg_name, &is_color, ins);
3130 return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str);
3131 }
3132
3133 /* Append the destination part of the instruction to the buffer, return the effective write mask */
3134 static DWORD shader_glsl_append_dst_ext(struct wined3d_string_buffer *buffer,
3135 const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst,
3136 enum wined3d_data_type data_type)
3137 {
3138 struct glsl_dst_param glsl_dst;
3139 DWORD mask;
3140
3141 if ((mask = shader_glsl_add_dst_param(ins, dst, &glsl_dst)))
3142 {
3143 switch (data_type)
3144 {
3145 case WINED3D_DATA_FLOAT:
3146 shader_addline(buffer, "%s%s = %s(",
3147 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3148 break;
3149 case WINED3D_DATA_INT:
3150 shader_addline(buffer, "%s%s = %sintBitsToFloat(",
3151 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3152 break;
3153 case WINED3D_DATA_RESOURCE:
3154 case WINED3D_DATA_SAMPLER:
3155 case WINED3D_DATA_UINT:
3156 shader_addline(buffer, "%s%s = %suintBitsToFloat(",
3157 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3158 break;
3159 default:
3160 FIXME("Unhandled data type %#x.\n", data_type);
3161 shader_addline(buffer, "%s%s = %s(",
3162 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3163 break;
3164 }
3165 }
3166
3167 return mask;
3168 }
3169
3170 /* Append the destination part of the instruction to the buffer, return the effective write mask */
3171 static DWORD shader_glsl_append_dst(struct wined3d_string_buffer *buffer, const struct wined3d_shader_instruction *ins)
3172 {
3173 return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type);
3174 }
3175
3176 /** Process GLSL instruction modifiers */
3177 static void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins)
3178 {
3179 struct glsl_dst_param dst_param;
3180 DWORD modifiers;
3181
3182 if (!ins->dst_count) return;
3183
3184 modifiers = ins->dst[0].modifiers;
3185 if (!modifiers) return;
3186
3187 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
3188
3189 if (modifiers & WINED3DSPDM_SATURATE)
3190 {
3191 /* _SAT means to clamp the value of the register to between 0 and 1 */
3192 shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name,
3193 dst_param.mask_str, dst_param.reg_name, dst_param.mask_str);
3194 }
3195
3196 if (modifiers & WINED3DSPDM_MSAMPCENTROID)
3197 {
3198 FIXME("_centroid modifier not handled\n");
3199 }
3200
3201 if (modifiers & WINED3DSPDM_PARTIALPRECISION)
3202 {
3203 /* MSDN says this modifier can be safely ignored, so that's what we'll do. */
3204 }
3205 }
3206
3207 static const char *shader_glsl_get_rel_op(enum wined3d_shader_rel_op op)
3208 {
3209 switch (op)
3210 {
3211 case WINED3D_SHADER_REL_OP_GT: return ">";
3212 case WINED3D_SHADER_REL_OP_EQ: return "==";
3213 case WINED3D_SHADER_REL_OP_GE: return ">=";
3214 case WINED3D_SHADER_REL_OP_LT: return "<";
3215 case WINED3D_SHADER_REL_OP_NE: return "!=";
3216 case WINED3D_SHADER_REL_OP_LE: return "<=";
3217 default:
3218 FIXME("Unrecognized operator %#x.\n", op);
3219 return "(\?\?)";
3220 }
3221 }
3222
3223 static BOOL shader_glsl_has_core_grad(const struct wined3d_gl_info *gl_info)
3224 {
3225 return shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4];
3226 }
3227
3228 static void shader_glsl_get_coord_size(enum wined3d_shader_resource_type resource_type,
3229 unsigned int *coord_size, unsigned int *deriv_size)
3230 {
3231 const BOOL is_array = resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY
3232 || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY;
3233
3234 *coord_size = resource_type_info[resource_type].coord_size;
3235 *deriv_size = *coord_size;
3236 if (is_array)
3237 --(*deriv_size);
3238 }
3239
3240 static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx,
3241 DWORD resource_idx, DWORD sampler_idx, DWORD flags, struct glsl_sample_function *sample_function)
3242 {
3243 enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type;
3244 struct shader_glsl_ctx_priv *priv = ctx->backend_data;
3245 const struct wined3d_gl_info *gl_info = ctx->gl_info;
3246 BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
3247 BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx);
3248 BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
3249 BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
3250 && priv->cur_ps_args->np2_fixup & (1u << resource_idx)
3251 && gl_info->supported[ARB_TEXTURE_RECTANGLE];
3252 BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
3253 BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD;
3254 BOOL offset = flags & WINED3D_GLSL_SAMPLE_OFFSET;
3255 const char *base = "texture", *type_part = "", *suffix = "";
3256 unsigned int coord_size, deriv_size;
3257
3258 sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type;
3259 sample_function->emulate_lod = WINED3D_SHADER_RESOURCE_NONE;
3260
3261 if (resource_type >= ARRAY_SIZE(resource_type_info))
3262 {
3263 ERR("Unexpected resource type %#x.\n", resource_type);
3264 resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D;
3265 }
3266
3267 /* Note that there's no such thing as a projected cube texture. */
3268 if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
3269 projected = FALSE;
3270
3271 if (shadow && lod)
3272 {
3273 switch (resource_type)
3274 {
3275 /* emulate textureLod(sampler2DArrayShadow, ...) using textureGradOffset */
3276 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
3277 sample_function->emulate_lod = resource_type;
3278 grad = offset = TRUE;
3279 lod = FALSE;
3280 break;
3281
3282 /* emulate textureLod(samplerCubeShadow, ...) using shadowCubeGrad */
3283 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
3284 sample_function->emulate_lod = resource_type;
3285 grad = legacy_syntax = TRUE;
3286 lod = FALSE;
3287 break;
3288
3289 default:
3290 break;
3291 }
3292 }
3293
3294 if (legacy_syntax)
3295 {
3296 if (shadow)
3297 base = "shadow";
3298
3299 type_part = resource_type_info[resource_type].type_part;
3300 if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect)
3301 type_part = "2DRect";
3302 if (!type_part[0] && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY)
3303 FIXME("Unhandled resource type %#x.\n", resource_type);
3304
3305 if (!lod && grad && !shader_glsl_has_core_grad(gl_info))
3306 {
3307 if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
3308 suffix = "ARB";
3309 else
3310 FIXME("Unsupported grad function.\n");
3311 }
3312 }
3313
3314 if (flags & WINED3D_GLSL_SAMPLE_LOAD)
3315 {
3316 static const DWORD texel_fetch_flags = WINED3D_GLSL_SAMPLE_LOAD | WINED3D_GLSL_SAMPLE_OFFSET;
3317 if (flags & ~texel_fetch_flags)
3318 ERR("Unexpected flags %#x for texelFetch.\n", flags & ~texel_fetch_flags);
3319
3320 base = "texelFetch";
3321 type_part = "";
3322 }
3323
3324 sample_function->name = string_buffer_get(priv->string_buffers);
3325 string_buffer_sprintf(sample_function->name, "%s%s%s%s%s%s", base, type_part, projected ? "Proj" : "",
3326 lod ? "Lod" : grad ? "Grad" : "", offset ? "Offset" : "", suffix);
3327
3328 shader_glsl_get_coord_size(resource_type, &coord_size, &deriv_size);
3329 if (shadow)
3330 ++coord_size;
3331 sample_function->offset_size = offset ? deriv_size : 0;
3332 sample_function->coord_mask = (1u << coord_size) - 1;
3333 sample_function->deriv_mask = (1u << deriv_size) - 1;
3334 sample_function->output_single_component = shadow && !legacy_syntax;
3335 }
3336
3337 static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx,
3338 struct glsl_sample_function *sample_function)
3339 {
3340 const struct shader_glsl_ctx_priv *priv = ctx->backend_data;
3341
3342 string_buffer_release(priv->string_buffers, sample_function->name);
3343 }
3344
3345 static void shader_glsl_append_fixup_arg(char *arguments, const char *reg_name,
3346 BOOL sign_fixup, enum fixup_channel_source channel_source)
3347 {
3348 switch(channel_source)
3349 {
3350 case CHANNEL_SOURCE_ZERO:
3351 strcat(arguments, "0.0");
3352 break;
3353
3354 case CHANNEL_SOURCE_ONE:
3355 strcat(arguments, "1.0");
3356 break;
3357
3358 case CHANNEL_SOURCE_X:
3359 strcat(arguments, reg_name);
3360 strcat(arguments, ".x");
3361 break;
3362
3363 case CHANNEL_SOURCE_Y:
3364 strcat(arguments, reg_name);
3365 strcat(arguments, ".y");
3366 break;
3367
3368 case CHANNEL_SOURCE_Z:
3369 strcat(arguments, reg_name);
3370 strcat(arguments, ".z");
3371 break;
3372
3373 case CHANNEL_SOURCE_W:
3374 strcat(arguments, reg_name);
3375 strcat(arguments, ".w");
3376 break;
3377
3378 default:
3379 FIXME("Unhandled channel source %#x\n", channel_source);
3380 strcat(arguments, "undefined");
3381 break;
3382 }
3383
3384 if (sign_fixup) strcat(arguments, " * 2.0 - 1.0");
3385 }
3386
3387 static void shader_glsl_color_correction_ext(struct wined3d_string_buffer *buffer,
3388 const char *reg_name, DWORD mask, struct color_fixup_desc fixup)
3389 {
3390 unsigned int mask_size, remaining;
3391 DWORD fixup_mask = 0;
3392 char arguments[256];
3393 char mask_str[6];
3394
3395 if (fixup.x_sign_fixup || fixup.x_source != CHANNEL_SOURCE_X) fixup_mask |= WINED3DSP_WRITEMASK_0;
3396 if (fixup.y_sign_fixup || fixup.y_source != CHANNEL_SOURCE_Y) fixup_mask |= WINED3DSP_WRITEMASK_1;
3397 if (fixup.z_sign_fixup || fixup.z_source != CHANNEL_SOURCE_Z) fixup_mask |= WINED3DSP_WRITEMASK_2;
3398 if (fixup.w_sign_fixup || fixup.w_source != CHANNEL_SOURCE_W) fixup_mask |= WINED3DSP_WRITEMASK_3;
3399 if (!(mask &= fixup_mask))
3400 return;
3401
3402 if (is_complex_fixup(fixup))
3403 {
3404 enum complex_fixup complex_fixup = get_complex_fixup(fixup);
3405 FIXME("Complex fixup (%#x) not supported\n",complex_fixup);
3406 return;
3407 }
3408
3409 shader_glsl_write_mask_to_str(mask, mask_str);
3410 mask_size = shader_glsl_get_write_mask_size(mask);
3411
3412 arguments[0] = '\0';
3413 remaining = mask_size;
3414 if (mask & WINED3DSP_WRITEMASK_0)
3415 {
3416 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.x_sign_fixup, fixup.x_source);
3417 if (--remaining) strcat(arguments, ", ");
3418 }
3419 if (mask & WINED3DSP_WRITEMASK_1)
3420 {
3421 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.y_sign_fixup, fixup.y_source);
3422 if (--remaining) strcat(arguments, ", ");
3423 }
3424 if (mask & WINED3DSP_WRITEMASK_2)
3425 {
3426 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.z_sign_fixup, fixup.z_source);
3427 if (--remaining) strcat(arguments, ", ");
3428 }
3429 if (mask & WINED3DSP_WRITEMASK_3)
3430 {
3431 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.w_sign_fixup, fixup.w_source);
3432 if (--remaining) strcat(arguments, ", ");
3433 }
3434
3435 if (mask_size > 1)
3436 shader_addline(buffer, "%s%s = vec%u(%s);\n", reg_name, mask_str, mask_size, arguments);
3437 else
3438 shader_addline(buffer, "%s%s = %s;\n", reg_name, mask_str, arguments);
3439 }
3440
3441 static void shader_glsl_color_correction(const struct wined3d_shader_instruction *ins, struct color_fixup_desc fixup)
3442 {
3443 char reg_name[256];
3444 BOOL is_color;
3445
3446 shader_glsl_get_register_name(&ins->dst[0].reg, ins->dst[0].reg.data_type, reg_name, &is_color, ins);
3447 shader_glsl_color_correction_ext(ins->ctx->buffer, reg_name, ins->dst[0].write_mask, fixup);
3448 }
3449
3450 static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
3451 unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, DWORD swizzle,
3452 const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset,
3453 const char *coord_reg_fmt, ...)
3454 {
3455 static const struct wined3d_shader_texel_offset dummy_offset = {0, 0, 0};
3456 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
3457 char dst_swizzle[6];
3458 struct color_fixup_desc fixup;
3459 BOOL np2_fixup = FALSE;
3460 va_list args;
3461 int ret;
3462
3463 shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle);
3464
3465 /* If ARB_texture_swizzle is supported we don't need to do anything here.
3466 * We actually rely on it for vertex shaders and SM4+. */
3467 if (version->type == WINED3D_SHADER_TYPE_PIXEL && version->major < 4)
3468 {
3469 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
3470 fixup = priv->cur_ps_args->color_fixup[sampler_bind_idx];
3471
3472 if (priv->cur_ps_args->np2_fixup & (1u << sampler_bind_idx))
3473 np2_fixup = TRUE;
3474 }
3475 else
3476 {
3477 fixup = COLOR_FIXUP_IDENTITY;
3478 }
3479
3480 shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], sample_function->data_type);
3481
3482 if (sample_function->output_single_component)
3483 shader_addline(ins->ctx->buffer, "vec4(");
3484
3485 shader_addline(ins->ctx->buffer, "%s(%s_sampler%u, ",
3486 sample_function->name->buffer, shader_glsl_get_prefix(version->type), sampler_bind_idx);
3487
3488 for (;;)
3489 {
3490 va_start(args, coord_reg_fmt);
3491 ret = shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args);
3492 va_end(args);
3493 if (!ret)
3494 break;
3495 if (!string_buffer_resize(ins->ctx->buffer, ret))
3496 break;
3497 }
3498
3499 if (np2_fixup)
3500 {
3501 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
3502 const unsigned char idx = priv->cur_np2fixup_info->idx[sampler_bind_idx];
3503
3504 switch (shader_glsl_get_write_mask_size(sample_function->coord_mask))
3505 {
3506 case 1:
3507 shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s",
3508 idx >> 1, (idx % 2) ? "z" : "x");
3509 break;
3510 case 2:
3511 shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s",
3512 idx >> 1, (idx % 2) ? "zw" : "xy");
3513 break;
3514 case 3:
3515 shader_addline(ins->ctx->buffer, " * vec3(ps_samplerNP2Fixup[%u].%s, 1.0)",
3516 idx >> 1, (idx % 2) ? "zw" : "xy");
3517 break;
3518 case 4:
3519 shader_addline(ins->ctx->buffer, " * vec4(ps_samplerNP2Fixup[%u].%s, 1.0, 1.0)",
3520 idx >> 1, (idx % 2) ? "zw" : "xy");
3521 break;
3522 }
3523 }
3524 if (sample_function->emulate_lod)
3525 {
3526 if (strcmp(bias, "0")) FIXME("Don't know how to emulate lod level %s\n", bias);
3527 switch (sample_function->emulate_lod)
3528 {
3529 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
3530 if (!dx) dx = "vec2(0.0, 0.0)";
3531 if (!dy) dy = "vec2(0.0, 0.0)";
3532 break;
3533
3534 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
3535 if (!dx) dx = "vec3(0.0, 0.0, 0.0)";
3536 if (!dy) dy = "vec3(0.0, 0.0, 0.0)";
3537 break;
3538
3539 default:
3540 break;
3541 }
3542 if (!offset) offset = &dummy_offset;
3543 }
3544 if (dx && dy)
3545 shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy);
3546 else if (bias)
3547 shader_addline(ins->ctx->buffer, ", %s", bias);
3548 if (sample_function->offset_size)
3549 {
3550 int offset_immdata[4] = {offset->u, offset->v, offset->w};
3551 shader_addline(ins->ctx->buffer, ", ");
3552 shader_glsl_append_imm_ivec(ins->ctx->buffer, offset_immdata, sample_function->offset_size);
3553 }
3554 shader_addline(ins->ctx->buffer, ")");
3555
3556 if (sample_function->output_single_component)
3557 shader_addline(ins->ctx->buffer, ")");
3558
3559 shader_addline(ins->ctx->buffer, "%s);\n", dst_swizzle);
3560
3561 if (!is_identity_fixup(fixup))
3562 shader_glsl_color_correction(ins, fixup);
3563 }
3564
3565 static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer)
3566 {
3567 /* Write the final position.
3568 *
3569 * OpenGL coordinates specify the center of the pixel while D3D coords
3570 * specify the corner. The offsets are stored in z and w in
3571 * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering
3572 * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow
3573 * a MAD. */
3574 shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n");
3575 shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n");
3576
3577 /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix()
3578 * in utils.c
3579 *
3580 * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However,
3581 * shaders are run before the homogeneous divide, so we have to take the w
3582 * into account: z = ((z / w) * 2 - 1) * w, which is the same as
3583 * z = z * 2 - w. */
3584 shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
3585 }
3586
3587 /*****************************************************************************
3588 * Begin processing individual instruction opcodes
3589 ****************************************************************************/
3590
3591 static void shader_glsl_binop(const struct wined3d_shader_instruction *ins)
3592 {
3593 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3594 struct glsl_src_param src0_param;
3595 struct glsl_src_param src1_param;
3596 DWORD write_mask;
3597 const char *op;
3598
3599 /* Determine the GLSL operator to use based on the opcode */
3600 switch (ins->handler_idx)
3601 {
3602 case WINED3DSIH_ADD: op = "+"; break;
3603 case WINED3DSIH_AND: op = "&"; break;
3604 case WINED3DSIH_DIV: op = "/"; break;
3605 case WINED3DSIH_IADD: op = "+"; break;
3606 case WINED3DSIH_ISHL: op = "<<"; break;
3607 case WINED3DSIH_ISHR: op = ">>"; break;
3608 case WINED3DSIH_MUL: op = "*"; break;
3609 case WINED3DSIH_OR: op = "|"; break;
3610 case WINED3DSIH_SUB: op = "-"; break;
3611 case WINED3DSIH_USHR: op = ">>"; break;
3612 case WINED3DSIH_XOR: op = "^"; break;
3613 default:
3614 op = "<unhandled operator>";
3615 FIXME("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
3616 break;
3617 }
3618
3619 write_mask = shader_glsl_append_dst(buffer, ins);
3620 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3621 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3622 shader_addline(buffer, "%s %s %s);\n", src0_param.param_str, op, src1_param.param_str);
3623 }
3624
3625 static void shader_glsl_relop(const struct wined3d_shader_instruction *ins)
3626 {
3627 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3628 struct glsl_src_param src0_param;
3629 struct glsl_src_param src1_param;
3630 unsigned int mask_size;
3631 DWORD write_mask;
3632 const char *op;
3633
3634 write_mask = shader_glsl_append_dst(buffer, ins);
3635 mask_size = shader_glsl_get_write_mask_size(write_mask);
3636 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3637 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3638
3639 if (mask_size > 1)
3640 {
3641 switch (ins->handler_idx)
3642 {
3643 case WINED3DSIH_EQ: op = "equal"; break;
3644 case WINED3DSIH_IEQ: op = "equal"; break;
3645 case WINED3DSIH_GE: op = "greaterThanEqual"; break;
3646 case WINED3DSIH_IGE: op = "greaterThanEqual"; break;
3647 case WINED3DSIH_UGE: op = "greaterThanEqual"; break;
3648 case WINED3DSIH_LT: op = "lessThan"; break;
3649 case WINED3DSIH_ILT: op = "lessThan"; break;
3650 case WINED3DSIH_ULT: op = "lessThan"; break;
3651 case WINED3DSIH_NE: op = "notEqual"; break;
3652 case WINED3DSIH_INE: op = "notEqual"; break;
3653 default:
3654 op = "<unhandled operator>";
3655 ERR("Unhandled opcode %#x.\n", ins->handler_idx);
3656 break;
3657 }
3658
3659 shader_addline(buffer, "uvec%u(%s(%s, %s)) * 0xffffffffu);\n",
3660 mask_size, op, src0_param.param_str, src1_param.param_str);
3661 }
3662 else
3663 {
3664 switch (ins->handler_idx)
3665 {
3666 case WINED3DSIH_EQ: op = "=="; break;
3667 case WINED3DSIH_IEQ: op = "=="; break;
3668 case WINED3DSIH_GE: op = ">="; break;
3669 case WINED3DSIH_IGE: op = ">="; break;
3670 case WINED3DSIH_UGE: op = ">="; break;
3671 case WINED3DSIH_LT: op = "<"; break;
3672 case WINED3DSIH_ILT: op = "<"; break;
3673 case WINED3DSIH_ULT: op = "<"; break;
3674 case WINED3DSIH_NE: op = "!="; break;
3675 case WINED3DSIH_INE: op = "!="; break;
3676 default:
3677 op = "<unhandled operator>";
3678 ERR("Unhandled opcode %#x.\n", ins->handler_idx);
3679 break;
3680 }
3681
3682 shader_addline(buffer, "%s %s %s ? 0xffffffffu : 0u);\n",
3683 src0_param.param_str, op, src1_param.param_str);
3684 }
3685 }
3686
3687 static void shader_glsl_unary_op(const struct wined3d_shader_instruction *ins)
3688 {
3689 struct glsl_src_param src_param;
3690 DWORD write_mask;
3691 const char *op;
3692
3693 switch (ins->handler_idx)
3694 {
3695 case WINED3DSIH_INEG: op = "-"; break;
3696 case WINED3DSIH_NOT: op = "~"; break;
3697 default:
3698 op = "<unhandled operator>";
3699 ERR("Unhandled opcode %s.\n",
3700 debug_d3dshaderinstructionhandler(ins->handler_idx));
3701 break;
3702 }
3703
3704 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
3705 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
3706 shader_addline(ins->ctx->buffer, "%s%s);\n", op, src_param.param_str);
3707 }
3708
3709 static void shader_glsl_mul_extended(const struct wined3d_shader_instruction *ins)
3710 {
3711 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3712 struct glsl_src_param src0_param;
3713 struct glsl_src_param src1_param;
3714 DWORD write_mask;
3715
3716 /* If we have ARB_gpu_shader5, we can use imulExtended() / umulExtended().
3717 * If not, we can emulate it. */
3718 if (ins->dst[0].reg.type != WINED3DSPR_NULL)
3719 FIXME("64-bit integer multiplies not implemented.\n");
3720
3721 if (ins->dst[1].reg.type != WINED3DSPR_NULL)
3722 {
3723 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
3724 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3725 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3726
3727 shader_addline(ins->ctx->buffer, "%s * %s);\n",
3728 src0_param.param_str, src1_param.param_str);
3729 }
3730 }
3731
3732 static void shader_glsl_udiv(const struct wined3d_shader_instruction *ins)
3733 {
3734 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3735 struct glsl_src_param src0_param, src1_param;
3736 DWORD write_mask;
3737
3738 if (ins->dst[0].reg.type != WINED3DSPR_NULL)
3739 {
3740 if (ins->dst[1].reg.type != WINED3DSPR_NULL)
3741 {
3742 char dst_mask[6];
3743
3744 write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
3745 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3746 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3747 shader_addline(buffer, "tmp0%s = uintBitsToFloat(%s / %s);\n",
3748 dst_mask, src0_param.param_str, src1_param.param_str);
3749
3750 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
3751 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3752 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3753 shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str);
3754
3755 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT);
3756 shader_addline(buffer, "tmp0%s);\n", dst_mask);
3757 }
3758 else
3759 {
3760 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type);
3761 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3762 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3763 shader_addline(buffer, "%s / %s);\n", src0_param.param_str, src1_param.param_str);
3764 }
3765 }
3766 else if (ins->dst[1].reg.type != WINED3DSPR_NULL)
3767 {
3768 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
3769 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3770 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3771 shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str);
3772 }
3773 }
3774
3775 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
3776 static void shader_glsl_mov(const struct wined3d_shader_instruction *ins)
3777 {
3778 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
3779 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3780 struct glsl_src_param src0_param;
3781 DWORD write_mask;
3782
3783 write_mask = shader_glsl_append_dst(buffer, ins);
3784 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3785
3786 /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later
3787 * shader versions WINED3DSIO_MOVA is used for this. */
3788 if (ins->ctx->reg_maps->shader_version.major == 1
3789 && ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX
3790 && ins->dst[0].reg.type == WINED3DSPR_ADDR)
3791 {
3792 /* This is a simple floor() */
3793 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
3794 if (mask_size > 1) {
3795 shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str);
3796 } else {
3797 shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str);
3798 }
3799 }
3800 else if (ins->handler_idx == WINED3DSIH_MOVA)
3801 {
3802 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
3803
3804 if (shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4])
3805 {
3806 if (mask_size > 1)
3807 shader_addline(buffer, "ivec%d(round(%s)));\n", mask_size, src0_param.param_str);
3808 else
3809 shader_addline(buffer, "int(round(%s)));\n", src0_param.param_str);
3810 }
3811 else
3812 {
3813 if (mask_size > 1)
3814 shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n",
3815 mask_size, src0_param.param_str, mask_size, src0_param.param_str);
3816 else
3817 shader_addline(buffer, "int(floor(abs(%s) + 0.5) * sign(%s)));\n",
3818 src0_param.param_str, src0_param.param_str);
3819 }
3820 }
3821 else
3822 {
3823 shader_addline(buffer, "%s);\n", src0_param.param_str);
3824 }
3825 }
3826
3827 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */
3828 static void shader_glsl_dot(const struct wined3d_shader_instruction *ins)
3829 {
3830 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3831 struct glsl_src_param src0_param;
3832 struct glsl_src_param src1_param;
3833 DWORD dst_write_mask, src_write_mask;
3834 unsigned int dst_size;
3835
3836 dst_write_mask = shader_glsl_append_dst(buffer, ins);
3837 dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
3838
3839 /* dp4 works on vec4, dp3 on vec3, etc. */
3840 if (ins->handler_idx == WINED3DSIH_DP4)
3841 src_write_mask = WINED3DSP_WRITEMASK_ALL;
3842 else if (ins->handler_idx == WINED3DSIH_DP3)
3843 src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
3844 else
3845 src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
3846
3847 shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param);
3848 shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param);
3849
3850 if (dst_size > 1) {
3851 shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str);
3852 } else {
3853 shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str);
3854 }
3855 }
3856
3857 /* Note that this instruction has some restrictions. The destination write mask
3858 * can't contain the w component, and the source swizzles have to be .xyzw */
3859 static void shader_glsl_cross(const struct wined3d_shader_instruction *ins)
3860 {
3861 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
3862 struct glsl_src_param src0_param;
3863 struct glsl_src_param src1_param;
3864 char dst_mask[6];
3865
3866 shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
3867 shader_glsl_append_dst(ins->ctx->buffer, ins);
3868 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
3869 shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
3870 shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask);
3871 }
3872
3873 static void shader_glsl_cut(const struct wined3d_shader_instruction *ins)
3874 {
3875 unsigned int stream = ins->handler_idx == WINED3DSIH_CUT ? 0 : ins->src[0].reg.idx[0].offset;
3876
3877 if (!stream)
3878 shader_addline(ins->ctx->buffer, "EndPrimitive();\n");
3879 else
3880 FIXME("Unhandled primitive stream %u.\n", stream);
3881 }
3882
3883 /* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1)
3884 * Src0 and src1 are scalars. Note that D3D uses the absolute of src0, while
3885 * GLSL uses the value as-is. */
3886 static void shader_glsl_pow(const struct wined3d_shader_instruction *ins)
3887 {
3888 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3889 struct glsl_src_param src0_param;
3890 struct glsl_src_param src1_param;
3891 DWORD dst_write_mask;
3892 unsigned int dst_size;
3893
3894 dst_write_mask = shader_glsl_append_dst(buffer, ins);
3895 dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
3896
3897 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
3898 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
3899
3900 if (dst_size > 1)
3901 {
3902 shader_addline(buffer, "vec%u(%s == 0.0 ? 1.0 : pow(abs(%s), %s)));\n",
3903 dst_size, src1_param.param_str, src0_param.param_str, src1_param.param_str);
3904 }
3905 else
3906 {
3907 shader_addline(buffer, "%s == 0.0 ? 1.0 : pow(abs(%s), %s));\n",
3908 src1_param.param_str, src0_param.param_str, src1_param.param_str);
3909 }
3910 }
3911
3912 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */
3913 static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins)
3914 {
3915 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3916 struct glsl_src_param src_param;
3917 const char *instruction;
3918 DWORD write_mask;
3919 unsigned i;
3920
3921 /* Determine the GLSL function to use based on the opcode */
3922 /* TODO: Possibly make this a table for faster lookups */
3923 switch (ins->handler_idx)
3924 {
3925 case WINED3DSIH_ABS: instruction = "abs"; break;
3926 case WINED3DSIH_BFREV: instruction = "bitfieldReverse"; break;
3927 case WINED3DSIH_COUNTBITS: instruction = "bitCount"; break;
3928 case WINED3DSIH_DSX: instruction = "dFdx"; break;
3929 case WINED3DSIH_DSX_COARSE: instruction = "dFdxCoarse"; break;
3930 case WINED3DSIH_DSX_FINE: instruction = "dFdxFine"; break;
3931 case WINED3DSIH_DSY: instruction = "ycorrection.y * dFdy"; break;
3932 case WINED3DSIH_DSY_COARSE: instruction = "ycorrection.y * dFdyCoarse"; break;
3933 case WINED3DSIH_DSY_FINE: instruction = "ycorrection.y * dFdyFine"; break;
3934 case WINED3DSIH_FIRSTBIT_HI: instruction = "findMSB"; break;
3935 case WINED3DSIH_FIRSTBIT_LO: instruction = "findLSB"; break;
3936 case WINED3DSIH_FIRSTBIT_SHI: instruction = "findMSB"; break;
3937 case WINED3DSIH_FRC: instruction = "fract"; break;
3938 case WINED3DSIH_IMAX: instruction = "max"; break;
3939 case WINED3DSIH_IMIN: instruction = "min"; break;
3940 case WINED3DSIH_MAX: instruction = "max"; break;
3941 case WINED3DSIH_MIN: instruction = "min"; break;
3942 case WINED3DSIH_ROUND_NE: instruction = "roundEven"; break;
3943 case WINED3DSIH_ROUND_NI: instruction = "floor"; break;
3944 case WINED3DSIH_ROUND_PI: instruction = "ceil"; break;
3945 case WINED3DSIH_ROUND_Z: instruction = "trunc"; break;
3946 case WINED3DSIH_SQRT: instruction = "sqrt"; break;
3947 case WINED3DSIH_UMAX: instruction = "max"; break;
3948 case WINED3DSIH_UMIN: instruction = "min"; break;
3949 default: instruction = "";
3950 ERR("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
3951 break;
3952 }
3953
3954 write_mask = shader_glsl_append_dst(buffer, ins);
3955
3956 /* In D3D bits are numbered from the most significant bit. */
3957 if (ins->handler_idx == WINED3DSIH_FIRSTBIT_HI || ins->handler_idx == WINED3DSIH_FIRSTBIT_SHI)
3958 shader_addline(buffer, "31 - ");
3959 shader_addline(buffer, "%s(", instruction);
3960
3961 if (ins->src_count)
3962 {
3963 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
3964 shader_addline(buffer, "%s", src_param.param_str);
3965 for (i = 1; i < ins->src_count; ++i)
3966 {
3967 shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param);
3968 shader_addline(buffer, ", %s", src_param.param_str);
3969 }
3970 }
3971
3972 shader_addline(buffer, "));\n");
3973 }
3974
3975 static void shader_glsl_float16(const struct wined3d_shader_instruction *ins)
3976 {
3977 struct wined3d_shader_dst_param dst;
3978 struct glsl_src_param src;
3979 DWORD write_mask;
3980 const char *fmt;
3981 unsigned int i;
3982
3983 fmt = ins->handler_idx == WINED3DSIH_F16TOF32
3984 ? "unpackHalf2x16(%s).x);\n" : "packHalf2x16(vec2(%s, 0.0)));\n";
3985
3986 dst = ins->dst[0];
3987 for (i = 0; i < 4; ++i)
3988 {
3989 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i);
3990 if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins,
3991 &dst, dst.reg.data_type)))
3992 continue;
3993
3994 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src);
3995 shader_addline(ins->ctx->buffer, fmt, src.param_str);
3996 }
3997 }
3998
3999 static void shader_glsl_bitwise_op(const struct wined3d_shader_instruction *ins)
4000 {
4001 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4002 struct wined3d_shader_dst_param dst;
4003 struct glsl_src_param src[4];
4004 const char *instruction;
4005 BOOL tmp_dst = FALSE;
4006 char mask_char[6];
4007 unsigned int i, j;
4008 DWORD write_mask;
4009
4010 switch (ins->handler_idx)
4011 {
4012 case WINED3DSIH_BFI: instruction = "bitfieldInsert"; break;
4013 case WINED3DSIH_IBFE: instruction = "bitfieldExtract"; break;
4014 case WINED3DSIH_UBFE: instruction = "bitfieldExtract"; break;
4015 default:
4016 ERR("Unhandled opcode %#x.\n", ins->handler_idx);
4017 return;
4018 }
4019
4020 for (i = 0; i < ins->src_count; ++i)
4021 {
4022 if (ins->dst[0].reg.idx[0].offset == ins->src[i].reg.idx[0].offset
4023 && ins->dst[0].reg.type == ins->src[i].reg.type)
4024 tmp_dst = TRUE;
4025 }
4026
4027 dst = ins->dst[0];
4028 for (i = 0; i < 4; ++i)
4029 {
4030 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i);
4031 if (tmp_dst && (write_mask = shader_glsl_get_write_mask(&dst, mask_char)))
4032 shader_addline(buffer, "tmp0%s = %sBitsToFloat(", mask_char,
4033 dst.reg.data_type == WINED3D_DATA_INT ? "int" : "uint");
4034 else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst, dst.reg.data_type)))
4035 continue;
4036
4037 for (j = 0; j < ins->src_count; ++j)
4038 shader_glsl_add_src_param(ins, &ins->src[j], write_mask, &src[j]);
4039 shader_addline(buffer, "%s(", instruction);
4040 for (j = 0; j < ins->src_count - 2; ++j)
4041 shader_addline(buffer, "%s, ", src[ins->src_count - j - 1].param_str);
4042 shader_addline(buffer, "%s & 0x1f, %s & 0x1f));\n", src[1].param_str, src[0].param_str);
4043 }
4044
4045 if (tmp_dst)
4046 {
4047 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT);
4048 shader_glsl_get_write_mask(&ins->dst[0], mask_char);
4049 shader_addline(buffer, "tmp0%s);\n", mask_char);
4050 }
4051 }
4052
4053 static void shader_glsl_nop(const struct wined3d_shader_instruction *ins) {}
4054
4055 static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins)
4056 {
4057 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4058 struct glsl_src_param src_param;
4059 unsigned int mask_size;
4060 DWORD write_mask;
4061 char dst_mask[6];
4062
4063 write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask);
4064 mask_size = shader_glsl_get_write_mask_size(write_mask);
4065 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
4066
4067 shader_addline(buffer, "tmp0.x = dot(%s, %s);\n",
4068 src_param.param_str, src_param.param_str);
4069 shader_glsl_append_dst(buffer, ins);
4070
4071 if (mask_size > 1)
4072 {
4073 shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s * inversesqrt(tmp0.x)));\n",
4074 mask_size, src_param.param_str);
4075 }
4076 else
4077 {
4078 shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s * inversesqrt(tmp0.x)));\n",
4079 src_param.param_str);
4080 }
4081 }
4082
4083 static void shader_glsl_scalar_op(const struct wined3d_shader_instruction *ins)
4084 {
4085 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
4086 ins->ctx->reg_maps->shader_version.minor);
4087 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4088 struct glsl_src_param src0_param;
4089 const char *prefix, *suffix;
4090 unsigned int dst_size;
4091 DWORD dst_write_mask;
4092
4093 dst_write_mask = shader_glsl_append_dst(buffer, ins);
4094 dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
4095
4096 if (shader_version < WINED3D_SHADER_VERSION(4, 0))
4097 dst_write_mask = WINED3DSP_WRITEMASK_3;
4098
4099 shader_glsl_add_src_param(ins, &ins->src[0], dst_write_mask, &src0_param);
4100
4101 switch (ins->handler_idx)
4102 {
4103 case WINED3DSIH_EXP:
4104 case WINED3DSIH_EXPP:
4105 prefix = "exp2(";
4106 suffix = ")";
4107 break;
4108
4109 case WINED3DSIH_LOG:
4110 case WINED3DSIH_LOGP:
4111 prefix = "log2(abs(";
4112 suffix = "))";
4113 break;
4114
4115 case WINED3DSIH_RCP:
4116 prefix = "1.0 / ";
4117 suffix = "";
4118 break;
4119
4120 case WINED3DSIH_RSQ:
4121 prefix = "inversesqrt(abs(";
4122 suffix = "))";
4123 break;
4124
4125 default:
4126 prefix = "";
4127 suffix = "";
4128 FIXME("Unhandled instruction %#x.\n", ins->handler_idx);
4129 break;
4130 }
4131
4132 if (dst_size > 1 && shader_version < WINED3D_SHADER_VERSION(4, 0))
4133 shader_addline(buffer, "vec%u(%s%s%s));\n", dst_size, prefix, src0_param.param_str, suffix);
4134 else
4135 shader_addline(buffer, "%s%s%s);\n", prefix, src0_param.param_str, suffix);
4136 }
4137
4138 /** Process the WINED3DSIO_EXPP instruction in GLSL:
4139 * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable):
4140 * dst.x = 2^(floor(src))
4141 * dst.y = src - floor(src)
4142 * dst.z = 2^src (partial precision is allowed, but optional)
4143 * dst.w = 1.0;
4144 * For 2.0 shaders, just do this (honoring writemask and swizzle):
4145 * dst = 2^src; (partial precision is allowed, but optional)
4146 */
4147 static void shader_glsl_expp(const struct wined3d_shader_instruction *ins)
4148 {
4149 if (ins->ctx->reg_maps->shader_version.major < 2)
4150 {
4151 struct glsl_src_param src_param;
4152 char dst_mask[6];
4153
4154 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param);
4155
4156 shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
4157 shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str);
4158 shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str);
4159 shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n");
4160
4161 shader_glsl_append_dst(ins->ctx->buffer, ins);
4162 shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
4163 shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask);
4164 return;
4165 }
4166
4167 shader_glsl_scalar_op(ins);
4168 }
4169
4170 static void shader_glsl_cast(const struct wined3d_shader_instruction *ins,
4171 const char *vector_constructor, const char *scalar_constructor)
4172 {
4173 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4174 struct glsl_src_param src_param;
4175 unsigned int mask_size;
4176 DWORD write_mask;
4177
4178 write_mask = shader_glsl_append_dst(buffer, ins);
4179 mask_size = shader_glsl_get_write_mask_size(write_mask);
4180 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
4181
4182 if (mask_size > 1)
4183 shader_addline(buffer, "%s%u(%s));\n", vector_constructor, mask_size, src_param.param_str);
4184 else
4185 shader_addline(buffer, "%s(%s));\n", scalar_constructor, src_param.param_str);
4186 }
4187
4188 static void shader_glsl_to_int(const struct wined3d_shader_instruction *ins)
4189 {
4190 shader_glsl_cast(ins, "ivec", "int");
4191 }
4192
4193 static void shader_glsl_to_uint(const struct wined3d_shader_instruction *ins)
4194 {
4195 shader_glsl_cast(ins, "uvec", "uint");
4196 }
4197
4198 static void shader_glsl_to_float(const struct wined3d_shader_instruction *ins)
4199 {
4200 shader_glsl_cast(ins, "vec", "float");
4201 }
4202
4203 /** Process signed comparison opcodes in GLSL. */
4204 static void shader_glsl_compare(const struct wined3d_shader_instruction *ins)
4205 {
4206 struct glsl_src_param src0_param;
4207 struct glsl_src_param src1_param;
4208 DWORD write_mask;
4209 unsigned int mask_size;
4210
4211 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4212 mask_size = shader_glsl_get_write_mask_size(write_mask);
4213 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4214 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4215
4216 if (mask_size > 1) {
4217 const char *compare;
4218
4219 switch(ins->handler_idx)
4220 {
4221 case WINED3DSIH_SLT: compare = "lessThan"; break;
4222 case WINED3DSIH_SGE: compare = "greaterThanEqual"; break;
4223 default: compare = "";
4224 FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
4225 }
4226
4227 shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare,
4228 src0_param.param_str, src1_param.param_str);
4229 } else {
4230 switch(ins->handler_idx)
4231 {
4232 case WINED3DSIH_SLT:
4233 /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed,
4234 * to return 0.0 but step returns 1.0 because step is not < x
4235 * An alternative is a bvec compare padded with an unused second component.
4236 * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same
4237 * issue. Playing with not() is not possible either because not() does not accept
4238 * a scalar.
4239 */
4240 shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n",
4241 src0_param.param_str, src1_param.param_str);
4242 break;
4243 case WINED3DSIH_SGE:
4244 /* Here we can use the step() function and safe a conditional */
4245 shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str);
4246 break;
4247 default:
4248 FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
4249 }
4250
4251 }
4252 }
4253
4254 static void shader_glsl_swapc(const struct wined3d_shader_instruction *ins)
4255 {
4256 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4257 struct wined3d_shader_dst_param dst[2];
4258 struct glsl_src_param src[3];
4259 unsigned int i, j, k;
4260 char mask_char[6];
4261 DWORD write_mask;
4262 BOOL tmp_dst[2];
4263
4264 for (i = 0; i < ins->dst_count; ++i)
4265 {
4266 tmp_dst[i] = FALSE;
4267 for (j = 0; j < ins->src_count; ++j)
4268 {
4269 if (ins->dst[i].reg.idx[0].offset == ins->src[j].reg.idx[0].offset
4270 && ins->dst[i].reg.type == ins->src[j].reg.type)
4271 tmp_dst[i] = TRUE;
4272 }
4273 }
4274
4275 dst[0] = ins->dst[0];
4276 dst[1] = ins->dst[1];
4277 for (i = 0; i < 4; ++i)
4278 {
4279 for (j = 0; j < ARRAY_SIZE(dst); ++j)
4280 {
4281 dst[j].write_mask = ins->dst[j].write_mask & (WINED3DSP_WRITEMASK_0 << i);
4282 if (tmp_dst[j] && (write_mask = shader_glsl_get_write_mask(&dst[j], mask_char)))
4283 shader_addline(buffer, "tmp%u%s = (", j, mask_char);
4284 else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst[j], dst[j].reg.data_type)))
4285 continue;
4286
4287 for (k = 0; k < ARRAY_SIZE(src); ++k)
4288 shader_glsl_add_src_param(ins, &ins->src[k], write_mask, &src[k]);
4289
4290 shader_addline(buffer, "%sbool(%s) ? %s : %s);\n", !j ? "!" : "",
4291 src[0].param_str, src[1].param_str, src[2].param_str);
4292 }
4293 }
4294
4295 for (i = 0; i < ARRAY_SIZE(tmp_dst); ++i)
4296 {
4297 if (tmp_dst[i])
4298 {
4299 shader_glsl_get_write_mask(&ins->dst[i], mask_char);
4300 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[i], ins->dst[i].reg.data_type);
4301 shader_addline(buffer, "tmp%u%s);\n", i, mask_char);
4302 }
4303 }
4304 }
4305
4306 static void shader_glsl_conditional_move(const struct wined3d_shader_instruction *ins)
4307 {
4308 const char *condition_prefix, *condition_suffix;
4309 struct wined3d_shader_dst_param dst;
4310 struct glsl_src_param src0_param;
4311 struct glsl_src_param src1_param;
4312 struct glsl_src_param src2_param;
4313 BOOL temp_destination = FALSE;
4314 DWORD cmp_channel = 0;
4315 unsigned int i, j;
4316 char mask_char[6];
4317 DWORD write_mask;
4318
4319 switch (ins->handler_idx)
4320 {
4321 case WINED3DSIH_CMP:
4322 condition_prefix = "";
4323 condition_suffix = " >= 0.0";
4324 break;
4325
4326 case WINED3DSIH_CND:
4327 condition_prefix = "";
4328 condition_suffix = " > 0.5";
4329 break;
4330
4331 case WINED3DSIH_MOVC:
4332 condition_prefix = "bool(";
4333 condition_suffix = ")";
4334 break;
4335
4336 default:
4337 FIXME("Unhandled instruction %#x.\n", ins->handler_idx);
4338 condition_prefix = "<unhandled prefix>";
4339 condition_suffix = "<unhandled suffix>";
4340 break;
4341 }
4342
4343 if (shader_is_scalar(&ins->dst[0].reg) || shader_is_scalar(&ins->src[0].reg))
4344 {
4345 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4346 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4347 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4348 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4349
4350 shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n",
4351 condition_prefix, src0_param.param_str, condition_suffix,
4352 src1_param.param_str, src2_param.param_str);
4353 return;
4354 }
4355
4356 dst = ins->dst[0];
4357
4358 /* Splitting the instruction up in multiple lines imposes a problem:
4359 * The first lines may overwrite source parameters of the following lines.
4360 * Deal with that by using a temporary destination register if needed. */
4361 if ((ins->src[0].reg.idx[0].offset == dst.reg.idx[0].offset
4362 && ins->src[0].reg.type == dst.reg.type)
4363 || (ins->src[1].reg.idx[0].offset == dst.reg.idx[0].offset
4364 && ins->src[1].reg.type == dst.reg.type)
4365 || (ins->src[2].reg.idx[0].offset == dst.reg.idx[0].offset
4366 && ins->src[2].reg.type == dst.reg.type))
4367 temp_destination = TRUE;
4368
4369 /* Cycle through all source0 channels. */
4370 for (i = 0; i < 4; ++i)
4371 {
4372 write_mask = 0;
4373 /* Find the destination channels which use the current source0 channel. */
4374 for (j = 0; j < 4; ++j)
4375 {
4376 if (shader_glsl_swizzle_get_component(ins->src[0].swizzle, j) == i)
4377 {
4378 write_mask |= WINED3DSP_WRITEMASK_0 << j;
4379 cmp_channel = WINED3DSP_WRITEMASK_0 << j;
4380 }
4381 }
4382 dst.write_mask = ins->dst[0].write_mask & write_mask;
4383
4384 if (temp_destination)
4385 {
4386 if (!(write_mask = shader_glsl_get_write_mask(&dst, mask_char)))
4387 continue;
4388 shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char);
4389 }
4390 else if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type)))
4391 continue;
4392
4393 shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param);
4394 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4395 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4396
4397 shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n",
4398 condition_prefix, src0_param.param_str, condition_suffix,
4399 src1_param.param_str, src2_param.param_str);
4400 }
4401
4402 if (temp_destination)
4403 {
4404 shader_glsl_get_write_mask(&ins->dst[0], mask_char);
4405 shader_glsl_append_dst(ins->ctx->buffer, ins);
4406 shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char);
4407 }
4408 }
4409
4410 /** Process the CND opcode in GLSL (dst = (src0 > 0.5) ? src1 : src2) */
4411 /* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4
4412 * the compare is done per component of src0. */
4413 static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
4414 {
4415 struct glsl_src_param src0_param;
4416 struct glsl_src_param src1_param;
4417 struct glsl_src_param src2_param;
4418 DWORD write_mask;
4419 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
4420 ins->ctx->reg_maps->shader_version.minor);
4421
4422 if (shader_version < WINED3D_SHADER_VERSION(1, 4))
4423 {
4424 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4425 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4426 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4427 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4428
4429 if (ins->coissue && ins->dst->write_mask != WINED3DSP_WRITEMASK_3)
4430 shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str);
4431 else
4432 shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n",
4433 src0_param.param_str, src1_param.param_str, src2_param.param_str);
4434 return;
4435 }
4436
4437 shader_glsl_conditional_move(ins);
4438 }
4439
4440 /** GLSL code generation for WINED3DSIO_MAD: Multiply the first 2 opcodes, then add the last */
4441 static void shader_glsl_mad(const struct wined3d_shader_instruction *ins)
4442 {
4443 struct glsl_src_param src0_param;
4444 struct glsl_src_param src1_param;
4445 struct glsl_src_param src2_param;
4446 DWORD write_mask;
4447
4448 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4449 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4450 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4451 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4452 shader_addline(ins->ctx->buffer, "(%s * %s) + %s);\n",
4453 src0_param.param_str, src1_param.param_str, src2_param.param_str);
4454 }
4455
4456 /* Handles transforming all WINED3DSIO_M?x? opcodes for
4457 Vertex shaders to GLSL codes */
4458 static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins)
4459 {
4460 int i;
4461 int nComponents = 0;
4462 struct wined3d_shader_dst_param tmp_dst = {{0}};
4463 struct wined3d_shader_src_param tmp_src[2] = {{{0}}};
4464 struct wined3d_shader_instruction tmp_ins;
4465
4466 memset(&tmp_ins, 0, sizeof(tmp_ins));
4467
4468 /* Set constants for the temporary argument */
4469 tmp_ins.ctx = ins->ctx;
4470 tmp_ins.dst_count = 1;
4471 tmp_ins.dst = &tmp_dst;
4472 tmp_ins.src_count = 2;
4473 tmp_ins.src = tmp_src;
4474
4475 switch(ins->handler_idx)
4476 {
4477 case WINED3DSIH_M4x4:
4478 nComponents = 4;
4479 tmp_ins.handler_idx = WINED3DSIH_DP4;
4480 break;
4481 case WINED3DSIH_M4x3:
4482 nComponents = 3;
4483 tmp_ins.handler_idx = WINED3DSIH_DP4;
4484 break;
4485 case WINED3DSIH_M3x4:
4486 nComponents = 4;
4487 tmp_ins.handler_idx = WINED3DSIH_DP3;
4488 break;
4489 case WINED3DSIH_M3x3:
4490 nComponents = 3;
4491 tmp_ins.handler_idx = WINED3DSIH_DP3;
4492 break;
4493 case WINED3DSIH_M3x2:
4494 nComponents = 2;
4495 tmp_ins.handler_idx = WINED3DSIH_DP3;
4496 break;
4497 default:
4498 break;
4499 }
4500
4501 tmp_dst = ins->dst[0];
4502 tmp_src[0] = ins->src[0];
4503 tmp_src[1] = ins->src[1];
4504 for (i = 0; i < nComponents; ++i)
4505 {
4506 tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i;
4507 shader_glsl_dot(&tmp_ins);
4508 ++tmp_src[1].reg.idx[0].offset;
4509 }
4510 }
4511
4512 /**
4513 The LRP instruction performs a component-wise linear interpolation
4514 between the second and third operands using the first operand as the
4515 blend factor. Equation: (dst = src2 + src0 * (src1 - src2))
4516 This is equivalent to mix(src2, src1, src0);
4517 */
4518 static void shader_glsl_lrp(const struct wined3d_shader_instruction *ins)
4519 {
4520 struct glsl_src_param src0_param;
4521 struct glsl_src_param src1_param;
4522 struct glsl_src_param src2_param;
4523 DWORD write_mask;
4524
4525 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4526
4527 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4528 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4529 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4530
4531 shader_addline(ins->ctx->buffer, "mix(%s, %s, %s));\n",
4532 src2_param.param_str, src1_param.param_str, src0_param.param_str);
4533 }
4534
4535 /** Process the WINED3DSIO_LIT instruction in GLSL:
4536 * dst.x = dst.w = 1.0
4537 * dst.y = (src0.x > 0) ? src0.x
4538 * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0
4539 * where src.w is clamped at +- 128
4540 */
4541 static void shader_glsl_lit(const struct wined3d_shader_instruction *ins)
4542 {
4543 struct glsl_src_param src0_param;
4544 struct glsl_src_param src1_param;
4545 struct glsl_src_param src3_param;
4546 char dst_mask[6];
4547
4548 shader_glsl_append_dst(ins->ctx->buffer, ins);
4549 shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
4550
4551 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4552 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src1_param);
4553 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src3_param);
4554
4555 /* The sdk specifies the instruction like this
4556 * dst.x = 1.0;
4557 * if(src.x > 0.0) dst.y = src.x
4558 * else dst.y = 0.0.
4559 * if(src.x > 0.0 && src.y > 0.0) dst.z = pow(src.y, power);
4560 * else dst.z = 0.0;
4561 * dst.w = 1.0;
4562 * (where power = src.w clamped between -128 and 128)
4563 *
4564 * Obviously that has quite a few conditionals in it which we don't like. So the first step is this:
4565 * dst.x = 1.0 ... No further explanation needed
4566 * dst.y = max(src.y, 0.0); ... If x < 0.0, use 0.0, otherwise x. Same as the conditional
4567 * dst.z = x > 0.0 ? pow(max(y, 0.0), p) : 0; ... 0 ^ power is 0, and otherwise we use y anyway
4568 * dst.w = 1.0. ... Nothing fancy.
4569 *
4570 * So we still have one conditional in there. So do this:
4571 * dst.z = pow(max(0.0, src.y) * step(0.0, src.x), power);
4572 *
4573 * step(0.0, x) will return 1 if src.x > 0.0, and 0 otherwise. So if y is 0 we get pow(0.0 * 1.0, power),
4574 * which sets dst.z to 0. If y > 0, but x = 0.0, we get pow(y * 0.0, power), which results in 0 too.
4575 * if both x and y are > 0, we get pow(y * 1.0, power), as it is supposed to.
4576 *
4577 * Unfortunately pow(0.0 ^ 0.0) returns NaN on most GPUs, but lit with src.y = 0 and src.w = 0 returns
4578 * a non-NaN value in dst.z. What we return doesn't matter, as long as it is not NaN. Return 0, which is
4579 * what all Windows HW drivers and GL_ARB_vertex_program's LIT do.
4580 */
4581 shader_addline(ins->ctx->buffer,
4582 "vec4(1.0, max(%s, 0.0), %s == 0.0 ? 0.0 : "
4583 "pow(max(0.0, %s) * step(0.0, %s), clamp(%s, -128.0, 128.0)), 1.0)%s);\n",
4584 src0_param.param_str, src3_param.param_str, src1_param.param_str,
4585 src0_param.param_str, src3_param.param_str, dst_mask);
4586 }
4587
4588 /** Process the WINED3DSIO_DST instruction in GLSL:
4589 * dst.x = 1.0
4590 * dst.y = src0.x * src0.y
4591 * dst.z = src0.z
4592 * dst.w = src1.w
4593 */
4594 static void shader_glsl_dst(const struct wined3d_shader_instruction *ins)
4595 {
4596 struct glsl_src_param src0y_param;
4597 struct glsl_src_param src0z_param;
4598 struct glsl_src_param src1y_param;
4599 struct glsl_src_param src1w_param;
4600 char dst_mask[6];
4601
4602 shader_glsl_append_dst(ins->ctx->buffer, ins);
4603 shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
4604
4605 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src0y_param);
4606 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &src0z_param);
4607 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_1, &src1y_param);
4608 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_3, &src1w_param);
4609
4610 shader_addline(ins->ctx->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n",
4611 src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask);
4612 }
4613
4614 /** Process the WINED3DSIO_SINCOS instruction in GLSL:
4615 * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware
4616 * can handle it. But, these functions are built-in for GLSL, so we can just ignore the last 2 params.
4617 *
4618 * dst.x = cos(src0.?)
4619 * dst.y = sin(src0.?)
4620 * dst.z = dst.z
4621 * dst.w = dst.w
4622 */
4623 static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins)
4624 {
4625 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4626 struct glsl_src_param src0_param;
4627 DWORD write_mask;
4628
4629 if (ins->ctx->reg_maps->shader_version.major < 4)
4630 {
4631 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4632
4633 write_mask = shader_glsl_append_dst(buffer, ins);
4634 switch (write_mask)
4635 {
4636 case WINED3DSP_WRITEMASK_0:
4637 shader_addline(buffer, "cos(%s));\n", src0_param.param_str);
4638 break;
4639
4640 case WINED3DSP_WRITEMASK_1:
4641 shader_addline(buffer, "sin(%s));\n", src0_param.param_str);
4642 break;
4643
4644 case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1):
4645 shader_addline(buffer, "vec2(cos(%s), sin(%s)));\n",
4646 src0_param.param_str, src0_param.param_str);
4647 break;
4648
4649 default:
4650 ERR("Write mask should be .x, .y or .xy\n");
4651 break;
4652 }
4653
4654 return;
4655 }
4656
4657 if (ins->dst[0].reg.type != WINED3DSPR_NULL)
4658 {
4659
4660 if (ins->dst[1].reg.type != WINED3DSPR_NULL)
4661 {
4662 char dst_mask[6];
4663
4664 write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
4665 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4666 shader_addline(buffer, "tmp0%s = sin(%s);\n", dst_mask, src0_param.param_str);
4667
4668 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
4669 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4670 shader_addline(buffer, "cos(%s));\n", src0_param.param_str);
4671
4672 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type);
4673 shader_addline(buffer, "tmp0%s);\n", dst_mask);
4674 }
4675 else
4676 {
4677 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type);
4678 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4679 shader_addline(buffer, "sin(%s));\n", src0_param.param_str);
4680 }
4681 }
4682 else if (ins->dst[1].reg.type != WINED3DSPR_NULL)
4683 {
4684 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
4685 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4686 shader_addline(buffer, "cos(%s));\n", src0_param.param_str);
4687 }
4688 }
4689
4690 /* sgn in vs_2_0 has 2 extra parameters(registers for temporary storage) which we don't use
4691 * here. But those extra parameters require a dedicated function for sgn, since map2gl would
4692 * generate invalid code
4693 */
4694 static void shader_glsl_sgn(const struct wined3d_shader_instruction *ins)
4695 {
4696 struct glsl_src_param src0_param;
4697 DWORD write_mask;
4698
4699 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4700 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4701
4702 shader_addline(ins->ctx->buffer, "sign(%s));\n", src0_param.param_str);
4703 }
4704
4705 /** Process the WINED3DSIO_LOOP instruction in GLSL:
4706 * Start a for() loop where src1.y is the initial value of aL,
4707 * increment aL by src1.z for a total of src1.x iterations.
4708 * Need to use a temporary variable for this operation.
4709 */
4710 /* FIXME: I don't think nested loops will work correctly this way. */
4711 static void shader_glsl_loop(const struct wined3d_shader_instruction *ins)
4712 {
4713 struct wined3d_shader_parser_state *state = ins->ctx->state;
4714 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4715 const struct wined3d_shader *shader = ins->ctx->shader;
4716 const struct wined3d_shader_lconst *constant;
4717 struct glsl_src_param src1_param;
4718 const DWORD *control_values = NULL;
4719
4720 if (ins->ctx->reg_maps->shader_version.major < 4)
4721 {
4722 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
4723
4724 /* Try to hardcode the loop control parameters if possible. Direct3D 9
4725 * class hardware doesn't support real varying indexing, but Microsoft
4726 * designed this feature for Shader model 2.x+. If the loop control is
4727 * known at compile time, the GLSL compiler can unroll the loop, and
4728 * replace indirect addressing with direct addressing. */
4729 if (ins->src[1].reg.type == WINED3DSPR_CONSTINT)
4730 {
4731 LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry)
4732 {
4733 if (constant->idx == ins->src[1].reg.idx[0].offset)
4734 {
4735 control_values = constant->value;
4736 break;
4737 }
4738 }
4739 }
4740
4741 if (control_values)
4742 {
4743 struct wined3d_shader_loop_control loop_control;
4744 loop_control.count = control_values[0];
4745 loop_control.start = control_values[1];
4746 loop_control.step = (int)control_values[2];
4747
4748 if (loop_control.step > 0)
4749 {
4750 shader_addline(buffer, "for (aL%u = %u; aL%u < (%u * %d + %u); aL%u += %d)\n{\n",
4751 state->current_loop_depth, loop_control.start,
4752 state->current_loop_depth, loop_control.count, loop_control.step, loop_control.start,
4753 state->current_loop_depth, loop_control.step);
4754 }
4755 else if (loop_control.step < 0)
4756 {
4757 shader_addline(buffer, "for (aL%u = %u; aL%u > (%u * %d + %u); aL%u += %d)\n{\n",
4758 state->current_loop_depth, loop_control.start,
4759 state->current_loop_depth, loop_control.count, loop_control.step, loop_control.start,
4760 state->current_loop_depth, loop_control.step);
4761 }
4762 else
4763 {
4764 shader_addline(buffer, "for (aL%u = %u, tmpInt%u = 0; tmpInt%u < %u; tmpInt%u++)\n{\n",
4765 state->current_loop_depth, loop_control.start, state->current_loop_depth,
4766 state->current_loop_depth, loop_control.count,
4767 state->current_loop_depth);
4768 }
4769 }
4770 else
4771 {
4772 shader_addline(buffer, "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z)\n{\n",
4773 state->current_loop_depth, state->current_loop_reg,
4774 src1_param.reg_name, state->current_loop_depth, src1_param.reg_name,
4775 state->current_loop_depth, state->current_loop_reg, src1_param.reg_name);
4776 }
4777
4778 ++state->current_loop_reg;
4779 }
4780 else
4781 {
4782 shader_addline(buffer, "for (;;)\n{\n");
4783 }
4784
4785 ++state->current_loop_depth;
4786 }
4787
4788 static void shader_glsl_end(const struct wined3d_shader_instruction *ins)
4789 {
4790 struct wined3d_shader_parser_state *state = ins->ctx->state;
4791
4792 shader_addline(ins->ctx->buffer, "}\n");
4793
4794 if (ins->handler_idx == WINED3DSIH_ENDLOOP)
4795 {
4796 --state->current_loop_depth;
4797 --state->current_loop_reg;
4798 }
4799
4800 if (ins->handler_idx == WINED3DSIH_ENDREP)
4801 {
4802 --state->current_loop_depth;
4803 }
4804 }
4805
4806 static void shader_glsl_rep(const struct wined3d_shader_instruction *ins)
4807 {
4808 struct wined3d_shader_parser_state *state = ins->ctx->state;
4809 const struct wined3d_shader *shader = ins->ctx->shader;
4810 const struct wined3d_shader_lconst *constant;
4811 struct glsl_src_param src0_param;
4812 const DWORD *control_values = NULL;
4813
4814 /* Try to hardcode local values to help the GLSL compiler to unroll and optimize the loop */
4815 if (ins->src[0].reg.type == WINED3DSPR_CONSTINT)
4816 {
4817 LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry)
4818 {
4819 if (constant->idx == ins->src[0].reg.idx[0].offset)
4820 {
4821 control_values = constant->value;
4822 break;
4823 }
4824 }
4825 }
4826
4827 if (control_values)
4828 {
4829 shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %d; tmpInt%d++) {\n",
4830 state->current_loop_depth, state->current_loop_depth,
4831 control_values[0], state->current_loop_depth);
4832 }
4833 else
4834 {
4835 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4836 shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n",
4837 state->current_loop_depth, state->current_loop_depth,
4838 src0_param.param_str, state->current_loop_depth);
4839 }
4840
4841 ++state->current_loop_depth;
4842 }
4843
4844 static void shader_glsl_switch(const struct wined3d_shader_instruction *ins)
4845 {
4846 struct glsl_src_param src0_param;
4847
4848 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4849 shader_addline(ins->ctx->buffer, "switch (%s)\n{\n", src0_param.param_str);
4850 }
4851
4852 static void shader_glsl_case(const struct wined3d_shader_instruction *ins)
4853 {
4854 struct glsl_src_param src0_param;
4855
4856 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4857 shader_addline(ins->ctx->buffer, "case %s:\n", src0_param.param_str);
4858 }
4859
4860 static void shader_glsl_default(const struct wined3d_shader_instruction *ins)
4861 {
4862 shader_addline(ins->ctx->buffer, "default:\n");
4863 }
4864
4865 static void shader_glsl_generate_conditional_op(const struct wined3d_shader_instruction *ins,
4866 const char *op)
4867 {
4868 struct glsl_src_param src_param;
4869 const char *condition;
4870
4871 condition = ins->flags == WINED3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool";
4872 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param);
4873 shader_addline(ins->ctx->buffer, "if (%s(%s)) %s\n", condition, src_param.param_str, op);
4874 }
4875
4876 static void shader_glsl_if(const struct wined3d_shader_instruction *ins)
4877 {
4878 shader_glsl_generate_conditional_op(ins, "{");
4879 }
4880
4881 static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins)
4882 {
4883 struct glsl_src_param src0_param;
4884 struct glsl_src_param src1_param;
4885
4886 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4887 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
4888
4889 shader_addline(ins->ctx->buffer, "if (%s %s %s) {\n",
4890 src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str);
4891 }
4892
4893 static void shader_glsl_else(const struct wined3d_shader_instruction *ins)
4894 {
4895 shader_addline(ins->ctx->buffer, "} else {\n");
4896 }
4897
4898 static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
4899 {
4900 unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset;
4901
4902 shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n");
4903 if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL])
4904 shader_glsl_fixup_position(ins->ctx->buffer);
4905
4906 if (!stream)
4907 shader_addline(ins->ctx->buffer, "EmitVertex();\n");
4908 else
4909 FIXME("Unhandled primitive stream %u.\n", stream);
4910 }
4911
4912 static void shader_glsl_break(const struct wined3d_shader_instruction *ins)
4913 {
4914 shader_addline(ins->ctx->buffer, "break;\n");
4915 }
4916
4917 /* FIXME: According to MSDN the compare is done per component. */
4918 static void shader_glsl_breakc(const struct wined3d_shader_instruction *ins)
4919 {
4920 struct glsl_src_param src0_param;
4921 struct glsl_src_param src1_param;
4922
4923 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4924 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
4925
4926 shader_addline(ins->ctx->buffer, "if (%s %s %s) break;\n",
4927 src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str);
4928 }
4929
4930 static void shader_glsl_conditional_op(const struct wined3d_shader_instruction *ins)
4931 {
4932 const char *op;
4933
4934 switch (ins->handler_idx)
4935 {
4936 case WINED3DSIH_BREAKP: op = "break;"; break;
4937 case WINED3DSIH_CONTINUEP: op = "continue;"; break;
4938 case WINED3DSIH_RETP: op = "return;"; break;
4939 default:
4940 ERR("Unhandled opcode %#x.\n", ins->handler_idx);
4941 return;
4942 }
4943
4944 shader_glsl_generate_conditional_op(ins, op);
4945 }
4946
4947 static void shader_glsl_continue(const struct wined3d_shader_instruction *ins)
4948 {
4949 shader_addline(ins->ctx->buffer, "continue;\n");
4950 }
4951
4952 static void shader_glsl_label(const struct wined3d_shader_instruction *ins)
4953 {
4954 shader_addline(ins->ctx->buffer, "}\n");
4955 shader_addline(ins->ctx->buffer, "void subroutine%u()\n{\n", ins->src[0].reg.idx[0].offset);
4956
4957 /* Subroutines appear at the end of the shader. */
4958 ins->ctx->state->in_subroutine = TRUE;
4959 }
4960
4961 static void shader_glsl_call(const struct wined3d_shader_instruction *ins)
4962 {
4963 shader_addline(ins->ctx->buffer, "subroutine%u();\n", ins->src[0].reg.idx[0].offset);
4964 }
4965
4966 static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins)
4967 {
4968 struct glsl_src_param src1_param;
4969
4970 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
4971 shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n",
4972 src1_param.param_str, ins->src[0].reg.idx[0].offset);
4973 }
4974
4975 static void shader_glsl_ret(const struct wined3d_shader_instruction *ins)
4976 {
4977 const struct wined3d_shader_version *version = &ins->ctx->shader->reg_maps.shader_version;
4978
4979 if (version->major >= 4 && !ins->ctx->state->in_subroutine)
4980 {
4981 shader_glsl_generate_shader_epilogue(ins->ctx);
4982 shader_addline(ins->ctx->buffer, "return;\n");
4983 }
4984 }
4985
4986 static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
4987 {
4988 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
4989 ins->ctx->reg_maps->shader_version.minor);
4990 struct glsl_sample_function sample_function;
4991 DWORD sample_flags = 0;
4992 DWORD resource_idx;
4993 DWORD mask = 0, swizzle;
4994 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
4995
4996 /* 1.0-1.4: Use destination register as sampler source.
4997 * 2.0+: Use provided sampler source. */
4998 if (shader_version < WINED3D_SHADER_VERSION(2,0))
4999 resource_idx = ins->dst[0].reg.idx[0].offset;
5000 else
5001 resource_idx = ins->src[1].reg.idx[0].offset;
5002
5003 if (shader_version < WINED3D_SHADER_VERSION(1,4))
5004 {
5005 DWORD flags = (priv->cur_ps_args->tex_transform >> resource_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)
5006 & WINED3D_PSARGS_TEXTRANSFORM_MASK;
5007 enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type;
5008
5009 /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */
5010 if (flags & WINED3D_PSARGS_PROJECTED && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
5011 {
5012 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
5013 switch (flags & ~WINED3D_PSARGS_PROJECTED)
5014 {
5015 case WINED3D_TTFF_COUNT1:
5016 FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n");
5017 break;
5018 case WINED3D_TTFF_COUNT2:
5019 mask = WINED3DSP_WRITEMASK_1;
5020 break;
5021 case WINED3D_TTFF_COUNT3:
5022 mask = WINED3DSP_WRITEMASK_2;
5023 break;
5024 case WINED3D_TTFF_COUNT4:
5025 case WINED3D_TTFF_DISABLE:
5026 mask = WINED3DSP_WRITEMASK_3;
5027 break;
5028 }
5029 }
5030 }
5031 else if (shader_version < WINED3D_SHADER_VERSION(2,0))
5032 {
5033 enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers;
5034
5035 if (src_mod == WINED3DSPSM_DZ) {
5036 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
5037 mask = WINED3DSP_WRITEMASK_2;
5038 } else if (src_mod == WINED3DSPSM_DW) {
5039 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
5040 mask = WINED3DSP_WRITEMASK_3;
5041 }
5042 }
5043 else
5044 {
5045 if ((ins->flags & WINED3DSI_TEXLD_PROJECT)
5046 && ins->ctx->reg_maps->resource_info[resource_idx].type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
5047 {
5048 /* ps 2.0 texldp instruction always divides by the fourth component. */
5049 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
5050 mask = WINED3DSP_WRITEMASK_3;
5051 }
5052 }
5053
5054 shader_glsl_get_sample_function(ins->ctx, resource_idx, resource_idx, sample_flags, &sample_function);
5055 mask |= sample_function.coord_mask;
5056 sample_function.coord_mask = mask;
5057
5058 if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE;
5059 else swizzle = ins->src[1].swizzle;
5060
5061 /* 1.0-1.3: Use destination register as coordinate source.
5062 1.4+: Use provided coordinate source register. */
5063 if (shader_version < WINED3D_SHADER_VERSION(1,4))
5064 {
5065 char coord_mask[6];
5066 shader_glsl_write_mask_to_str(mask, coord_mask);
5067 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL,
5068 "T%u%s", resource_idx, coord_mask);
5069 }
5070 else
5071 {
5072 struct glsl_src_param coord_param;
5073 shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param);
5074 if (ins->flags & WINED3DSI_TEXLD_BIAS)
5075 {
5076 struct glsl_src_param bias;
5077 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias);
5078 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, bias.param_str,
5079 NULL, "%s", coord_param.param_str);
5080 } else {
5081 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL,
5082 "%s", coord_param.param_str);
5083 }
5084 }
5085 shader_glsl_release_sample_function(ins->ctx, &sample_function);
5086 }
5087
5088 static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
5089 {
5090 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
5091 struct glsl_src_param coord_param, dx_param, dy_param;
5092 struct glsl_sample_function sample_function;
5093 DWORD sampler_idx;
5094 DWORD swizzle = ins->src[1].swizzle;
5095
5096 if (!shader_glsl_has_core_grad(gl_info) && !gl_info->supported[ARB_SHADER_TEXTURE_LOD])
5097 {
5098 FIXME("texldd used, but not supported by hardware. Falling back to regular tex.\n");
5099 shader_glsl_tex(ins);
5100 return;
5101 }
5102
5103 sampler_idx = ins->src[1].reg.idx[0].offset;
5104
5105 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_GRAD, &sample_function);
5106 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
5107 shader_glsl_add_src_param(ins, &ins->src[2], sample_function.deriv_mask, &dx_param);
5108 shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dy_param);
5109
5110 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str,
5111 NULL, NULL, "%s", coord_param.param_str);
5112 shader_glsl_release_sample_function(ins->ctx, &sample_function);
5113 }
5114
5115 static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
5116 {
5117 const struct wined3d_shader_version *shader_version = &ins->ctx->reg_maps->shader_version;
5118 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
5119 struct glsl_src_param coord_param, lod_param;
5120 struct glsl_sample_function sample_function;
5121 DWORD swizzle = ins->src[1].swizzle;
5122 DWORD sampler_idx;
5123
5124 sampler_idx = ins->src[1].reg.idx[0].offset;
5125
5126 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_LOD, &sample_function);
5127 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
5128
5129 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
5130
5131 if (shader_version->type == WINED3D_SHADER_TYPE_PIXEL && !shader_glsl_has_core_grad(gl_info)
5132 && !gl_info->supported[ARB_SHADER_TEXTURE_LOD])
5133 {
5134 /* Plain GLSL only supports Lod sampling functions in vertex shaders.
5135 * However, the NVIDIA drivers allow them in fragment shaders as well,
5136 * even without the appropriate extension. */
5137 WARN("Using %s in fragment shader.\n", sample_function.name->buffer);
5138 }
5139 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str, NULL,
5140 "%s", coord_param.param_str);
5141 shader_glsl_release_sample_function(ins->ctx, &sample_function);
5142 }
5143
5144 static unsigned int shader_glsl_find_sampler(const struct wined3d_shader_sampler_map *sampler_map,
5145 unsigned int resource_idx, unsigned int sampler_idx)
5146 {
5147 struct wined3d_shader_sampler_map_entry *entries = sampler_map->entries;
5148 unsigned int i;
5149
5150 for (i = 0; i < sampler_map->count; ++i)
5151 {
5152 if (entries[i].resource_idx == resource_idx && entries[i].sampler_idx == sampler_idx)
5153 return entries[i].bind_idx;
5154 }
5155
5156 ERR("No GLSL sampler found for resource %u / sampler %u.\n", resource_idx, sampler_idx);
5157
5158 return ~0u;
5159 }
5160
5161 static void shader_glsl_atomic(const struct wined3d_shader_instruction *ins)
5162 {
5163 const BOOL is_imm_instruction = WINED3DSIH_IMM_ATOMIC_AND <= ins->handler_idx
5164 && ins->handler_idx <= WINED3DSIH_IMM_ATOMIC_XOR;
5165 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5166 const struct wined3d_shader_version *version = &reg_maps->shader_version;
5167 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
5168 struct glsl_src_param structure_idx, offset, data, data2;
5169 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5170 enum wined3d_shader_resource_type resource_type;
5171 struct wined3d_string_buffer *address;
5172 enum wined3d_data_type data_type;
5173 unsigned int resource_idx, stride;
5174 const char *op, *resource;
5175 DWORD coord_mask;
5176 BOOL is_tgsm;
5177
5178 resource_idx = ins->dst[is_imm_instruction].reg.idx[0].offset;
5179 is_tgsm = ins->dst[is_imm_instruction].reg.type == WINED3DSPR_GROUPSHAREDMEM;
5180 if (is_tgsm)
5181 {
5182 if (resource_idx >= reg_maps->tgsm_count)
5183 {
5184 ERR("Invalid TGSM index %u.\n", resource_idx);
5185 return;
5186 }
5187 resource = "g";
5188 data_type = WINED3D_DATA_UINT;
5189 coord_mask = 1;
5190 stride = reg_maps->tgsm[resource_idx].stride;
5191 }
5192 else
5193 {
5194 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info))
5195 {
5196 ERR("Invalid UAV index %u.\n", resource_idx);
5197 return;
5198 }
5199 resource_type = reg_maps->uav_resource_info[resource_idx].type;
5200 if (resource_type >= ARRAY_SIZE(resource_type_info))
5201 {
5202 ERR("Unexpected resource type %#x.\n", resource_type);
5203 return;
5204 }
5205 resource = "image";
5206 data_type = reg_maps->uav_resource_info[resource_idx].data_type;
5207 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1;
5208 stride = reg_maps->uav_resource_info[resource_idx].stride;
5209 }
5210
5211 switch (ins->handler_idx)
5212 {
5213 case WINED3DSIH_ATOMIC_AND:
5214 case WINED3DSIH_IMM_ATOMIC_AND:
5215 if (is_tgsm)
5216 op = "atomicAnd";
5217 else
5218 op = "imageAtomicAnd";
5219 break;
5220 case WINED3DSIH_ATOMIC_CMP_STORE:
5221 case WINED3DSIH_IMM_ATOMIC_CMP_EXCH:
5222 if (is_tgsm)
5223 op = "atomicCompSwap";
5224 else
5225 op = "imageAtomicCompSwap";
5226 break;
5227 case WINED3DSIH_ATOMIC_IADD:
5228 case WINED3DSIH_IMM_ATOMIC_IADD:
5229 if (is_tgsm)
5230 op = "atomicAdd";
5231 else
5232 op = "imageAtomicAdd";
5233 break;
5234 case WINED3DSIH_ATOMIC_IMAX:
5235 case WINED3DSIH_IMM_ATOMIC_IMAX:
5236 if (is_tgsm)
5237 op = "atomicMax";
5238 else
5239 op = "imageAtomicMax";
5240 if (data_type != WINED3D_DATA_INT)
5241 {
5242 FIXME("Unhandled opcode %#x for unsigned integers.\n", ins->handler_idx);
5243 return;
5244 }
5245 break;
5246 case WINED3DSIH_ATOMIC_IMIN:
5247 case WINED3DSIH_IMM_ATOMIC_IMIN:
5248 if (is_tgsm)
5249 op = "atomicMin";
5250 else
5251 op = "imageAtomicMin";
5252 if (data_type != WINED3D_DATA_INT)
5253 {
5254 FIXME("Unhandled opcode %#x for unsigned integers.\n", ins->handler_idx);
5255 return;
5256 }
5257 break;
5258 case WINED3DSIH_ATOMIC_OR:
5259 case WINED3DSIH_IMM_ATOMIC_OR:
5260 if (is_tgsm)
5261 op = "atomicOr";
5262 else
5263 op = "imageAtomicOr";
5264 break;
5265 case WINED3DSIH_ATOMIC_UMAX:
5266 case WINED3DSIH_IMM_ATOMIC_UMAX:
5267 if (is_tgsm)
5268 op = "atomicMax";
5269 else
5270 op = "imageAtomicMax";
5271 if (data_type != WINED3D_DATA_UINT)
5272 {
5273 FIXME("Unhandled opcode %#x for signed integers.\n", ins->handler_idx);
5274 return;
5275 }
5276 break;
5277 case WINED3DSIH_ATOMIC_UMIN:
5278 case WINED3DSIH_IMM_ATOMIC_UMIN:
5279 if (is_tgsm)
5280 op = "atomicMin";
5281 else
5282 op = "imageAtomicMin";
5283 if (data_type != WINED3D_DATA_UINT)
5284 {
5285 FIXME("Unhandled opcode %#x for signed integers.\n", ins->handler_idx);
5286 return;
5287 }
5288 break;
5289 case WINED3DSIH_ATOMIC_XOR:
5290 case WINED3DSIH_IMM_ATOMIC_XOR:
5291 if (is_tgsm)
5292 op = "atomicXor";
5293 else
5294 op = "imageAtomicXor";
5295 break;
5296 case WINED3DSIH_IMM_ATOMIC_EXCH:
5297 if (is_tgsm)
5298 op = "atomicExchange";
5299 else
5300 op = "imageAtomicExchange";
5301 break;
5302 default:
5303 ERR("Unhandled opcode %#x.\n", ins->handler_idx);
5304 return;
5305 }
5306
5307 address = string_buffer_get(priv->string_buffers);
5308 if (stride)
5309 {
5310 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &structure_idx);
5311 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &offset);
5312 string_buffer_sprintf(address, "%s * %u + %s / 4", structure_idx.param_str, stride, offset.param_str);
5313 }
5314 else
5315 {
5316 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &offset);
5317 string_buffer_sprintf(address, "%s", offset.param_str);
5318 if (is_tgsm || (reg_maps->uav_resource_info[resource_idx].flags & WINED3D_VIEW_BUFFER_RAW))
5319 shader_addline(address, "/ 4");
5320 }
5321
5322 if (is_imm_instruction)
5323 shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], data_type);
5324
5325 if (is_tgsm)
5326 shader_addline(buffer, "%s(%s_%s%u[%s], ",
5327 op, shader_glsl_get_prefix(version->type), resource, resource_idx, address->buffer);
5328 else
5329 shader_addline(buffer, "%s(%s_%s%u, %s, ",
5330 op, shader_glsl_get_prefix(version->type), resource, resource_idx, address->buffer);
5331
5332 shader_glsl_add_src_param_ext(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &data, data_type);
5333 shader_addline(buffer, "%s", data.param_str);
5334 if (ins->src_count >= 3)
5335 {
5336 shader_glsl_add_src_param_ext(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &data2, data_type);
5337 shader_addline(buffer, ", %s", data2.param_str);
5338 }
5339
5340 if (is_imm_instruction)
5341 shader_addline(buffer, ")");
5342 shader_addline(buffer, ");\n");
5343
5344 string_buffer_release(priv->string_buffers, address);
5345 }
5346
5347 static void shader_glsl_uav_counter(const struct wined3d_shader_instruction *ins)
5348 {
5349 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type);
5350 const char *op;
5351
5352 if (ins->handler_idx == WINED3DSIH_IMM_ATOMIC_ALLOC)
5353 op = "atomicCounterIncrement";
5354 else
5355 op = "atomicCounterDecrement";
5356
5357 shader_glsl_append_dst(ins->ctx->buffer, ins);
5358 shader_addline(ins->ctx->buffer, "%s(%s_counter%u));\n", op, prefix, ins->src[0].reg.idx[0].offset);
5359 }
5360
5361 static void shader_glsl_ld_uav(const struct wined3d_shader_instruction *ins)
5362 {
5363 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5364 const struct wined3d_shader_version *version = &reg_maps->shader_version;
5365 enum wined3d_shader_resource_type resource_type;
5366 struct glsl_src_param image_coord_param;
5367 enum wined3d_data_type data_type;
5368 DWORD coord_mask, write_mask;
5369 unsigned int uav_idx;
5370 char dst_swizzle[6];
5371
5372 uav_idx = ins->src[1].reg.idx[0].offset;
5373 if (uav_idx >= ARRAY_SIZE(reg_maps->uav_resource_info))
5374 {
5375 ERR("Invalid UAV index %u.\n", uav_idx);
5376 return;
5377 }
5378 resource_type = reg_maps->uav_resource_info[uav_idx].type;
5379 if (resource_type >= ARRAY_SIZE(resource_type_info))
5380 {
5381 ERR("Unexpected resource type %#x.\n", resource_type);
5382 resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D;
5383 }
5384 data_type = reg_maps->uav_resource_info[uav_idx].data_type;
5385 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1;
5386
5387 write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], data_type);
5388 shader_glsl_get_swizzle(&ins->src[1], FALSE, write_mask, dst_swizzle);
5389
5390 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &image_coord_param);
5391 shader_addline(ins->ctx->buffer, "imageLoad(%s_image%u, %s)%s);\n",
5392 shader_glsl_get_prefix(version->type), uav_idx, image_coord_param.param_str, dst_swizzle);
5393 }
5394
5395 static void shader_glsl_ld_raw_structured(const struct wined3d_shader_instruction *ins)
5396 {
5397 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type);
5398 const struct wined3d_shader_src_param *src = &ins->src[ins->src_count - 1];
5399 unsigned int i, swizzle, resource_idx, bind_idx, stride, src_idx = 0;
5400 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5401 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
5402 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5403 struct glsl_src_param structure_idx, offset;
5404 struct wined3d_string_buffer *address;
5405 struct wined3d_shader_dst_param dst;
5406 const char *function, *resource;
5407
5408 resource_idx = src->reg.idx[0].offset;
5409 if (src->reg.type == WINED3DSPR_RESOURCE)
5410 {
5411 if (resource_idx >= ARRAY_SIZE(reg_maps->resource_info))
5412 {
5413 ERR("Invalid resource index %u.\n", resource_idx);
5414 return;
5415 }
5416 stride = reg_maps->resource_info[resource_idx].stride;
5417 bind_idx = shader_glsl_find_sampler(&reg_maps->sampler_map, resource_idx, WINED3D_SAMPLER_DEFAULT);
5418 function = "texelFetch";
5419 resource = "sampler";
5420 }
5421 else if (src->reg.type == WINED3DSPR_UAV)
5422 {
5423 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info))
5424 {
5425 ERR("Invalid UAV index %u.\n", resource_idx);
5426 return;
5427 }
5428 stride = reg_maps->uav_resource_info[resource_idx].stride;
5429 bind_idx = resource_idx;
5430 function = "imageLoad";
5431 resource = "image";
5432 }
5433 else
5434 {
5435 if (resource_idx >= reg_maps->tgsm_count)
5436 {
5437 ERR("Invalid TGSM index %u.\n", resource_idx);
5438 return;
5439 }
5440 stride = reg_maps->tgsm[resource_idx].stride;
5441 bind_idx = resource_idx;
5442 function = NULL;
5443 resource = "g";
5444 }
5445
5446 address = string_buffer_get(priv->string_buffers);
5447 if (ins->handler_idx == WINED3DSIH_LD_STRUCTURED)
5448 {
5449 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &structure_idx);
5450 shader_addline(address, "%s * %u + ", structure_idx.param_str, stride);
5451 }
5452 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &offset);
5453 shader_addline(address, "%s / 4", offset.param_str);
5454
5455 dst = ins->dst[0];
5456 if (shader_glsl_get_write_mask_size(dst.write_mask) > 1)
5457 {
5458 /* The instruction is split into multiple lines. The first lines may
5459 * overwrite source parameters of the following lines. */
5460 shader_addline(buffer, "tmp0.x = intBitsToFloat(%s);\n", address->buffer);
5461 string_buffer_sprintf(address, "floatBitsToInt(tmp0.x)");
5462 }
5463
5464 for (i = 0; i < 4; ++i)
5465 {
5466 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i);
5467 if (!shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type))
5468 continue;
5469
5470 swizzle = shader_glsl_swizzle_get_component(src->swizzle, i);
5471 if (function)
5472 shader_addline(buffer, "%s(%s_%s%u, %s + %u).x);\n",
5473 function, prefix, resource, bind_idx, address->buffer, swizzle);
5474 else
5475 shader_addline(buffer, "%s_%s%u[%s + %u]);\n",
5476 prefix, resource, bind_idx, address->buffer, swizzle);
5477 }
5478
5479 string_buffer_release(priv->string_buffers, address);
5480 }
5481
5482 static void shader_glsl_store_uav(const struct wined3d_shader_instruction *ins)
5483 {
5484 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5485 const struct wined3d_shader_version *version = &reg_maps->shader_version;
5486 struct glsl_src_param image_coord_param, image_data_param;
5487 enum wined3d_shader_resource_type resource_type;
5488 enum wined3d_data_type data_type;
5489 unsigned int uav_idx;
5490 DWORD coord_mask;
5491
5492 uav_idx = ins->dst[0].reg.idx[0].offset;
5493 if (uav_idx >= ARRAY_SIZE(reg_maps->uav_resource_info))
5494 {
5495 ERR("Invalid UAV index %u.\n", uav_idx);
5496 return;
5497 }
5498 resource_type = reg_maps->uav_resource_info[uav_idx].type;
5499 if (resource_type >= ARRAY_SIZE(resource_type_info))
5500 {
5501 ERR("Unexpected resource type %#x.\n", resource_type);
5502 return;
5503 }
5504 data_type = reg_maps->uav_resource_info[uav_idx].data_type;
5505 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1;
5506
5507 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &image_coord_param);
5508 shader_glsl_add_src_param_ext(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &image_data_param, data_type);
5509 shader_addline(ins->ctx->buffer, "imageStore(%s_image%u, %s, %s);\n",
5510 shader_glsl_get_prefix(version->type), uav_idx,
5511 image_coord_param.param_str, image_data_param.param_str);
5512 }
5513
5514 static void shader_glsl_store_raw_structured(const struct wined3d_shader_instruction *ins)
5515 {
5516 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type);
5517 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5518 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
5519 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5520 struct glsl_src_param structure_idx, offset, data;
5521 unsigned int i, resource_idx, stride, src_idx = 0;
5522 struct wined3d_string_buffer *address;
5523 DWORD write_mask;
5524 BOOL is_tgsm;
5525
5526 resource_idx = ins->dst[0].reg.idx[0].offset;
5527 is_tgsm = ins->dst[0].reg.type == WINED3DSPR_GROUPSHAREDMEM;
5528 if (is_tgsm)
5529 {
5530 if (resource_idx >= reg_maps->tgsm_count)
5531 {
5532 ERR("Invalid TGSM index %u.\n", resource_idx);
5533 return;
5534 }
5535 stride = reg_maps->tgsm[resource_idx].stride;
5536 }
5537 else
5538 {
5539 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info))
5540 {
5541 ERR("Invalid UAV index %u.\n", resource_idx);
5542 return;
5543 }
5544 stride = reg_maps->uav_resource_info[resource_idx].stride;
5545 }
5546
5547 address = string_buffer_get(priv->string_buffers);
5548 if (ins->handler_idx == WINED3DSIH_STORE_STRUCTURED)
5549 {
5550 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &structure_idx);
5551 shader_addline(address, "%s * %u + ", structure_idx.param_str, stride);
5552 }
5553 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &offset);
5554 shader_addline(address, "%s / 4", offset.param_str);
5555
5556 for (i = 0; i < 4; ++i)
5557 {
5558 if (!(write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i)))
5559 continue;
5560
5561 shader_glsl_add_src_param(ins, &ins->src[src_idx], write_mask, &data);
5562
5563 if (is_tgsm)
5564 shader_addline(buffer, "%s_g%u[%s + %u] = %s;\n",
5565 prefix, resource_idx, address->buffer, i, data.param_str);
5566 else
5567 shader_addline(buffer, "imageStore(%s_image%u, %s + %u, uvec4(%s, 0, 0, 0));\n",
5568 prefix, resource_idx, address->buffer, i, data.param_str);
5569 }
5570
5571 string_buffer_release(priv->string_buffers, address);
5572 }
5573
5574 static void shader_glsl_sync(const struct wined3d_shader_instruction *ins)
5575 {
5576 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5577 unsigned int sync_flags = ins->flags;
5578
5579 if (sync_flags & WINED3DSSF_THREAD_GROUP)
5580 {
5581 shader_addline(buffer, "barrier();\n");
5582 sync_flags &= ~(WINED3DSSF_THREAD_GROUP | WINED3DSSF_GROUP_SHARED_MEMORY);
5583 }
5584
5585 if (sync_flags & WINED3DSSF_GROUP_SHARED_MEMORY)
5586 {
5587 shader_addline(buffer, "memoryBarrierShared();\n");
5588 sync_flags &= ~WINED3DSSF_GROUP_SHARED_MEMORY;
5589 }
5590
5591 if (sync_flags)
5592 FIXME("Unhandled sync flags %#x.\n", sync_flags);
5593 }
5594
5595 static const struct wined3d_shader_resource_info *shader_glsl_get_resource_info(
5596 const struct wined3d_shader_instruction *ins, const struct wined3d_shader_register *reg)
5597 {
5598 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5599 unsigned int idx = reg->idx[0].offset;
5600
5601 if (reg->type == WINED3DSPR_RESOURCE)
5602 {
5603 if (idx >= ARRAY_SIZE(reg_maps->resource_info))
5604 {
5605 ERR("Invalid resource index %u.\n", idx);
5606 return NULL;
5607 }
5608 return &reg_maps->resource_info[idx];
5609 }
5610
5611 if (reg->type == WINED3DSPR_UAV)
5612 {
5613 if (idx >= ARRAY_SIZE(reg_maps->uav_resource_info))
5614 {
5615 ERR("Invalid UAV index %u.\n", idx);
5616 return NULL;
5617 }
5618 return &reg_maps->uav_resource_info[idx];
5619 }
5620
5621 FIXME("Unhandled register type %#x.\n", reg->type);
5622 return NULL;
5623 }
5624
5625 static void shader_glsl_bufinfo(const struct wined3d_shader_instruction *ins)
5626 {
5627 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type);
5628 const struct wined3d_shader_resource_info *resource_info;
5629 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5630 unsigned int resource_idx;
5631 char dst_swizzle[6];
5632 DWORD write_mask;
5633
5634 write_mask = shader_glsl_append_dst(buffer, ins);
5635 shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle);
5636
5637 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[0].reg)))
5638 return;
5639 resource_idx = ins->src[0].reg.idx[0].offset;
5640
5641 shader_addline(buffer, "ivec2(");
5642 if (ins->src[0].reg.type == WINED3DSPR_RESOURCE)
5643 {
5644 unsigned int bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map,
5645 resource_idx, WINED3D_SAMPLER_DEFAULT);
5646 shader_addline(buffer, "textureSize(%s_sampler%u)", prefix, bind_idx);
5647 }
5648 else
5649 {
5650 shader_addline(buffer, "imageSize(%s_image%u)", prefix, resource_idx);
5651 }
5652 if (resource_info->stride)
5653 shader_addline(buffer, " / %u", resource_info->stride);
5654 else if (resource_info->flags & WINED3D_VIEW_BUFFER_RAW)
5655 shader_addline(buffer, " * 4");
5656 shader_addline(buffer, ", %u)%s);\n", resource_info->stride, dst_swizzle);
5657 }
5658
5659 static BOOL is_multisampled(enum wined3d_shader_resource_type resource_type)
5660 {
5661 return resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DMS
5662 || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY;
5663 }
5664
5665 static BOOL is_mipmapped(enum wined3d_shader_resource_type resource_type)
5666 {
5667 return resource_type != WINED3D_SHADER_RESOURCE_BUFFER && !is_multisampled(resource_type);
5668 }
5669
5670 static void shader_glsl_resinfo(const struct wined3d_shader_instruction *ins)
5671 {
5672 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
5673 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
5674 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5675 enum wined3d_shader_resource_type resource_type;
5676 enum wined3d_shader_register_type reg_type;
5677 unsigned int resource_idx, bind_idx, i;
5678 enum wined3d_data_type dst_data_type;
5679 struct glsl_src_param lod_param;
5680 BOOL supports_mipmaps;
5681 char dst_swizzle[6];
5682 DWORD write_mask;
5683
5684 dst_data_type = ins->dst[0].reg.data_type;
5685 if (ins->flags == WINED3DSI_RESINFO_UINT)
5686 dst_data_type = WINED3D_DATA_UINT;
5687 else if (ins->flags)
5688 FIXME("Unhandled flags %#x.\n", ins->flags);
5689
5690 reg_type = ins->src[1].reg.type;
5691 resource_idx = ins->src[1].reg.idx[0].offset;
5692 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &lod_param);
5693 if (reg_type == WINED3DSPR_RESOURCE)
5694 {
5695 resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type;
5696 bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map,
5697 resource_idx, WINED3D_SAMPLER_DEFAULT);
5698 }
5699 else
5700 {
5701 resource_type = ins->ctx->reg_maps->uav_resource_info[resource_idx].type;
5702 bind_idx = resource_idx;
5703 }
5704
5705 if (resource_type >= ARRAY_SIZE(resource_type_info))
5706 {
5707 ERR("Unexpected resource type %#x.\n", resource_type);
5708 return;
5709 }
5710
5711 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], dst_data_type);
5712 shader_glsl_get_swizzle(&ins->src[1], FALSE, write_mask, dst_swizzle);
5713
5714 if (dst_data_type == WINED3D_DATA_UINT)
5715 shader_addline(buffer, "uvec4(");
5716 else
5717 shader_addline(buffer, "vec4(");
5718
5719 if (reg_type == WINED3DSPR_RESOURCE)
5720 {
5721 shader_addline(buffer, "textureSize(%s_sampler%u",
5722 shader_glsl_get_prefix(version->type), bind_idx);
5723 }
5724 else
5725 {
5726 shader_addline(buffer, "imageSize(%s_image%u",
5727 shader_glsl_get_prefix(version->type), bind_idx);
5728 }
5729
5730 supports_mipmaps = is_mipmapped(resource_type) && reg_type != WINED3DSPR_UAV;
5731 if (supports_mipmaps)
5732 shader_addline(buffer, ", %s", lod_param.param_str);
5733 shader_addline(buffer, "), ");
5734
5735 for (i = 0; i < 3 - resource_type_info[resource_type].resinfo_size; ++i)
5736 shader_addline(buffer, "0, ");
5737
5738 if (supports_mipmaps)
5739 {
5740 if (gl_info->supported[ARB_TEXTURE_QUERY_LEVELS])
5741 {
5742 shader_addline(buffer, "textureQueryLevels(%s_sampler%u)",
5743 shader_glsl_get_prefix(version->type), bind_idx);
5744 }
5745 else
5746 {
5747 FIXME("textureQueryLevels is not supported, returning 1 level.\n");
5748 shader_addline(buffer, "1");
5749 }
5750 }
5751 else
5752 {
5753 shader_addline(buffer, "1");
5754 }
5755
5756 shader_addline(buffer, ")%s);\n", dst_swizzle);
5757 }
5758
5759 static void shader_glsl_ld(const struct wined3d_shader_instruction *ins)
5760 {
5761 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5762 struct glsl_src_param coord_param, lod_param, sample_param;
5763 unsigned int resource_idx, sampler_idx, sampler_bind_idx;
5764 struct glsl_sample_function sample_function;
5765 DWORD flags = WINED3D_GLSL_SAMPLE_LOAD;
5766 BOOL has_lod_param;
5767
5768 if (wined3d_shader_instruction_has_texel_offset(ins))
5769 flags |= WINED3D_GLSL_SAMPLE_OFFSET;
5770
5771 resource_idx = ins->src[1].reg.idx[0].offset;
5772 sampler_idx = WINED3D_SAMPLER_DEFAULT;
5773
5774 if (resource_idx >= ARRAY_SIZE(reg_maps->resource_info))
5775 {
5776 ERR("Invalid resource index %u.\n", resource_idx);
5777 return;
5778 }
5779 has_lod_param = is_mipmapped(reg_maps->resource_info[resource_idx].type);
5780
5781 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function);
5782 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
5783 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
5784 sampler_bind_idx = shader_glsl_find_sampler(&reg_maps->sampler_map, resource_idx, sampler_idx);
5785 if (is_multisampled(reg_maps->resource_info[resource_idx].type))
5786 {
5787 shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &sample_param);
5788 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle,
5789 NULL, NULL, NULL, &ins->texel_offset, "%s, %s", coord_param.param_str, sample_param.param_str);
5790 }
5791 else
5792 {
5793 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle,
5794 NULL, NULL, has_lod_param ? lod_param.param_str : NULL, &ins->texel_offset,
5795 "%s", coord_param.param_str);
5796 }
5797 shader_glsl_release_sample_function(ins->ctx, &sample_function);
5798 }
5799
5800 static void shader_glsl_sample(const struct wined3d_shader_instruction *ins)
5801 {
5802 const char *lod_param_str = NULL, *dx_param_str = NULL, *dy_param_str = NULL;
5803 struct glsl_src_param coord_param, lod_param, dx_param, dy_param;
5804 unsigned int resource_idx, sampler_idx, sampler_bind_idx;
5805 struct glsl_sample_function sample_function;
5806 DWORD flags = 0;
5807
5808 if (ins->handler_idx == WINED3DSIH_SAMPLE_GRAD)
5809 flags |= WINED3D_GLSL_SAMPLE_GRAD;
5810 if (ins->handler_idx == WINED3DSIH_SAMPLE_LOD)
5811 flags |= WINED3D_GLSL_SAMPLE_LOD;
5812 if (wined3d_shader_instruction_has_texel_offset(ins))
5813 flags |= WINED3D_GLSL_SAMPLE_OFFSET;
5814
5815 resource_idx = ins->src[1].reg.idx[0].offset;
5816 sampler_idx = ins->src[2].reg.idx[0].offset;
5817
5818 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function);
5819 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
5820
5821 switch (ins->handler_idx)
5822 {
5823 case WINED3DSIH_SAMPLE:
5824 break;
5825 case WINED3DSIH_SAMPLE_B:
5826 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param);
5827 lod_param_str = lod_param.param_str;
5828 break;
5829 case WINED3DSIH_SAMPLE_GRAD:
5830 shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dx_param);
5831 shader_glsl_add_src_param(ins, &ins->src[4], sample_function.deriv_mask, &dy_param);
5832 dx_param_str = dx_param.param_str;
5833 dy_param_str = dy_param.param_str;
5834 break;
5835 case WINED3DSIH_SAMPLE_LOD:
5836 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param);
5837 lod_param_str = lod_param.param_str;
5838 break;
5839 default:
5840 ERR("Unhandled opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
5841 break;
5842 }
5843
5844 sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx);
5845 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle,
5846 dx_param_str, dy_param_str, lod_param_str, &ins->texel_offset, "%s", coord_param.param_str);
5847 shader_glsl_release_sample_function(ins->ctx, &sample_function);
5848 }
5849
5850 /* GLSL doesn't provide a function to sample from level zero with depth
5851 * comparison for array textures and cube textures. We use textureGrad*()
5852 * to implement sample_c_lz.
5853 */
5854 static void shader_glsl_gen_sample_c_lz(const struct wined3d_shader_instruction *ins,
5855 unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function,
5856 unsigned int coord_size, const char *coord_param, const char *ref_param)
5857 {
5858 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
5859 unsigned int deriv_size = wined3d_popcount(sample_function->deriv_mask);
5860 const struct wined3d_shader_texel_offset *offset = &ins->texel_offset;
5861 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5862 char dst_swizzle[6];
5863
5864 WARN("Emitting textureGrad() for sample_c_lz.\n");
5865
5866 shader_glsl_swizzle_to_str(WINED3DSP_NOSWIZZLE, FALSE, ins->dst[0].write_mask, dst_swizzle);
5867 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], sample_function->data_type);
5868 shader_addline(buffer, "vec4(textureGrad%s(%s_sampler%u, vec%u(%s, %s), vec%u(0.0), vec%u(0.0)",
5869 sample_function->offset_size ? "Offset" : "",
5870 shader_glsl_get_prefix(version->type), sampler_bind_idx,
5871 coord_size, coord_param, ref_param, deriv_size, deriv_size);
5872 if (sample_function->offset_size)
5873 {
5874 int offset_immdata[4] = {offset->u, offset->v, offset->w};
5875 shader_addline(buffer, ", ");
5876 shader_glsl_append_imm_ivec(buffer, offset_immdata, sample_function->offset_size);
5877 }
5878 shader_addline(buffer, "))%s);\n", dst_swizzle);
5879 }
5880
5881 static void shader_glsl_sample_c(const struct wined3d_shader_instruction *ins)
5882 {
5883 unsigned int resource_idx, sampler_idx, sampler_bind_idx;
5884 const struct wined3d_shader_resource_info *resource_info;
5885 struct glsl_src_param coord_param, compare_param;
5886 struct glsl_sample_function sample_function;
5887 const char *lod_param = NULL;
5888 unsigned int coord_size;
5889 DWORD flags = 0;
5890
5891 if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ)
5892 {
5893 lod_param = "0";
5894 flags |= WINED3D_GLSL_SAMPLE_LOD;
5895 }
5896
5897 if (wined3d_shader_instruction_has_texel_offset(ins))
5898 flags |= WINED3D_GLSL_SAMPLE_OFFSET;
5899
5900 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[1].reg)))
5901 return;
5902 resource_idx = ins->src[1].reg.idx[0].offset;
5903 sampler_idx = ins->src[2].reg.idx[0].offset;
5904
5905 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function);
5906 coord_size = shader_glsl_get_write_mask_size(sample_function.coord_mask);
5907 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask >> 1, &coord_param);
5908 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &compare_param);
5909 sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx);
5910 if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ
5911 && (resource_info->type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY
5912 || resource_info->type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE))
5913 {
5914 shader_glsl_gen_sample_c_lz(ins, sampler_bind_idx, &sample_function,
5915 coord_size, coord_param.param_str, compare_param.param_str);
5916 }
5917 else
5918 {
5919 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, WINED3DSP_NOSWIZZLE,
5920 NULL, NULL, lod_param, &ins->texel_offset, "vec%u(%s, %s)",
5921 coord_size, coord_param.param_str, compare_param.param_str);
5922 }
5923 shader_glsl_release_sample_function(ins->ctx, &sample_function);
5924 }
5925
5926 static void shader_glsl_gather4(const struct wined3d_shader_instruction *ins)
5927 {
5928 unsigned int resource_param_idx, resource_idx, sampler_idx, sampler_bind_idx, component_idx;
5929 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
5930 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
5931 struct glsl_src_param coord_param, compare_param, offset_param;
5932 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
5933 const struct wined3d_shader_resource_info *resource_info;
5934 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5935 unsigned int coord_size, offset_size;
5936 char dst_swizzle[6];
5937 BOOL has_offset;
5938
5939 if (!gl_info->supported[ARB_TEXTURE_GATHER])
5940 {
5941 FIXME("OpenGL implementation does not support textureGather.\n");
5942 return;
5943 }
5944
5945 has_offset = ins->handler_idx == WINED3DSIH_GATHER4_PO
5946 || ins->handler_idx == WINED3DSIH_GATHER4_PO_C
5947 || wined3d_shader_instruction_has_texel_offset(ins);
5948
5949 resource_param_idx =
5950 (ins->handler_idx == WINED3DSIH_GATHER4_PO || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) ? 2 : 1;
5951 resource_idx = ins->src[resource_param_idx].reg.idx[0].offset;
5952 sampler_idx = ins->src[resource_param_idx + 1].reg.idx[0].offset;
5953 component_idx = shader_glsl_swizzle_get_component(ins->src[resource_param_idx + 1].swizzle, 0);
5954 sampler_bind_idx = shader_glsl_find_sampler(&reg_maps->sampler_map, resource_idx, sampler_idx);
5955
5956 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[resource_param_idx].reg)))
5957 return;
5958
5959 if (resource_info->type >= ARRAY_SIZE(resource_type_info))
5960 {
5961 ERR("Unexpected resource type %#x.\n", resource_info->type);
5962 return;
5963 }
5964 shader_glsl_get_coord_size(resource_info->type, &coord_size, &offset_size);
5965
5966 shader_glsl_swizzle_to_str(ins->src[resource_param_idx].swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle);
5967 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], resource_info->data_type);
5968
5969 shader_glsl_add_src_param(ins, &ins->src[0], (1u << coord_size) - 1, &coord_param);
5970
5971 shader_addline(buffer, "textureGather%s(%s_sampler%u, %s",
5972 has_offset ? "Offset" : "", prefix, sampler_bind_idx, coord_param.param_str);
5973 if (ins->handler_idx == WINED3DSIH_GATHER4_C || ins->handler_idx == WINED3DSIH_GATHER4_PO_C)
5974 {
5975 shader_glsl_add_src_param(ins, &ins->src[resource_param_idx + 2], WINED3DSP_WRITEMASK_0, &compare_param);
5976 shader_addline(buffer, ", %s", compare_param.param_str);
5977 }
5978 if (ins->handler_idx == WINED3DSIH_GATHER4_PO || ins->handler_idx == WINED3DSIH_GATHER4_PO_C)
5979 {
5980 shader_glsl_add_src_param(ins, &ins->src[1], (1u << offset_size) - 1, &offset_param);
5981 shader_addline(buffer, ", %s", offset_param.param_str);
5982 }
5983 else if (has_offset)
5984 {
5985 int offset_immdata[4] = {ins->texel_offset.u, ins->texel_offset.v, ins->texel_offset.w};
5986 shader_addline(buffer, ", ");
5987 shader_glsl_append_imm_ivec(buffer, offset_immdata, offset_size);
5988 }
5989 if (component_idx)
5990 shader_addline(buffer, ", %u", component_idx);
5991
5992 shader_addline(buffer, ")%s);\n", dst_swizzle);
5993 }
5994
5995 static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
5996 {
5997 /* FIXME: Make this work for more than just 2D textures */
5998 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
5999 DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
6000
6001 if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4))
6002 {
6003 char dst_mask[6];
6004
6005 shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
6006 shader_addline(buffer, "clamp(ffp_texcoord[%u], 0.0, 1.0)%s);\n",
6007 ins->dst[0].reg.idx[0].offset, dst_mask);
6008 }
6009 else
6010 {
6011 enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers;
6012 DWORD reg = ins->src[0].reg.idx[0].offset;
6013 char dst_swizzle[6];
6014
6015 shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle);
6016
6017 if (src_mod == WINED3DSPSM_DZ || src_mod == WINED3DSPSM_DW)
6018 {
6019 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
6020 struct glsl_src_param div_param;
6021 DWORD src_writemask = src_mod == WINED3DSPSM_DZ ? WINED3DSP_WRITEMASK_2 : WINED3DSP_WRITEMASK_3;
6022
6023 shader_glsl_add_src_param(ins, &ins->src[0], src_writemask, &div_param);
6024
6025 if (mask_size > 1)
6026 shader_addline(buffer, "ffp_texcoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
6027 else
6028 shader_addline(buffer, "ffp_texcoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
6029 }
6030 else
6031 {
6032 shader_addline(buffer, "ffp_texcoord[%u]%s);\n", reg, dst_swizzle);
6033 }
6034 }
6035 }
6036
6037 /** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL:
6038 * Take a 3-component dot product of the TexCoord[dstreg] and src,
6039 * then perform a 1D texture lookup from stage dstregnum, place into dst. */
6040 static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
6041 {
6042 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6043 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
6044 struct glsl_sample_function sample_function;
6045 struct glsl_src_param src0_param;
6046 UINT mask_size;
6047
6048 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6049
6050 /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one
6051 * scalar, and projected sampling would require 4.
6052 *
6053 * It is a dependent read - not valid with conditional NP2 textures
6054 */
6055 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
6056 mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask);
6057
6058 switch(mask_size)
6059 {
6060 case 1:
6061 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
6062 NULL, "dot(ffp_texcoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
6063 break;
6064
6065 case 2:
6066 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
6067 NULL, "vec2(dot(ffp_texcoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
6068 break;
6069
6070 case 3:
6071 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
6072 NULL, "vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
6073 break;
6074
6075 default:
6076 FIXME("Unexpected mask size %u\n", mask_size);
6077 break;
6078 }
6079 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6080 }
6081
6082 /** Process the WINED3DSIO_TEXDP3 instruction in GLSL:
6083 * Take a 3-component dot product of the TexCoord[dstreg] and src. */
6084 static void shader_glsl_texdp3(const struct wined3d_shader_instruction *ins)
6085 {
6086 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6087 DWORD dstreg = ins->dst[0].reg.idx[0].offset;
6088 struct glsl_src_param src0_param;
6089 DWORD dst_mask;
6090 unsigned int mask_size;
6091
6092 dst_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
6093 mask_size = shader_glsl_get_write_mask_size(dst_mask);
6094 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6095
6096 if (mask_size > 1) {
6097 shader_addline(ins->ctx->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str);
6098 } else {
6099 shader_addline(ins->ctx->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str);
6100 }
6101 }
6102
6103 /** Process the WINED3DSIO_TEXDEPTH instruction in GLSL:
6104 * Calculate the depth as dst.x / dst.y */
6105 static void shader_glsl_texdepth(const struct wined3d_shader_instruction *ins)
6106 {
6107 struct glsl_dst_param dst_param;
6108
6109 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
6110
6111 /* Tests show that texdepth never returns anything below 0.0, and that r5.y is clamped to 1.0.
6112 * Negative input is accepted, -0.25 / -0.5 returns 0.5. GL should clamp gl_FragDepth to [0;1], but
6113 * this doesn't always work, so clamp the results manually. Whether or not the x value is clamped at 1
6114 * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result
6115 * >= 1.0 or < 0.0
6116 */
6117 shader_addline(ins->ctx->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n",
6118 dst_param.reg_name, dst_param.reg_name);
6119 }
6120
6121 /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL:
6122 * Last row of a 3x2 matrix multiply, use the result to calculate the depth:
6123 * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated)
6124 * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
6125 */
6126 static void shader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins)
6127 {
6128 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6129 DWORD dstreg = ins->dst[0].reg.idx[0].offset;
6130 struct glsl_src_param src0_param;
6131
6132 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6133
6134 shader_addline(ins->ctx->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str);
6135 shader_addline(ins->ctx->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n");
6136 }
6137
6138 /** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL
6139 * Calculate the 1st of a 2-row matrix multiplication. */
6140 static void shader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins)
6141 {
6142 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6143 DWORD reg = ins->dst[0].reg.idx[0].offset;
6144 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
6145 struct glsl_src_param src0_param;
6146
6147 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6148 shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
6149 }
6150
6151 /** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL
6152 * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */
6153 static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins)
6154 {
6155 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6156 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
6157 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
6158 DWORD reg = ins->dst[0].reg.idx[0].offset;
6159 struct glsl_src_param src0_param;
6160
6161 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6162 shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + tex_mx->current_row, reg, src0_param.param_str);
6163 tex_mx->texcoord_w[tex_mx->current_row++] = reg;
6164 }
6165
6166 static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins)
6167 {
6168 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6169 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
6170 struct glsl_sample_function sample_function;
6171 DWORD reg = ins->dst[0].reg.idx[0].offset;
6172 struct glsl_src_param src0_param;
6173
6174 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6175 shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
6176
6177 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function);
6178
6179 /* Sample the texture using the calculated coordinates */
6180 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xy");
6181 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6182 }
6183
6184 /** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL
6185 * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */
6186 static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins)
6187 {
6188 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6189 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
6190 struct glsl_sample_function sample_function;
6191 DWORD reg = ins->dst[0].reg.idx[0].offset;
6192 struct glsl_src_param src0_param;
6193
6194 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6195 shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
6196
6197 /* Dependent read, not valid with conditional NP2 */
6198 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function);
6199
6200 /* Sample the texture using the calculated coordinates */
6201 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xyz");
6202 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6203
6204 tex_mx->current_row = 0;
6205 }
6206
6207 /** Process the WINED3DSIO_TEXM3X3 instruction in GLSL
6208 * Perform the 3rd row of a 3x3 matrix multiply */
6209 static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins)
6210 {
6211 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6212 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
6213 DWORD reg = ins->dst[0].reg.idx[0].offset;
6214 struct glsl_src_param src0_param;
6215 char dst_mask[6];
6216
6217 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6218
6219 shader_glsl_append_dst(ins->ctx->buffer, ins);
6220 shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
6221 shader_addline(ins->ctx->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask);
6222
6223 tex_mx->current_row = 0;
6224 }
6225
6226 /* Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL
6227 * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */
6228 static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins)
6229 {
6230 struct glsl_src_param src0_param;
6231 struct glsl_src_param src1_param;
6232 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
6233 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
6234 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6235 struct glsl_sample_function sample_function;
6236 DWORD reg = ins->dst[0].reg.idx[0].offset;
6237 char coord_mask[6];
6238
6239 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6240 shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
6241
6242 /* Perform the last matrix multiply operation */
6243 shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
6244 /* Reflection calculation */
6245 shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str);
6246
6247 /* Dependent read, not valid with conditional NP2 */
6248 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function);
6249 shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask);
6250
6251 /* Sample the texture */
6252 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE,
6253 NULL, NULL, NULL, NULL, "tmp0%s", coord_mask);
6254 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6255
6256 tex_mx->current_row = 0;
6257 }
6258
6259 /* Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL
6260 * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */
6261 static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins)
6262 {
6263 struct wined3d_string_buffer *buffer = ins->ctx->buffer;
6264 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
6265 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
6266 struct glsl_sample_function sample_function;
6267 DWORD reg = ins->dst[0].reg.idx[0].offset;
6268 struct glsl_src_param src0_param;
6269 char coord_mask[6];
6270
6271 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
6272
6273 /* Perform the last matrix multiply operation */
6274 shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str);
6275
6276 /* Construct the eye-ray vector from w coordinates */
6277 shader_addline(buffer, "tmp1.xyz = normalize(vec3(ffp_texcoord[%u].w, ffp_texcoord[%u].w, ffp_texcoord[%u].w));\n",
6278 tex_mx->texcoord_w[0], tex_mx->texcoord_w[1], reg);
6279 shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n");
6280
6281 /* Dependent read, not valid with conditional NP2 */
6282 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function);
6283 shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask);
6284
6285 /* Sample the texture using the calculated coordinates */
6286 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE,
6287 NULL, NULL, NULL, NULL, "tmp0%s", coord_mask);
6288 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6289
6290 tex_mx->current_row = 0;
6291 }
6292
6293 /** Process the WINED3DSIO_TEXBEM instruction in GLSL.
6294 * Apply a fake bump map transform.
6295 * texbem is pshader <= 1.3 only, this saves a few version checks
6296 */
6297 static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins)
6298 {
6299 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
6300 struct glsl_sample_function sample_function;
6301 struct glsl_src_param coord_param;
6302 DWORD sampler_idx;
6303 DWORD mask;
6304 DWORD flags;
6305 char coord_mask[6];
6306
6307 sampler_idx = ins->dst[0].reg.idx[0].offset;
6308 flags = (priv->cur_ps_args->tex_transform >> sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)
6309 & WINED3D_PSARGS_TEXTRANSFORM_MASK;
6310
6311 /* Dependent read, not valid with conditional NP2 */
6312 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
6313 mask = sample_function.coord_mask;
6314
6315 shader_glsl_write_mask_to_str(mask, coord_mask);
6316
6317 /* With projected textures, texbem only divides the static texture coord,
6318 * not the displacement, so we can't let GL handle this. */
6319 if (flags & WINED3D_PSARGS_PROJECTED)
6320 {
6321 DWORD div_mask=0;
6322 char coord_div_mask[3];
6323 switch (flags & ~WINED3D_PSARGS_PROJECTED)
6324 {
6325 case WINED3D_TTFF_COUNT1:
6326 FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n");
6327 break;
6328 case WINED3D_TTFF_COUNT2:
6329 div_mask = WINED3DSP_WRITEMASK_1;
6330 break;
6331 case WINED3D_TTFF_COUNT3:
6332 div_mask = WINED3DSP_WRITEMASK_2;
6333 break;
6334 case WINED3D_TTFF_COUNT4:
6335 case WINED3D_TTFF_DISABLE:
6336 div_mask = WINED3DSP_WRITEMASK_3;
6337 break;
6338 }
6339 shader_glsl_write_mask_to_str(div_mask, coord_div_mask);
6340 shader_addline(ins->ctx->buffer, "T%u%s /= T%u%s;\n", sampler_idx, coord_mask, sampler_idx, coord_div_mask);
6341 }
6342
6343 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &coord_param);
6344
6345 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
6346 "T%u%s + vec4(bumpenv_mat%u * %s, 0.0, 0.0)%s", sampler_idx, coord_mask, sampler_idx,
6347 coord_param.param_str, coord_mask);
6348
6349 if (ins->handler_idx == WINED3DSIH_TEXBEML)
6350 {
6351 struct glsl_src_param luminance_param;
6352 struct glsl_dst_param dst_param;
6353
6354 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &luminance_param);
6355 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
6356
6357 shader_addline(ins->ctx->buffer, "%s%s *= (%s * bumpenv_lum_scale%u + bumpenv_lum_offset%u);\n",
6358 dst_param.reg_name, dst_param.mask_str,
6359 luminance_param.param_str, sampler_idx, sampler_idx);
6360 }
6361 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6362 }
6363
6364 static void shader_glsl_bem(const struct wined3d_shader_instruction *ins)
6365 {
6366 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
6367 struct glsl_src_param src0_param, src1_param;
6368
6369 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param);
6370 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param);
6371
6372 shader_glsl_append_dst(ins->ctx->buffer, ins);
6373 shader_addline(ins->ctx->buffer, "%s + bumpenv_mat%u * %s);\n",
6374 src0_param.param_str, sampler_idx, src1_param.param_str);
6375 }
6376
6377 /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
6378 * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
6379 static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins)
6380 {
6381 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
6382 struct glsl_sample_function sample_function;
6383 struct glsl_src_param src0_param;
6384
6385 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
6386
6387 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
6388 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
6389 "%s.wx", src0_param.reg_name);
6390 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6391 }
6392
6393 /** Process the WINED3DSIO_TEXREG2GB instruction in GLSL
6394 * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */
6395 static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins)
6396 {
6397 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
6398 struct glsl_sample_function sample_function;
6399 struct glsl_src_param src0_param;
6400
6401 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
6402
6403 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
6404 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
6405 "%s.yz", src0_param.reg_name);
6406 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6407 }
6408
6409 /** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL
6410 * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */
6411 static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins)
6412 {
6413 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
6414 struct glsl_sample_function sample_function;
6415 struct glsl_src_param src0_param;
6416
6417 /* Dependent read, not valid with conditional NP2 */
6418 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function);
6419 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param);
6420
6421 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL,
6422 "%s", src0_param.param_str);
6423 shader_glsl_release_sample_function(ins->ctx, &sample_function);
6424 }
6425
6426 /** Process the WINED3DSIO_TEXKILL instruction in GLSL.
6427 * If any of the first 3 components are < 0, discard this pixel */
6428 static void shader_glsl_texkill(const struct wined3d_shader_instruction *ins)
6429 {
6430 if (ins->ctx->reg_maps->shader_version.major >= 4)
6431 {
6432 shader_glsl_generate_conditional_op(ins, "discard;");
6433 }
6434 else
6435 {
6436 struct glsl_dst_param dst_param;
6437
6438 /* The argument is a destination parameter, and no writemasks are allowed */
6439 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
6440
6441 /* 2.0 shaders compare all 4 components in texkill. */
6442 if (ins->ctx->reg_maps->shader_version.major >= 2)
6443 shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyzw, vec4(0.0)))) discard;\n", dst_param.reg_name);
6444 /* 1.x shaders only compare the first 3 components, probably due to
6445 * the nature of the texkill instruction as a tex* instruction, and
6446 * phase, which kills all .w components. Even if all 4 components are
6447 * defined, only the first 3 are used. */
6448 else
6449 shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_param.reg_name);
6450 }
6451 }
6452
6453 /** Process the WINED3DSIO_DP2ADD instruction in GLSL.
6454 * dst = dot2(src0, src1) + src2 */
6455 static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins)
6456 {
6457 struct glsl_src_param src0_param;
6458 struct glsl_src_param src1_param;
6459 struct glsl_src_param src2_param;
6460 DWORD write_mask;
6461 unsigned int mask_size;
6462
6463 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
6464 mask_size = shader_glsl_get_write_mask_size(write_mask);
6465
6466 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param);
6467 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param);
6468 shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &src2_param);
6469
6470 if (mask_size > 1) {
6471 shader_addline(ins->ctx->buffer, "vec%d(dot(%s, %s) + %s));\n",
6472 mask_size, src0_param.param_str, src1_param.param_str, src2_param.param_str);
6473 } else {
6474 shader_addline(ins->ctx->buffer, "dot(%s, %s) + %s);\n",
6475 src0_param.param_str, src1_param.param_str, src2_param.param_str);
6476 }
6477 }
6478
6479 static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer,
6480 const struct wined3d_shader_signature *input_signature,
6481 const struct wined3d_shader_reg_maps *reg_maps,
6482 const struct ps_compile_args *args, const struct wined3d_gl_info *gl_info, BOOL unroll)
6483 {
6484 unsigned int i;
6485
6486 for (i = 0; i < input_signature->element_count; ++i)
6487 {
6488 const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
6489 const char *semantic_name;
6490 UINT semantic_idx;
6491 char reg_mask[6];
6492
6493 /* Unused */
6494 if (!(reg_maps->input_registers & (1u << input->register_idx)))
6495 continue;
6496
6497 semantic_name = input->semantic_name;
6498 semantic_idx = input->semantic_idx;
6499 shader_glsl_write_mask_to_str(input->mask, reg_mask);
6500
6501 if (args->vp_mode == vertexshader)
6502 {
6503 if (input->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx)
6504 {
6505 shader_addline(buffer, "ps_in[%u]%s = vpos%s;\n",
6506 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
6507 }
6508 else if (args->pointsprite && shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
6509 {
6510 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", input->register_idx);
6511 }
6512 else if (input->sysval_semantic == WINED3D_SV_IS_FRONT_FACE)
6513 {
6514 shader_addline(buffer, "ps_in[%u]%s = uintBitsToFloat(gl_FrontFacing ? 0xffffffffu : 0u);\n",
6515 input->register_idx, reg_mask);
6516 }
6517 else if (input->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx)
6518 {
6519 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT])
6520 shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_Layer);\n",
6521 input->register_idx, reg_mask);
6522 else
6523 FIXME("ARB_fragment_layer_viewport is not supported.\n");
6524 }
6525 else
6526 {
6527 if (input->sysval_semantic)
6528 FIXME("Unhandled sysval semantic %#x.\n", input->sysval_semantic);
6529 shader_addline(buffer, unroll ? "ps_in[%u]%s = %s%u%s;\n" : "ps_in[%u]%s = %s[%u]%s;\n",
6530 shader->u.ps.input_reg_map[input->register_idx], reg_mask,
6531 shader_glsl_shader_input_name(gl_info),
6532 shader->u.ps.input_reg_map[input->register_idx], reg_mask);
6533 }
6534 }
6535 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
6536 {
6537 if (args->pointsprite)
6538 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n",
6539 shader->u.ps.input_reg_map[input->register_idx]);
6540 else if (args->vp_mode == pretransformed && args->texcoords_initialized & (1u << semantic_idx))
6541 shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n",
6542 shader->u.ps.input_reg_map[input->register_idx], reg_mask,
6543 needs_legacy_glsl_syntax(gl_info)
6544 ? "gl_TexCoord" : "ffp_varying_texcoord", semantic_idx, reg_mask);
6545 else
6546 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
6547 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
6548 }
6549 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
6550 {
6551 if (!semantic_idx)
6552 shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_diffuse)%s;\n",
6553 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
6554 else if (semantic_idx == 1)
6555 shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_specular)%s;\n",
6556 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
6557 else
6558 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
6559 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
6560 }
6561 else
6562 {
6563 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
6564 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
6565 }
6566 }
6567 }
6568
6569 static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry)
6570 {
6571 struct glsl_program_key key;
6572
6573 key.vs_id = entry->vs.id;
6574 key.hs_id = entry->hs.id;
6575 key.ds_id = entry->ds.id;
6576 key.gs_id = entry->gs.id;
6577 key.ps_id = entry->ps.id;
6578 key.cs_id = entry->cs.id;
6579
6580 if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1)
6581 {
6582 ERR("Failed to insert program entry.\n");
6583 }
6584 }
6585
6586 static struct glsl_shader_prog_link *get_glsl_program_entry(const struct shader_glsl_priv *priv,
6587 const struct glsl_program_key *key)
6588 {
6589 struct wine_rb_entry *entry;
6590
6591 entry = wine_rb_get(&priv->program_lookup, key);
6592 return entry ? WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry) : NULL;
6593 }
6594
6595 /* Context activation is done by the caller. */
6596 static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info,
6597 struct glsl_shader_prog_link *entry)
6598 {
6599 wine_rb_remove(&priv->program_lookup, &entry->program_lookup_entry);
6600
6601 GL_EXTCALL(glDeleteProgram(entry->id));
6602 if (entry->vs.id)
6603 list_remove(&entry->vs.shader_entry);
6604 if (entry->hs.id)
6605 list_remove(&entry->hs.shader_entry);
6606 if (entry->ds.id)
6607 list_remove(&entry->ds.shader_entry);
6608 if (entry->gs.id)
6609 list_remove(&entry->gs.shader_entry);
6610 if (entry->ps.id)
6611 list_remove(&entry->ps.shader_entry);
6612 if (entry->cs.id)
6613 list_remove(&entry->cs.shader_entry);
6614 heap_free(entry);
6615 }
6616
6617 static void shader_glsl_setup_vs3_output(struct shader_glsl_priv *priv,
6618 const struct wined3d_gl_info *gl_info, const DWORD *map,
6619 const struct wined3d_shader_signature *input_signature,
6620 const struct wined3d_shader_reg_maps *reg_maps_in,
6621 const struct wined3d_shader_signature *output_signature,
6622 const struct wined3d_shader_reg_maps *reg_maps_out)
6623 {
6624 struct wined3d_string_buffer *destination = string_buffer_get(&priv->string_buffers);
6625 const char *out_array_name = shader_glsl_shader_output_name(gl_info);
6626 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
6627 unsigned int in_count = vec4_varyings(3, gl_info);
6628 unsigned int max_varyings = needs_legacy_glsl_syntax(gl_info) ? in_count + 2 : in_count;
6629 DWORD in_idx, *set = NULL;
6630 unsigned int i, j;
6631 char reg_mask[6];
6632
6633 set = heap_calloc(max_varyings, sizeof(*set));
6634
6635 for (i = 0; i < input_signature->element_count; ++i)
6636 {
6637 const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
6638
6639 if (!(reg_maps_in->input_registers & (1u << input->register_idx)))
6640 continue;
6641
6642 in_idx = map[input->register_idx];
6643 /* Declared, but not read register */
6644 if (in_idx == ~0u)
6645 continue;
6646 if (in_idx >= max_varyings)
6647 {
6648 FIXME("More input varyings declared than supported, expect issues.\n");
6649 continue;
6650 }
6651
6652 if (in_idx == in_count)
6653 string_buffer_sprintf(destination, "gl_FrontColor");
6654 else if (in_idx == in_count + 1)
6655 string_buffer_sprintf(destination, "gl_FrontSecondaryColor");
6656 else
6657 string_buffer_sprintf(destination, "%s[%u]", out_array_name, in_idx);
6658
6659 if (!set[in_idx])
6660 set[in_idx] = ~0u;
6661
6662 for (j = 0; j < output_signature->element_count; ++j)
6663 {
6664 const struct wined3d_shader_signature_element *output = &output_signature->elements[j];
6665 DWORD mask;
6666
6667 if (!(reg_maps_out->output_registers & (1u << output->register_idx))
6668 || input->semantic_idx != output->semantic_idx
6669 || strcmp(input->semantic_name, output->semantic_name)
6670 || !(mask = input->mask & output->mask))
6671 continue;
6672
6673 if (set[in_idx] == ~0u)
6674 set[in_idx] = 0;
6675 set[in_idx] |= mask & reg_maps_out->u.output_registers_mask[output->register_idx];
6676 shader_glsl_write_mask_to_str(mask, reg_mask);
6677
6678 shader_addline(buffer, "%s%s = outputs[%u]%s;\n",
6679 destination->buffer, reg_mask, output->register_idx, reg_mask);
6680 }
6681 }
6682
6683 for (i = 0; i < max_varyings; ++i)
6684 {
6685 unsigned int size;
6686
6687 if (!set[i] || set[i] == WINED3DSP_WRITEMASK_ALL)
6688 continue;
6689
6690 if (set[i] == ~0u)
6691 set[i] = 0;
6692
6693 size = 0;
6694 if (!(set[i] & WINED3DSP_WRITEMASK_0))
6695 reg_mask[size++] = 'x';
6696 if (!(set[i] & WINED3DSP_WRITEMASK_1))
6697 reg_mask[size++] = 'y';
6698 if (!(set[i] & WINED3DSP_WRITEMASK_2))
6699 reg_mask[size++] = 'z';
6700 if (!(set[i] & WINED3DSP_WRITEMASK_3))
6701 reg_mask[size++] = 'w';
6702 reg_mask[size] = '\0';
6703
6704 if (i == in_count)
6705 string_buffer_sprintf(destination, "gl_FrontColor");
6706 else if (i == in_count + 1)
6707 string_buffer_sprintf(destination, "gl_FrontSecondaryColor");
6708 else
6709 string_buffer_sprintf(destination, "%s[%u]", out_array_name, i);
6710
6711 if (size == 1)
6712 shader_addline(buffer, "%s.%s = 0.0;\n", destination->buffer, reg_mask);
6713 else
6714 shader_addline(buffer, "%s.%s = vec%u(0.0);\n", destination->buffer, reg_mask, size);
6715 }
6716
6717 heap_free(set);
6718 string_buffer_release(&priv->string_buffers, destination);
6719 }
6720
6721 static void shader_glsl_setup_sm4_shader_output(struct shader_glsl_priv *priv,
6722 unsigned int input_count, const struct wined3d_shader_signature *output_signature,
6723 const struct wined3d_shader_reg_maps *reg_maps_out, const char *output_variable_name,
6724 BOOL rasterizer_setup)
6725 {
6726 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
6727 char reg_mask[6];
6728 unsigned int i;
6729
6730 for (i = 0; i < output_signature->element_count; ++i)
6731 {
6732 const struct wined3d_shader_signature_element *output = &output_signature->elements[i];
6733
6734 if (!(reg_maps_out->output_registers & (1u << output->register_idx)))
6735 continue;
6736
6737 if (output->stream_idx)
6738 continue;
6739
6740 if (output->register_idx >= input_count)
6741 continue;
6742
6743 shader_glsl_write_mask_to_str(output->mask, reg_mask);
6744
6745 shader_addline(buffer,
6746 rasterizer_setup ? "%s.reg%u%s = outputs[%u]%s;\n" : "%s.reg[%u]%s = outputs[%u]%s;\n",
6747 output_variable_name, output->register_idx, reg_mask, output->register_idx, reg_mask);
6748 }
6749 }
6750
6751 static void shader_glsl_generate_clip_or_cull_distances(struct wined3d_string_buffer *buffer,
6752 const struct wined3d_shader_signature_element *element, DWORD clip_or_cull_distance_mask)
6753 {
6754 unsigned int i, clip_or_cull_index;
6755 const char *name;
6756 char reg_mask[6];
6757
6758 name = element->sysval_semantic == WINED3D_SV_CLIP_DISTANCE ? "Clip" : "Cull";
6759 /* Assign consecutive indices starting from 0. */
6760 clip_or_cull_index = element->semantic_idx ? wined3d_popcount(clip_or_cull_distance_mask & 0xf) : 0;
6761 for (i = 0; i < 4; ++i)
6762 {
6763 if (!(element->mask & (WINED3DSP_WRITEMASK_0 << i)))
6764 continue;
6765
6766 shader_glsl_write_mask_to_str(WINED3DSP_WRITEMASK_0 << i, reg_mask);
6767 shader_addline(buffer, "gl_%sDistance[%u] = outputs[%u]%s;\n",
6768 name, clip_or_cull_index, element->register_idx, reg_mask);
6769 ++clip_or_cull_index;
6770 }
6771 }
6772
6773 static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv,
6774 const struct wined3d_gl_info *gl_info, const DWORD *map,
6775 const struct wined3d_shader_signature *input_signature,
6776 const struct wined3d_shader_reg_maps *reg_maps_in, unsigned int input_count,
6777 const struct wined3d_shader_signature *output_signature,
6778 const struct wined3d_shader_reg_maps *reg_maps_out, BOOL per_vertex_point_size)
6779 {
6780 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
6781 const char *semantic_name;
6782 unsigned int semantic_idx;
6783 char reg_mask[6];
6784 unsigned int i;
6785
6786 /* First, sort out position and point size system values. */
6787 for (i = 0; i < output_signature->element_count; ++i)
6788 {
6789 const struct wined3d_shader_signature_element *output = &output_signature->elements[i];
6790
6791 if (!(reg_maps_out->output_registers & (1u << output->register_idx)))
6792 continue;
6793
6794 if (output->stream_idx)
6795 continue;
6796
6797 semantic_name = output->semantic_name;
6798 semantic_idx = output->semantic_idx;
6799 shader_glsl_write_mask_to_str(output->mask, reg_mask);
6800
6801 if (output->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx)
6802 {
6803 shader_addline(buffer, "gl_Position%s = outputs[%u]%s;\n",
6804 reg_mask, output->register_idx, reg_mask);
6805 }
6806 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size)
6807 {
6808 shader_addline(buffer, "gl_PointSize = clamp(outputs[%u].%c, "
6809 "ffp_point.size_min, ffp_point.size_max);\n", output->register_idx, reg_mask[1]);
6810 }
6811 else if (output->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx)
6812 {
6813 shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n",
6814 output->register_idx, reg_mask);
6815 }
6816 else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE)
6817 {
6818 shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask);
6819 }
6820 else if (output->sysval_semantic == WINED3D_SV_CULL_DISTANCE)
6821 {
6822 shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->cull_distance_mask);
6823 }
6824 else if (output->sysval_semantic)
6825 {
6826 FIXME("Unhandled sysval semantic %#x.\n", output->sysval_semantic);
6827 }
6828 }
6829
6830 /* Then, setup the pixel shader input. */
6831 if (reg_maps_out->shader_version.major < 4)
6832 shader_glsl_setup_vs3_output(priv, gl_info, map, input_signature, reg_maps_in,
6833 output_signature, reg_maps_out);
6834 else
6835 shader_glsl_setup_sm4_shader_output(priv, input_count, output_signature, reg_maps_out, "shader_out", TRUE);
6836 }
6837
6838 /* Context activation is done by the caller. */
6839 static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl_priv *priv,
6840 const struct wined3d_shader *vs, const struct wined3d_shader *ps,
6841 BOOL per_vertex_point_size, BOOL flatshading, const struct wined3d_gl_info *gl_info)
6842 {
6843 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
6844 DWORD ps_major = ps ? ps->reg_maps.shader_version.major : 0;
6845 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
6846 const char *semantic_name;
6847 UINT semantic_idx;
6848 char reg_mask[6];
6849 unsigned int i;
6850 GLuint ret;
6851
6852 string_buffer_clear(buffer);
6853
6854 shader_glsl_add_version_declaration(buffer, gl_info);
6855
6856 if (per_vertex_point_size)
6857 {
6858 shader_addline(buffer, "uniform struct\n{\n");
6859 shader_addline(buffer, " float size_min;\n");
6860 shader_addline(buffer, " float size_max;\n");
6861 shader_addline(buffer, "} ffp_point;\n");
6862 }
6863
6864 if (ps_major < 3)
6865 {
6866 DWORD colors_written_mask[2] = {0};
6867 DWORD texcoords_written_mask[MAX_TEXTURES] = {0};
6868
6869 if (!legacy_syntax)
6870 {
6871 declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_diffuse;\n");
6872 declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_specular;\n");
6873 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
6874 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
6875 }
6876
6877 shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output);
6878
6879 for (i = 0; i < vs->output_signature.element_count; ++i)
6880 {
6881 const struct wined3d_shader_signature_element *output = &vs->output_signature.elements[i];
6882 DWORD write_mask;
6883
6884 if (!(vs->reg_maps.output_registers & (1u << output->register_idx)))
6885 continue;
6886
6887 semantic_name = output->semantic_name;
6888 semantic_idx = output->semantic_idx;
6889 write_mask = output->mask;
6890 shader_glsl_write_mask_to_str(write_mask, reg_mask);
6891
6892 if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR) && semantic_idx < 2)
6893 {
6894 if (legacy_syntax)
6895 shader_addline(buffer, "gl_Front%sColor%s = outputs[%u]%s;\n",
6896 semantic_idx ? "Secondary" : "", reg_mask, output->register_idx, reg_mask);
6897 else
6898 shader_addline(buffer, "ffp_varying_%s%s = clamp(outputs[%u]%s, 0.0, 1.0);\n",
6899 semantic_idx ? "specular" : "diffuse", reg_mask, output->register_idx, reg_mask);
6900
6901 colors_written_mask[semantic_idx] = write_mask;
6902 }
6903 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION) && !semantic_idx)
6904 {
6905 shader_addline(buffer, "gl_Position%s = outputs[%u]%s;\n",
6906 reg_mask, output->register_idx, reg_mask);
6907 }
6908 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
6909 {
6910 if (semantic_idx < MAX_TEXTURES)
6911 {
6912 shader_addline(buffer, "%s[%u]%s = outputs[%u]%s;\n",
6913 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord",
6914 semantic_idx, reg_mask, output->register_idx, reg_mask);
6915 texcoords_written_mask[semantic_idx] = write_mask;
6916 }
6917 }
6918 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size)
6919 {
6920 shader_addline(buffer, "gl_PointSize = clamp(outputs[%u].%c, "
6921 "ffp_point.size_min, ffp_point.size_max);\n", output->register_idx, reg_mask[1]);
6922 }
6923 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
6924 {
6925 shader_addline(buffer, "%s = clamp(outputs[%u].%c, 0.0, 1.0);\n",
6926 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord",
6927 output->register_idx, reg_mask[1]);
6928 }
6929 }
6930
6931 for (i = 0; i < 2; ++i)
6932 {
6933 if (colors_written_mask[i] != WINED3DSP_WRITEMASK_ALL)
6934 {
6935 shader_glsl_write_mask_to_str(~colors_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask);
6936 if (!i)
6937 shader_addline(buffer, "%s%s = vec4(1.0)%s;\n",
6938 legacy_syntax ? "gl_FrontColor" : "ffp_varying_diffuse",
6939 reg_mask, reg_mask);
6940 else
6941 shader_addline(buffer, "%s%s = vec4(0.0)%s;\n",
6942 legacy_syntax ? "gl_FrontSecondaryColor" : "ffp_varying_specular",
6943 reg_mask, reg_mask);
6944 }
6945 }
6946 for (i = 0; i < MAX_TEXTURES; ++i)
6947 {
6948 if (ps && !(ps->reg_maps.texcoord & (1u << i)))
6949 continue;
6950
6951 if (texcoords_written_mask[i] != WINED3DSP_WRITEMASK_ALL)
6952 {
6953 if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info)
6954 && !texcoords_written_mask[i])
6955 continue;
6956
6957 shader_glsl_write_mask_to_str(~texcoords_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask);
6958 shader_addline(buffer, "%s[%u]%s = vec4(0.0)%s;\n",
6959 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", i, reg_mask, reg_mask);
6960 }
6961 }
6962 }
6963 else
6964 {
6965 unsigned int in_count = min(vec4_varyings(ps_major, gl_info), ps->limits->packed_input);
6966
6967 shader_glsl_declare_shader_outputs(gl_info, buffer, in_count, FALSE, NULL);
6968 shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output);
6969 shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, ps->u.ps.input_reg_map, &ps->input_signature,
6970 &ps->reg_maps, 0, &vs->output_signature, &vs->reg_maps, per_vertex_point_size);
6971 }
6972
6973 shader_addline(buffer, "}\n");
6974
6975 ret = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
6976 checkGLcall("glCreateShader(GL_VERTEX_SHADER)");
6977 shader_glsl_compile(gl_info, ret, buffer->buffer);
6978
6979 return ret;
6980 }
6981
6982 static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *priv,
6983 const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc)
6984 {
6985 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
6986 unsigned int i;
6987
6988 shader_addline(buffer, "out shader_in_out\n{\n");
6989 for (i = 0; i < so_desc->element_count; ++i)
6990 {
6991 const struct wined3d_stream_output_element *e = &so_desc->elements[i];
6992
6993 if (e->stream_idx)
6994 {
6995 FIXME("Unhandled stream %u.\n", e->stream_idx);
6996 continue;
6997 }
6998 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
6999 continue;
7000
7001 if (e->component_idx || e->component_count != 4)
7002 {
7003 if (e->component_count == 1)
7004 shader_addline(buffer, "float");
7005 else
7006 shader_addline(buffer, "vec%u", e->component_count);
7007 shader_addline(buffer, " reg%u_%u_%u;\n",
7008 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1);
7009 }
7010 else
7011 {
7012 shader_addline(buffer, "vec4 reg%u;\n", e->register_idx);
7013 }
7014 }
7015 shader_addline(buffer, "} shader_out;\n");
7016
7017 shader_addline(buffer, "void setup_gs_output(in vec4 outputs[%u])\n{\n",
7018 shader->limits->packed_output);
7019 for (i = 0; i < so_desc->element_count; ++i)
7020 {
7021 const struct wined3d_stream_output_element *e = &so_desc->elements[i];
7022
7023 if (e->stream_idx)
7024 {
7025 FIXME("Unhandled stream %u.\n", e->stream_idx);
7026 continue;
7027 }
7028 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
7029 continue;
7030
7031 if (e->component_idx || e->component_count != 4)
7032 {
7033 DWORD write_mask;
7034 char str_mask[6];
7035
7036 write_mask = ((1u << e->component_count) - 1) << e->component_idx;
7037 shader_glsl_write_mask_to_str(write_mask, str_mask);
7038 shader_addline(buffer, "shader_out.reg%u_%u_%u = outputs[%u]%s;\n",
7039 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1,
7040 e->register_idx, str_mask);
7041 }
7042 else
7043 {
7044 shader_addline(buffer, "shader_out.reg%u = outputs[%u];\n",
7045 e->register_idx, e->register_idx);
7046 }
7047 }
7048 shader_addline(buffer, "}\n");
7049 }
7050
7051 static void shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv *priv,
7052 const struct wined3d_shader *shader, unsigned int input_count,
7053 const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup, const DWORD *interpolation_mode)
7054 {
7055 const char *prefix = shader_glsl_get_prefix(shader->reg_maps.shader_version.type);
7056 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
7057
7058 if (rasterizer_setup)
7059 input_count = min(vec4_varyings(4, gl_info), input_count);
7060
7061 if (input_count)
7062 shader_glsl_declare_shader_outputs(gl_info, buffer, input_count, rasterizer_setup, interpolation_mode);
7063
7064 shader_addline(buffer, "void setup_%s_output(in vec4 outputs[%u])\n{\n",
7065 prefix, shader->limits->packed_output);
7066
7067 if (rasterizer_setup)
7068 shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, NULL, NULL,
7069 NULL, input_count, &shader->output_signature, &shader->reg_maps, FALSE);
7070 else
7071 shader_glsl_setup_sm4_shader_output(priv, input_count, &shader->output_signature,
7072 &shader->reg_maps, "shader_out", rasterizer_setup);
7073
7074 shader_addline(buffer, "}\n");
7075 }
7076
7077 static void shader_glsl_generate_patch_constant_name(struct wined3d_string_buffer *buffer,
7078 const struct wined3d_shader_signature_element *constant, unsigned int *user_constant_idx,
7079 const char *reg_mask)
7080 {
7081 if (!constant->sysval_semantic)
7082 {
7083 shader_addline(buffer, "user_patch_constant[%u]%s", (*user_constant_idx)++, reg_mask);
7084 return;
7085 }
7086
7087 switch (constant->sysval_semantic)
7088 {
7089 case WINED3D_SV_TESS_FACTOR_QUADEDGE:
7090 case WINED3D_SV_TESS_FACTOR_TRIEDGE:
7091 case WINED3D_SV_TESS_FACTOR_LINEDET:
7092 case WINED3D_SV_TESS_FACTOR_LINEDEN:
7093 shader_addline(buffer, "gl_TessLevelOuter[%u]", constant->semantic_idx);
7094 break;
7095 case WINED3D_SV_TESS_FACTOR_QUADINT:
7096 case WINED3D_SV_TESS_FACTOR_TRIINT:
7097 shader_addline(buffer, "gl_TessLevelInner[%u]", constant->semantic_idx);
7098 break;
7099 default:
7100 FIXME("Unhandled sysval semantic %#x.\n", constant->sysval_semantic);
7101 shader_addline(buffer, "vec4(0.0)%s", reg_mask);
7102 }
7103 }
7104
7105 static void shader_glsl_generate_patch_constant_setup(struct wined3d_string_buffer *buffer,
7106 const struct wined3d_shader_signature *signature, BOOL input_setup)
7107 {
7108 unsigned int i, register_count, user_constant_index, user_constant_count;
7109
7110 register_count = user_constant_count = 0;
7111 for (i = 0; i < signature->element_count; ++i)
7112 {
7113 const struct wined3d_shader_signature_element *constant = &signature->elements[i];
7114 register_count = max(constant->register_idx + 1, register_count);
7115 if (!constant->sysval_semantic)
7116 ++user_constant_count;
7117 }
7118
7119 if (user_constant_count)
7120 shader_addline(buffer, "patch %s vec4 user_patch_constant[%u];\n",
7121 input_setup ? "in" : "out", user_constant_count);
7122 if (input_setup)
7123 shader_addline(buffer, "vec4 vpc[%u];\n", register_count);
7124
7125 shader_addline(buffer, "void setup_patch_constant_%s()\n{\n", input_setup ? "input" : "output");
7126 for (i = 0, user_constant_index = 0; i < signature->element_count; ++i)
7127 {
7128 const struct wined3d_shader_signature_element *constant = &signature->elements[i];
7129 char reg_mask[6];
7130
7131 shader_glsl_write_mask_to_str(constant->mask, reg_mask);
7132
7133 if (input_setup)
7134 shader_addline(buffer, "vpc[%u]%s", constant->register_idx, reg_mask);
7135 else
7136 shader_glsl_generate_patch_constant_name(buffer, constant, &user_constant_index, reg_mask);
7137
7138 shader_addline(buffer, " = ");
7139
7140 if (input_setup)
7141 shader_glsl_generate_patch_constant_name(buffer, constant, &user_constant_index, reg_mask);
7142 else
7143 shader_addline(buffer, "hs_out[%u]%s", constant->register_idx, reg_mask);
7144
7145 shader_addline(buffer, ";\n");
7146 }
7147 shader_addline(buffer, "}\n");
7148 }
7149
7150 static void shader_glsl_generate_srgb_write_correction(struct wined3d_string_buffer *buffer,
7151 const struct wined3d_gl_info *gl_info)
7152 {
7153 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0";
7154
7155 shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(srgb_const0.x));\n", output);
7156 shader_addline(buffer, "tmp0.xyz = tmp0.xyz * vec3(srgb_const0.y) - vec3(srgb_const0.z);\n");
7157 shader_addline(buffer, "tmp1.xyz = %s.xyz * vec3(srgb_const0.w);\n", output);
7158 shader_addline(buffer, "bvec3 srgb_compare = lessThan(%s.xyz, vec3(srgb_const1.x));\n", output);
7159 shader_addline(buffer, "%s.xyz = mix(tmp0.xyz, tmp1.xyz, vec3(srgb_compare));\n", output);
7160 shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", output, output);
7161 }
7162
7163 static void shader_glsl_generate_fog_code(struct wined3d_string_buffer *buffer,
7164 const struct wined3d_gl_info *gl_info, enum wined3d_ffp_ps_fog_mode mode)
7165 {
7166 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0";
7167
7168 switch (mode)
7169 {
7170 case WINED3D_FFP_PS_FOG_OFF:
7171 return;
7172
7173 case WINED3D_FFP_PS_FOG_LINEAR:
7174 shader_addline(buffer, "float fog = (ffp_fog.end - ffp_varying_fogcoord) * ffp_fog.scale;\n");
7175 break;
7176
7177 case WINED3D_FFP_PS_FOG_EXP:
7178 shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_varying_fogcoord);\n");
7179 break;
7180
7181 case WINED3D_FFP_PS_FOG_EXP2:
7182 shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_fog.density"
7183 " * ffp_varying_fogcoord * ffp_varying_fogcoord);\n");
7184 break;
7185
7186 default:
7187 ERR("Invalid fog mode %#x.\n", mode);
7188 return;
7189 }
7190
7191 shader_addline(buffer, "%s.xyz = mix(ffp_fog.color.xyz, %s.xyz, clamp(fog, 0.0, 1.0));\n",
7192 output, output);
7193 }
7194
7195 static void shader_glsl_generate_alpha_test(struct wined3d_string_buffer *buffer,
7196 const struct wined3d_gl_info *gl_info, enum wined3d_cmp_func alpha_func)
7197 {
7198 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0";
7199
7200 /* alpha_func is the PASS condition, not the DISCARD condition. Instead of
7201 * flipping all the operators here, just negate the comparison below. */
7202 static const char * const comparison_operator[] =
7203 {
7204 "", /* WINED3D_CMP_NEVER */
7205 "<", /* WINED3D_CMP_LESS */
7206 "==", /* WINED3D_CMP_EQUAL */
7207 "<=", /* WINED3D_CMP_LESSEQUAL */
7208 ">", /* WINED3D_CMP_GREATER */
7209 "!=", /* WINED3D_CMP_NOTEQUAL */
7210 ">=", /* WINED3D_CMP_GREATEREQUAL */
7211 "" /* WINED3D_CMP_ALWAYS */
7212 };
7213
7214 if (alpha_func == WINED3D_CMP_ALWAYS)
7215 return;
7216
7217 if (alpha_func != WINED3D_CMP_NEVER)
7218 shader_addline(buffer, "if (!(%s.a %s alpha_test_ref))\n",
7219 output, comparison_operator[alpha_func - WINED3D_CMP_NEVER]);
7220 shader_addline(buffer, " discard;\n");
7221 }
7222
7223 static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer,
7224 const struct wined3d_gl_info *gl_info)
7225 {
7226 if (gl_info->supported[ARB_CULL_DISTANCE])
7227 shader_addline(buffer, "#extension GL_ARB_cull_distance : enable\n");
7228 if (gl_info->supported[ARB_GPU_SHADER5])
7229 shader_addline(buffer, "#extension GL_ARB_gpu_shader5 : enable\n");
7230 if (gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS])
7231 shader_addline(buffer, "#extension GL_ARB_shader_atomic_counters : enable\n");
7232 if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
7233 shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n");
7234 if (gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE])
7235 shader_addline(buffer, "#extension GL_ARB_shader_image_load_store : enable\n");
7236 if (gl_info->supported[ARB_SHADER_IMAGE_SIZE])
7237 shader_addline(buffer, "#extension GL_ARB_shader_image_size : enable\n");
7238 if (gl_info->supported[ARB_SHADER_STORAGE_BUFFER_OBJECT])
7239 shader_addline(buffer, "#extension GL_ARB_shader_storage_buffer_object : enable\n");
7240 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK])
7241 shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n");
7242 if (gl_info->supported[ARB_SHADING_LANGUAGE_PACKING])
7243 shader_addline(buffer, "#extension GL_ARB_shading_language_packing : enable\n");
7244 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY])
7245 shader_addline(buffer, "#extension GL_ARB_texture_cube_map_array : enable\n");
7246 if (gl_info->supported[ARB_TEXTURE_GATHER])
7247 shader_addline(buffer, "#extension GL_ARB_texture_gather : enable\n");
7248 if (gl_info->supported[ARB_TEXTURE_QUERY_LEVELS])
7249 shader_addline(buffer, "#extension GL_ARB_texture_query_levels : enable\n");
7250 if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
7251 shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n");
7252 if (gl_info->supported[EXT_GPU_SHADER4])
7253 shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
7254 if (gl_info->supported[EXT_TEXTURE_ARRAY])
7255 shader_addline(buffer, "#extension GL_EXT_texture_array : enable\n");
7256 }
7257
7258 static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_info,
7259 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader,
7260 const struct ps_compile_args *args)
7261 {
7262 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7263 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0";
7264
7265 /* Pixel shaders < 2.0 place the resulting color in R0 implicitly. */
7266 if (reg_maps->shader_version.major < 2)
7267 shader_addline(buffer, "%s = R0;\n", output);
7268
7269 if (args->srgb_correction)
7270 shader_glsl_generate_srgb_write_correction(buffer, gl_info);
7271
7272 /* SM < 3 does not replace the fog stage. */
7273 if (reg_maps->shader_version.major < 3)
7274 shader_glsl_generate_fog_code(buffer, gl_info, args->fog);
7275
7276 shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1);
7277 }
7278
7279 /* Context activation is done by the caller. */
7280 static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context,
7281 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers,
7282 const struct wined3d_shader *shader,
7283 const struct ps_compile_args *args, struct ps_np2fixup_info *np2fixup_info)
7284 {
7285 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7286 const struct wined3d_shader_version *version = &reg_maps->shader_version;
7287 const char *prefix = shader_glsl_get_prefix(version->type);
7288 const struct wined3d_gl_info *gl_info = context->gl_info;
7289 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
7290 unsigned int i, extra_constants_needed = 0;
7291 struct shader_glsl_ctx_priv priv_ctx;
7292 GLuint shader_id;
7293 DWORD map;
7294
7295 memset(&priv_ctx, 0, sizeof(priv_ctx));
7296 priv_ctx.cur_ps_args = args;
7297 priv_ctx.cur_np2fixup_info = np2fixup_info;
7298 priv_ctx.string_buffers = string_buffers;
7299
7300 shader_glsl_add_version_declaration(buffer, gl_info);
7301
7302 shader_glsl_enable_extensions(buffer, gl_info);
7303 if (gl_info->supported[ARB_CONSERVATIVE_DEPTH])
7304 shader_addline(buffer, "#extension GL_ARB_conservative_depth : enable\n");
7305 if (gl_info->supported[ARB_DERIVATIVE_CONTROL])
7306 shader_addline(buffer, "#extension GL_ARB_derivative_control : enable\n");
7307 if (shader_glsl_use_explicit_attrib_location(gl_info))
7308 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n");
7309 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS])
7310 shader_addline(buffer, "#extension GL_ARB_fragment_coord_conventions : enable\n");
7311 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT])
7312 shader_addline(buffer, "#extension GL_ARB_fragment_layer_viewport : enable\n");
7313 if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
7314 shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
7315 /* The spec says that it doesn't have to be explicitly enabled, but the
7316 * nvidia drivers write a warning if we don't do so. */
7317 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
7318 shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
7319
7320 /* Base Declarations */
7321 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
7322
7323 if (gl_info->supported[ARB_CONSERVATIVE_DEPTH])
7324 {
7325 if (shader->u.ps.depth_output == WINED3DSPR_DEPTHOUTGE)
7326 shader_addline(buffer, "layout (depth_greater) out float gl_FragDepth;\n");
7327 else if (shader->u.ps.depth_output == WINED3DSPR_DEPTHOUTLE)
7328 shader_addline(buffer, "layout (depth_less) out float gl_FragDepth;\n");
7329 }
7330
7331 /* Declare uniforms for NP2 texcoord fixup:
7332 * This is NOT done inside the loop that declares the texture samplers
7333 * since the NP2 fixup code is currently only used for the GeforceFX
7334 * series and when forcing the ARB_npot extension off. Modern cards just
7335 * skip the code anyway, so put it inside a separate loop. */
7336 if (args->np2_fixup)
7337 {
7338 struct ps_np2fixup_info *fixup = priv_ctx.cur_np2fixup_info;
7339 unsigned int cur = 0;
7340
7341 /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height]
7342 * while D3D has them in the (normalized) [0,1]x[0,1] range.
7343 * samplerNP2Fixup stores texture dimensions and is updated through
7344 * shader_glsl_load_np2fixup_constants when the sampler changes. */
7345
7346 for (i = 0; i < shader->limits->sampler; ++i)
7347 {
7348 if (!reg_maps->resource_info[i].type || !(args->np2_fixup & (1u << i)))
7349 continue;
7350
7351 if (reg_maps->resource_info[i].type != WINED3D_SHADER_RESOURCE_TEXTURE_2D)
7352 {
7353 FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n");
7354 continue;
7355 }
7356
7357 fixup->idx[i] = cur++;
7358 }
7359
7360 fixup->num_consts = (cur + 1) >> 1;
7361 fixup->active = args->np2_fixup;
7362 shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts);
7363 }
7364
7365 if (version->major < 3 || args->vp_mode != vertexshader)
7366 {
7367 shader_addline(buffer, "uniform struct\n{\n");
7368 shader_addline(buffer, " vec4 color;\n");
7369 shader_addline(buffer, " float density;\n");
7370 shader_addline(buffer, " float end;\n");
7371 shader_addline(buffer, " float scale;\n");
7372 shader_addline(buffer, "} ffp_fog;\n");
7373
7374 if (needs_legacy_glsl_syntax(gl_info))
7375 {
7376 if (glsl_is_color_reg_read(shader, 0))
7377 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
7378 if (glsl_is_color_reg_read(shader, 1))
7379 shader_addline(buffer, "vec4 ffp_varying_specular;\n");
7380 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
7381 shader_addline(buffer, "float ffp_varying_fogcoord;\n");
7382 }
7383 else
7384 {
7385 if (glsl_is_color_reg_read(shader, 0))
7386 declare_in_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_diffuse;\n");
7387 if (glsl_is_color_reg_read(shader, 1))
7388 declare_in_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_specular;\n");
7389 declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
7390 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
7391 declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
7392 }
7393 }
7394
7395 if (version->major >= 3)
7396 {
7397 unsigned int in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input);
7398
7399 if (args->vp_mode == vertexshader && reg_maps->input_registers)
7400 shader_glsl_declare_shader_inputs(gl_info, buffer, in_count,
7401 shader->u.ps.interpolation_mode, version->major >= 4);
7402 shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count);
7403 }
7404
7405 for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i)
7406 {
7407 if (!(map & 1))
7408 continue;
7409
7410 shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", i);
7411
7412 if (reg_maps->luminanceparams & (1u << i))
7413 {
7414 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", i);
7415 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", i);
7416 extra_constants_needed++;
7417 }
7418
7419 extra_constants_needed++;
7420 }
7421
7422 if (args->srgb_correction)
7423 {
7424 shader_addline(buffer, "const vec4 srgb_const0 = ");
7425 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0);
7426 shader_addline(buffer, ";\n");
7427 shader_addline(buffer, "const vec4 srgb_const1 = ");
7428 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1);
7429 shader_addline(buffer, ";\n");
7430 }
7431 if (reg_maps->vpos || reg_maps->usesdsy)
7432 {
7433 if (reg_maps->usesdsy || !gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS])
7434 {
7435 ++extra_constants_needed;
7436 shader_addline(buffer, "uniform vec4 ycorrection;\n");
7437 }
7438 if (reg_maps->vpos)
7439 {
7440 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS])
7441 {
7442 if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER)
7443 shader_addline(buffer, "layout(%spixel_center_integer) in vec4 gl_FragCoord;\n",
7444 args->render_offscreen ? "" : "origin_upper_left, ");
7445 else if (!args->render_offscreen)
7446 shader_addline(buffer, "layout(origin_upper_left) in vec4 gl_FragCoord;\n");
7447 }
7448 shader_addline(buffer, "vec4 vpos;\n");
7449 }
7450 }
7451
7452 if (args->alpha_test_func + 1 != WINED3D_CMP_ALWAYS)
7453 shader_addline(buffer, "uniform float alpha_test_ref;\n");
7454
7455 if (!needs_legacy_glsl_syntax(gl_info))
7456 {
7457 if (args->dual_source_blend)
7458 {
7459 for (i = 0; i < gl_info->limits.dual_buffers * 2; i++)
7460 {
7461 if (shader_glsl_use_explicit_attrib_location(gl_info))
7462 shader_addline(buffer, "layout(location = %u, index = %u) ", i / 2, i % 2);
7463 shader_addline(buffer, "out vec4 ps_out%u;\n", i);
7464 }
7465 }
7466 else
7467 {
7468 for (i = 0; i < gl_info->limits.buffers; i++)
7469 {
7470 if (shader_glsl_use_explicit_attrib_location(gl_info))
7471 shader_addline(buffer, "layout(location = %u) ", i);
7472 shader_addline(buffer, "out vec4 ps_out%u;\n", i);
7473 }
7474 }
7475 }
7476
7477 if (shader->limits->constant_float + extra_constants_needed >= gl_info->limits.glsl_ps_float_constants)
7478 FIXME("Insufficient uniforms to run this shader.\n");
7479
7480 if (shader->u.ps.force_early_depth_stencil)
7481 shader_addline(buffer, "layout(early_fragment_tests) in;\n");
7482
7483 shader_addline(buffer, "void main()\n{\n");
7484
7485 /* Direct3D applications expect integer vPos values, while OpenGL drivers
7486 * add approximately 0.5. This causes off-by-one problems as spotted by
7487 * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly
7488 * 0.5, but rather something like 0.49999999 or 0.50000001, which still
7489 * causes precision troubles when we just subtract 0.5.
7490 *
7491 * To deal with that, just floor() the position. This will eliminate the
7492 * fraction on all cards.
7493 *
7494 * TODO: Test how this behaves with multisampling.
7495 *
7496 * An advantage of floor is that it works even if the driver doesn't add
7497 * 0.5. It is somewhat questionable if 1.5, 2.5, ... are the proper values
7498 * to return in gl_FragCoord, even though coordinates specify the pixel
7499 * centers instead of the pixel corners. This code will behave correctly
7500 * on drivers that returns integer values. */
7501 if (reg_maps->vpos)
7502 {
7503 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS])
7504 shader_addline(buffer, "vpos = gl_FragCoord;\n");
7505 else if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER)
7506 shader_addline(buffer,
7507 "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n");
7508 else
7509 shader_addline(buffer,
7510 "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1);\n");
7511 }
7512
7513 if (reg_maps->shader_version.major < 3 || args->vp_mode != vertexshader)
7514 {
7515 unsigned int i;
7516 WORD map = reg_maps->texcoord;
7517
7518 if (legacy_syntax)
7519 {
7520 if (glsl_is_color_reg_read(shader, 0))
7521 shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n");
7522 if (glsl_is_color_reg_read(shader, 1))
7523 shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n");
7524 }
7525
7526 for (i = 0; map; map >>= 1, ++i)
7527 {
7528 if (map & 1)
7529 {
7530 if (args->pointsprite)
7531 shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", i);
7532 else if (args->texcoords_initialized & (1u << i))
7533 shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n", i,
7534 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", i);
7535 else
7536 shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", i);
7537 shader_addline(buffer, "vec4 T%u = ffp_texcoord[%u];\n", i, i);
7538 }
7539 }
7540
7541 if (legacy_syntax)
7542 shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n");
7543 }
7544
7545 /* Pack 3.0 inputs */
7546 if (reg_maps->shader_version.major >= 3)
7547 shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args, gl_info,
7548 reg_maps->shader_version.major >= 4);
7549
7550 /* Base Shader Body */
7551 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
7552 return 0;
7553
7554 /* In SM4+ the shader epilogue is generated by the "ret" instruction. */
7555 if (reg_maps->shader_version.major < 4)
7556 shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, args);
7557
7558 shader_addline(buffer, "}\n");
7559
7560 shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
7561 TRACE("Compiling shader object %u.\n", shader_id);
7562 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
7563
7564 return shader_id;
7565 }
7566
7567 static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_info,
7568 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader,
7569 const struct vs_compile_args *args)
7570 {
7571 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7572 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
7573 unsigned int i;
7574
7575 /* Unpack outputs. */
7576 shader_addline(buffer, "setup_vs_output(vs_out);\n");
7577
7578 /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
7579 * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
7580 * the fog frag coord is thrown away. If the fog frag coord is used, but not written by
7581 * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0).
7582 */
7583 if (reg_maps->shader_version.major < 3)
7584 {
7585 if (args->fog_src == VS_FOG_Z)
7586 shader_addline(buffer, "%s = gl_Position.z;\n",
7587 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord");
7588 else if (!reg_maps->fog)
7589 shader_addline(buffer, "%s = 0.0;\n",
7590 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord");
7591 }
7592
7593 /* We always store the clipplanes without y inversion. */
7594 if (args->clip_enabled)
7595 {
7596 if (legacy_syntax)
7597 shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
7598 else
7599 for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
7600 shader_addline(buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i);
7601 }
7602
7603 if (args->point_size && !args->per_vertex_point_size)
7604 shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
7605
7606 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
7607 shader_glsl_fixup_position(buffer);
7608 }
7609
7610 /* Context activation is done by the caller. */
7611 static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context,
7612 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct vs_compile_args *args)
7613 {
7614 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers;
7615 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7616 const struct wined3d_shader_version *version = &reg_maps->shader_version;
7617 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
7618 const struct wined3d_gl_info *gl_info = context->gl_info;
7619 struct shader_glsl_ctx_priv priv_ctx;
7620 GLuint shader_id;
7621 unsigned int i;
7622
7623 memset(&priv_ctx, 0, sizeof(priv_ctx));
7624 priv_ctx.cur_vs_args = args;
7625 priv_ctx.string_buffers = string_buffers;
7626
7627 shader_glsl_add_version_declaration(buffer, gl_info);
7628
7629 shader_glsl_enable_extensions(buffer, gl_info);
7630 if (gl_info->supported[ARB_DRAW_INSTANCED])
7631 shader_addline(buffer, "#extension GL_ARB_draw_instanced : enable\n");
7632 if (shader_glsl_use_explicit_attrib_location(gl_info))
7633 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n");
7634
7635 /* Base Declarations */
7636 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
7637
7638 for (i = 0; i < shader->input_signature.element_count; ++i)
7639 shader_glsl_declare_generic_vertex_attribute(buffer, gl_info, &shader->input_signature.elements[i]);
7640
7641 if (args->point_size && !args->per_vertex_point_size)
7642 {
7643 shader_addline(buffer, "uniform struct\n{\n");
7644 shader_addline(buffer, " float size;\n");
7645 shader_addline(buffer, " float size_min;\n");
7646 shader_addline(buffer, " float size_max;\n");
7647 shader_addline(buffer, "} ffp_point;\n");
7648 }
7649
7650 if (!needs_legacy_glsl_syntax(gl_info))
7651 {
7652 if (args->clip_enabled)
7653 shader_addline(buffer, "uniform vec4 clip_planes[%u];\n", gl_info->limits.user_clip_distances);
7654
7655 if (version->major < 3)
7656 {
7657 declare_out_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_diffuse;\n");
7658 declare_out_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_specular;\n");
7659 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
7660 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
7661 }
7662 }
7663
7664 if (version->major < 4)
7665 shader_addline(buffer, "void setup_vs_output(in vec4[%u]);\n", shader->limits->packed_output);
7666
7667 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
7668 shader_addline(buffer, "uniform vec4 pos_fixup;\n");
7669
7670 if (reg_maps->shader_version.major >= 4)
7671 shader_glsl_generate_sm4_output_setup(priv, shader, args->next_shader_input_count,
7672 gl_info, args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode);
7673
7674 shader_addline(buffer, "void main()\n{\n");
7675
7676 if (reg_maps->input_rel_addressing)
7677 {
7678 unsigned int highest_input_register = wined3d_log2i(reg_maps->input_registers);
7679 shader_addline(buffer, "vec4 vs_in[%u];\n", highest_input_register + 1);
7680 for (i = 0; i < shader->input_signature.element_count; ++i)
7681 {
7682 const struct wined3d_shader_signature_element *e = &shader->input_signature.elements[i];
7683 shader_addline(buffer, "vs_in[%u] = vs_in%u;\n", e->register_idx, e->register_idx);
7684 }
7685 }
7686
7687 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
7688 return 0;
7689
7690 /* In SM4+ the shader epilogue is generated by the "ret" instruction. */
7691 if (reg_maps->shader_version.major < 4)
7692 shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, args);
7693
7694 shader_addline(buffer, "}\n");
7695
7696 shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
7697 TRACE("Compiling shader object %u.\n", shader_id);
7698 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
7699
7700 return shader_id;
7701 }
7702
7703 static void shader_glsl_generate_default_control_point_phase(const struct wined3d_shader *shader,
7704 struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps)
7705 {
7706 const struct wined3d_shader_signature *output_signature = &shader->output_signature;
7707 char reg_mask[6];
7708 unsigned int i;
7709
7710 for (i = 0; i < output_signature->element_count; ++i)
7711 {
7712 const struct wined3d_shader_signature_element *output = &output_signature->elements[i];
7713
7714 shader_glsl_write_mask_to_str(output->mask, reg_mask);
7715 shader_addline(buffer, "shader_out[gl_InvocationID].reg[%u]%s = shader_in[gl_InvocationID].reg[%u]%s;\n",
7716 output->register_idx, reg_mask, output->register_idx, reg_mask);
7717 }
7718 }
7719
7720 static HRESULT shader_glsl_generate_shader_phase(const struct wined3d_shader *shader,
7721 struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps,
7722 struct shader_glsl_ctx_priv *priv_ctx, const struct wined3d_shader_phase *phase,
7723 const char *phase_name, unsigned phase_idx)
7724 {
7725 unsigned int i;
7726 HRESULT hr;
7727
7728 shader_addline(buffer, "void hs_%s_phase%u(%s)\n{\n",
7729 phase_name, phase_idx, phase->instance_count ? "int phase_instance_id" : "");
7730 for (i = 0; i < phase->temporary_count; ++i)
7731 shader_addline(buffer, "vec4 R%u;\n", i);
7732 hr = shader_generate_code(shader, buffer, reg_maps, priv_ctx, phase->start, phase->end);
7733 shader_addline(buffer, "}\n");
7734 return hr;
7735 }
7736
7737 static void shader_glsl_generate_shader_phase_invocation(struct wined3d_string_buffer *buffer,
7738 const struct wined3d_shader_phase *phase, const char *phase_name, unsigned int phase_idx)
7739 {
7740 if (phase->instance_count)
7741 {
7742 shader_addline(buffer, "for (int i = 0; i < %u; ++i)\n{\n", phase->instance_count);
7743 shader_addline(buffer, "hs_%s_phase%u(i);\n", phase_name, phase_idx);
7744 shader_addline(buffer, "}\n");
7745 }
7746 else
7747 {
7748 shader_addline(buffer, "hs_%s_phase%u();\n", phase_name, phase_idx);
7749 }
7750 }
7751
7752 static GLuint shader_glsl_generate_hull_shader(const struct wined3d_context *context,
7753 struct shader_glsl_priv *priv, const struct wined3d_shader *shader)
7754 {
7755 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers;
7756 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7757 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
7758 const struct wined3d_gl_info *gl_info = context->gl_info;
7759 const struct wined3d_hull_shader *hs = &shader->u.hs;
7760 const struct wined3d_shader_phase *phase;
7761 struct shader_glsl_ctx_priv priv_ctx;
7762 GLuint shader_id;
7763 unsigned int i;
7764
7765 memset(&priv_ctx, 0, sizeof(priv_ctx));
7766 priv_ctx.string_buffers = string_buffers;
7767
7768 shader_glsl_add_version_declaration(buffer, gl_info);
7769
7770 shader_glsl_enable_extensions(buffer, gl_info);
7771 shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n");
7772
7773 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
7774
7775 shader_addline(buffer, "layout(vertices = %u) out;\n", hs->output_vertex_count);
7776
7777 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input);
7778 shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out[];\n", shader->limits->packed_output);
7779
7780 shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, FALSE);
7781
7782 if (hs->phases.control_point)
7783 {
7784 shader_addline(buffer, "void setup_hs_output(in vec4 outputs[%u])\n{\n",
7785 shader->limits->packed_output);
7786 shader_glsl_setup_sm4_shader_output(priv, shader->limits->packed_output, &shader->output_signature,
7787 &shader->reg_maps, "shader_out[gl_InvocationID]", FALSE);
7788 shader_addline(buffer, "}\n");
7789 }
7790
7791 shader_addline(buffer, "void hs_control_point_phase()\n{\n");
7792 if ((phase = hs->phases.control_point))
7793 {
7794 for (i = 0; i < phase->temporary_count; ++i)
7795 shader_addline(buffer, "vec4 R%u;\n", i);
7796 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, phase->start, phase->end)))
7797 return 0;
7798 shader_addline(buffer, "setup_hs_output(hs_out);\n");
7799 }
7800 else
7801 {
7802 shader_glsl_generate_default_control_point_phase(shader, buffer, reg_maps);
7803 }
7804 shader_addline(buffer, "}\n");
7805
7806 for (i = 0; i < hs->phases.fork_count; ++i)
7807 {
7808 if (FAILED(shader_glsl_generate_shader_phase(shader, buffer, reg_maps, &priv_ctx,
7809 &hs->phases.fork[i], "fork", i)))
7810 return 0;
7811 }
7812
7813 for (i = 0; i < hs->phases.join_count; ++i)
7814 {
7815 if (FAILED(shader_glsl_generate_shader_phase(shader, buffer, reg_maps, &priv_ctx,
7816 &hs->phases.join[i], "join", i)))
7817 return 0;
7818 }
7819
7820 shader_addline(buffer, "void main()\n{\n");
7821 shader_addline(buffer, "hs_control_point_phase();\n");
7822 if (reg_maps->vocp)
7823 shader_addline(buffer, "barrier();\n");
7824 for (i = 0; i < hs->phases.fork_count; ++i)
7825 shader_glsl_generate_shader_phase_invocation(buffer, &hs->phases.fork[i], "fork", i);
7826 for (i = 0; i < hs->phases.join_count; ++i)
7827 shader_glsl_generate_shader_phase_invocation(buffer, &hs->phases.join[i], "join", i);
7828 shader_addline(buffer, "setup_patch_constant_output();\n");
7829 shader_addline(buffer, "}\n");
7830
7831 shader_id = GL_EXTCALL(glCreateShader(GL_TESS_CONTROL_SHADER));
7832 TRACE("Compiling shader object %u.\n", shader_id);
7833 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
7834
7835 return shader_id;
7836 }
7837
7838 static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_info,
7839 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader,
7840 const struct ds_compile_args *args)
7841 {
7842 shader_addline(buffer, "setup_ds_output(ds_out);\n");
7843
7844 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
7845 shader_glsl_fixup_position(buffer);
7846 }
7847
7848 static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context,
7849 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct ds_compile_args *args)
7850 {
7851 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers;
7852 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7853 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
7854 const struct wined3d_gl_info *gl_info = context->gl_info;
7855 struct shader_glsl_ctx_priv priv_ctx;
7856 GLuint shader_id;
7857
7858 memset(&priv_ctx, 0, sizeof(priv_ctx));
7859 priv_ctx.cur_ds_args = args;
7860 priv_ctx.string_buffers = string_buffers;
7861
7862 shader_glsl_add_version_declaration(buffer, gl_info);
7863
7864 shader_glsl_enable_extensions(buffer, gl_info);
7865 shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n");
7866
7867 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
7868
7869 shader_addline(buffer, "layout(");
7870 switch (shader->u.ds.tessellator_domain)
7871 {
7872 case WINED3D_TESSELLATOR_DOMAIN_LINE:
7873 shader_addline(buffer, "isolines");
7874 break;
7875 case WINED3D_TESSELLATOR_DOMAIN_QUAD:
7876 shader_addline(buffer, "quads");
7877 break;
7878 case WINED3D_TESSELLATOR_DOMAIN_TRIANGLE:
7879 shader_addline(buffer, "triangles");
7880 break;
7881 }
7882 switch (args->tessellator_output_primitive)
7883 {
7884 case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CW:
7885 if (args->render_offscreen)
7886 shader_addline(buffer, ", ccw");
7887 else
7888 shader_addline(buffer, ", cw");
7889 break;
7890 case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW:
7891 if (args->render_offscreen)
7892 shader_addline(buffer, ", cw");
7893 else
7894 shader_addline(buffer, ", ccw");
7895 break;
7896 case WINED3D_TESSELLATOR_OUTPUT_POINT:
7897 shader_addline(buffer, ", point_mode");
7898 break;
7899 case WINED3D_TESSELLATOR_OUTPUT_LINE:
7900 break;
7901 }
7902 switch (args->tessellator_partitioning)
7903 {
7904 case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD:
7905 shader_addline(buffer, ", fractional_odd_spacing");
7906 break;
7907 case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN:
7908 shader_addline(buffer, ", fractional_even_spacing");
7909 break;
7910 case WINED3D_TESSELLATOR_PARTITIONING_INTEGER:
7911 case WINED3D_TESSELLATOR_PARTITIONING_POW2:
7912 shader_addline(buffer, ", equal_spacing");
7913 break;
7914 }
7915 shader_addline(buffer, ") in;\n");
7916
7917 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input);
7918
7919 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
7920 shader_addline(buffer, "uniform vec4 pos_fixup;\n");
7921
7922 shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info,
7923 args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode);
7924 shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, TRUE);
7925
7926 shader_addline(buffer, "void main()\n{\n");
7927 shader_addline(buffer, "setup_patch_constant_input();\n");
7928
7929 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
7930 return 0;
7931
7932 shader_addline(buffer, "}\n");
7933
7934 shader_id = GL_EXTCALL(glCreateShader(GL_TESS_EVALUATION_SHADER));
7935 TRACE("Compiling shader object %u.\n", shader_id);
7936 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
7937
7938 return shader_id;
7939 }
7940
7941 /* Context activation is done by the caller. */
7942 static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context *context,
7943 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct gs_compile_args *args)
7944 {
7945 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers;
7946 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
7947 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
7948 const struct wined3d_gl_info *gl_info = context->gl_info;
7949 struct shader_glsl_ctx_priv priv_ctx;
7950 GLuint shader_id;
7951
7952 memset(&priv_ctx, 0, sizeof(priv_ctx));
7953 priv_ctx.string_buffers = string_buffers;
7954
7955 shader_glsl_add_version_declaration(buffer, gl_info);
7956
7957 shader_glsl_enable_extensions(buffer, gl_info);
7958
7959 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
7960
7961 shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(shader->u.gs.input_type));
7962 if (shader->u.gs.instance_count > 1)
7963 shader_addline(buffer, ", invocations = %u", shader->u.gs.instance_count);
7964 shader_addline(buffer, ") in;\n");
7965 shader_addline(buffer, "layout(%s, max_vertices = %u) out;\n",
7966 glsl_primitive_type_from_d3d(shader->u.gs.output_type), shader->u.gs.vertices_out);
7967 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input);
7968
7969 if (!gl_info->supported[ARB_CLIP_CONTROL])
7970 shader_addline(buffer, "uniform vec4 pos_fixup;\n");
7971
7972 if (is_rasterization_disabled(shader))
7973 {
7974 shader_glsl_generate_stream_output_setup(priv, shader, &shader->u.gs.so_desc);
7975 }
7976 else
7977 {
7978 shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count,
7979 gl_info, TRUE, args->interpolation_mode);
7980 }
7981 shader_addline(buffer, "void main()\n{\n");
7982 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
7983 return 0;
7984 shader_addline(buffer, "}\n");
7985
7986 shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER));
7987 TRACE("Compiling shader object %u.\n", shader_id);
7988 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
7989
7990 return shader_id;
7991 }
7992
7993 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx)
7994 {
7995 const struct shader_glsl_ctx_priv *priv = ctx->backend_data;
7996 const struct wined3d_gl_info *gl_info = ctx->gl_info;
7997 struct wined3d_string_buffer *buffer = ctx->buffer;
7998 const struct wined3d_shader *shader = ctx->shader;
7999
8000 switch (shader->reg_maps.shader_version.type)
8001 {
8002 case WINED3D_SHADER_TYPE_PIXEL:
8003 shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, priv->cur_ps_args);
8004 break;
8005 case WINED3D_SHADER_TYPE_VERTEX:
8006 shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, priv->cur_vs_args);
8007 break;
8008 case WINED3D_SHADER_TYPE_DOMAIN:
8009 shader_glsl_generate_ds_epilogue(gl_info, buffer, shader, priv->cur_ds_args);
8010 break;
8011 case WINED3D_SHADER_TYPE_GEOMETRY:
8012 case WINED3D_SHADER_TYPE_COMPUTE:
8013 break;
8014 default:
8015 FIXME("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type);
8016 break;
8017 }
8018 }
8019
8020 /* Context activation is done by the caller. */
8021 static GLuint shader_glsl_generate_compute_shader(const struct wined3d_context *context,
8022 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers,
8023 const struct wined3d_shader *shader)
8024 {
8025 const struct wined3d_shader_thread_group_size *thread_group_size = &shader->u.cs.thread_group_size;
8026 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
8027 const struct wined3d_gl_info *gl_info = context->gl_info;
8028 struct shader_glsl_ctx_priv priv_ctx;
8029 GLuint shader_id;
8030 unsigned int i;
8031
8032 memset(&priv_ctx, 0, sizeof(priv_ctx));
8033 priv_ctx.string_buffers = string_buffers;
8034
8035 shader_glsl_add_version_declaration(buffer, gl_info);
8036
8037 shader_glsl_enable_extensions(buffer, gl_info);
8038 shader_addline(buffer, "#extension GL_ARB_compute_shader : enable\n");
8039
8040 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
8041
8042 for (i = 0; i < reg_maps->tgsm_count; ++i)
8043 {
8044 if (reg_maps->tgsm[i].size)
8045 shader_addline(buffer, "shared uint cs_g%u[%u];\n", i, reg_maps->tgsm[i].size);
8046 }
8047
8048 shader_addline(buffer, "layout(local_size_x = %u, local_size_y = %u, local_size_z = %u) in;\n",
8049 thread_group_size->x, thread_group_size->y, thread_group_size->z);
8050
8051 shader_addline(buffer, "void main()\n{\n");
8052 shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL);
8053 shader_addline(buffer, "}\n");
8054
8055 shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER));
8056 TRACE("Compiling shader object %u.\n", shader_id);
8057 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
8058
8059 return shader_id;
8060 }
8061
8062 static GLuint find_glsl_pshader(const struct wined3d_context *context,
8063 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers,
8064 struct wined3d_shader *shader,
8065 const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info)
8066 {
8067 struct glsl_ps_compiled_shader *gl_shaders, *new_array;
8068 struct glsl_shader_private *shader_data;
8069 struct ps_np2fixup_info *np2fixup;
8070 UINT i;
8071 DWORD new_size;
8072 GLuint ret;
8073
8074 if (!shader->backend_data)
8075 {
8076 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data))))
8077 {
8078 ERR("Failed to allocate backend data.\n");
8079 return 0;
8080 }
8081 }
8082 shader_data = shader->backend_data;
8083 gl_shaders = shader_data->gl_shaders.ps;
8084
8085 /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
8086 * so a linear search is more performant than a hashmap or a binary search
8087 * (cache coherency etc)
8088 */
8089 for (i = 0; i < shader_data->num_gl_shaders; ++i)
8090 {
8091 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args)))
8092 {
8093 if (args->np2_fixup)
8094 *np2fixup_info = &gl_shaders[i].np2fixup;
8095 return gl_shaders[i].id;
8096 }
8097 }
8098
8099 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
8100 if (shader_data->shader_array_size == shader_data->num_gl_shaders)
8101 {
8102 if (shader_data->num_gl_shaders)
8103 {
8104 new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
8105 new_array = heap_realloc(shader_data->gl_shaders.ps, new_size * sizeof(*gl_shaders));
8106 }
8107 else
8108 {
8109 new_array = heap_alloc(sizeof(*gl_shaders));
8110 new_size = 1;
8111 }
8112
8113 if(!new_array) {
8114 ERR("Out of memory\n");
8115 return 0;
8116 }
8117 shader_data->gl_shaders.ps = new_array;
8118 shader_data->shader_array_size = new_size;
8119 gl_shaders = new_array;
8120 }
8121
8122 gl_shaders[shader_data->num_gl_shaders].args = *args;
8123
8124 np2fixup = &gl_shaders[shader_data->num_gl_shaders].np2fixup;
8125 memset(np2fixup, 0, sizeof(*np2fixup));
8126 *np2fixup_info = args->np2_fixup ? np2fixup : NULL;
8127
8128 pixelshader_update_resource_types(shader, args->tex_types);
8129
8130 string_buffer_clear(buffer);
8131 ret = shader_glsl_generate_pshader(context, buffer, string_buffers, shader, args, np2fixup);
8132 gl_shaders[shader_data->num_gl_shaders++].id = ret;
8133
8134 return ret;
8135 }
8136
8137 static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
8138 const DWORD use_map)
8139 {
8140 if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE;
8141 if((stored->clip_enabled) != new->clip_enabled) return FALSE;
8142 if (stored->point_size != new->point_size)
8143 return FALSE;
8144 if (stored->per_vertex_point_size != new->per_vertex_point_size)
8145 return FALSE;
8146 if (stored->flatshading != new->flatshading)
8147 return FALSE;
8148 if (stored->next_shader_type != new->next_shader_type)
8149 return FALSE;
8150 if (stored->next_shader_input_count != new->next_shader_input_count)
8151 return FALSE;
8152 return stored->fog_src == new->fog_src;
8153 }
8154
8155 static GLuint find_glsl_vshader(const struct wined3d_context *context, struct shader_glsl_priv *priv,
8156 struct wined3d_shader *shader, const struct vs_compile_args *args)
8157 {
8158 UINT i;
8159 DWORD new_size;
8160 DWORD use_map = context->stream_info.use_map;
8161 struct glsl_vs_compiled_shader *gl_shaders, *new_array;
8162 struct glsl_shader_private *shader_data;
8163 GLuint ret;
8164
8165 if (!shader->backend_data)
8166 {
8167 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data))))
8168 {
8169 ERR("Failed to allocate backend data.\n");
8170 return 0;
8171 }
8172 }
8173 shader_data = shader->backend_data;
8174 gl_shaders = shader_data->gl_shaders.vs;
8175
8176 /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
8177 * so a linear search is more performant than a hashmap or a binary search
8178 * (cache coherency etc)
8179 */
8180 for (i = 0; i < shader_data->num_gl_shaders; ++i)
8181 {
8182 if (vs_args_equal(&gl_shaders[i].args, args, use_map))
8183 return gl_shaders[i].id;
8184 }
8185
8186 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
8187
8188 if (shader_data->shader_array_size == shader_data->num_gl_shaders)
8189 {
8190 if (shader_data->num_gl_shaders)
8191 {
8192 new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
8193 new_array = heap_realloc(shader_data->gl_shaders.vs, new_size * sizeof(*gl_shaders));
8194 }
8195 else
8196 {
8197 new_array = heap_alloc(sizeof(*gl_shaders));
8198 new_size = 1;
8199 }
8200
8201 if(!new_array) {
8202 ERR("Out of memory\n");
8203 return 0;
8204 }
8205 shader_data->gl_shaders.vs = new_array;
8206 shader_data->shader_array_size = new_size;
8207 gl_shaders = new_array;
8208 }
8209
8210 gl_shaders[shader_data->num_gl_shaders].args = *args;
8211
8212 string_buffer_clear(&priv->shader_buffer);
8213 ret = shader_glsl_generate_vshader(context, priv, shader, args);
8214 gl_shaders[shader_data->num_gl_shaders++].id = ret;
8215
8216 return ret;
8217 }
8218
8219 static GLuint find_glsl_hull_shader(const struct wined3d_context *context,
8220 struct shader_glsl_priv *priv, struct wined3d_shader *shader)
8221 {
8222 struct glsl_hs_compiled_shader *gl_shaders, *new_array;
8223 struct glsl_shader_private *shader_data;
8224 unsigned int new_size;
8225 GLuint ret;
8226
8227 if (!shader->backend_data)
8228 {
8229 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data))))
8230 {
8231 ERR("Failed to allocate backend data.\n");
8232 return 0;
8233 }
8234 }
8235 shader_data = shader->backend_data;
8236 gl_shaders = shader_data->gl_shaders.hs;
8237
8238 if (shader_data->num_gl_shaders > 0)
8239 {
8240 assert(shader_data->num_gl_shaders == 1);
8241 return gl_shaders[0].id;
8242 }
8243
8244 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
8245
8246 assert(!shader_data->gl_shaders.hs);
8247 new_size = 1;
8248 if (!(new_array = heap_alloc(sizeof(*new_array))))
8249 {
8250 ERR("Failed to allocate GL shaders array.\n");
8251 return 0;
8252 }
8253 shader_data->gl_shaders.hs = new_array;
8254 shader_data->shader_array_size = new_size;
8255 gl_shaders = new_array;
8256
8257 string_buffer_clear(&priv->shader_buffer);
8258 ret = shader_glsl_generate_hull_shader(context, priv, shader);
8259 gl_shaders[shader_data->num_gl_shaders++].id = ret;
8260
8261 return ret;
8262 }
8263
8264 static GLuint find_glsl_domain_shader(const struct wined3d_context *context,
8265 struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct ds_compile_args *args)
8266 {
8267 struct glsl_ds_compiled_shader *gl_shaders, *new_array;
8268 struct glsl_shader_private *shader_data;
8269 unsigned int i, new_size;
8270 GLuint ret;
8271
8272 if (!shader->backend_data)
8273 {
8274 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data))))
8275 {
8276 ERR("Failed to allocate backend data.\n");
8277 return 0;
8278 }
8279 }
8280 shader_data = shader->backend_data;
8281 gl_shaders = shader_data->gl_shaders.ds;
8282
8283 for (i = 0; i < shader_data->num_gl_shaders; ++i)
8284 {
8285 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args)))
8286 return gl_shaders[i].id;
8287 }
8288
8289 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
8290
8291 if (shader_data->num_gl_shaders)
8292 {
8293 new_size = shader_data->shader_array_size + 1;
8294 new_array = heap_realloc(shader_data->gl_shaders.ds, new_size * sizeof(*new_array));
8295 }
8296 else
8297 {
8298 new_array = heap_alloc(sizeof(*new_array));
8299 new_size = 1;
8300 }
8301
8302 if (!new_array)
8303 {
8304 ERR("Failed to allocate GL shaders array.\n");
8305 return 0;
8306 }
8307 shader_data->gl_shaders.ds = new_array;
8308 shader_data->shader_array_size = new_size;
8309 gl_shaders = new_array;
8310
8311 string_buffer_clear(&priv->shader_buffer);
8312 ret = shader_glsl_generate_domain_shader(context, priv, shader, args);
8313 gl_shaders[shader_data->num_gl_shaders].args = *args;
8314 gl_shaders[shader_data->num_gl_shaders++].id = ret;
8315
8316 return ret;
8317 }
8318
8319 static GLuint find_glsl_geometry_shader(const struct wined3d_context *context,
8320 struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct gs_compile_args *args)
8321 {
8322 struct glsl_gs_compiled_shader *gl_shaders, *new_array;
8323 struct glsl_shader_private *shader_data;
8324 unsigned int i, new_size;
8325 GLuint ret;
8326
8327 if (!shader->backend_data)
8328 {
8329 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data))))
8330 {
8331 ERR("Failed to allocate backend data.\n");
8332 return 0;
8333 }
8334 }
8335 shader_data = shader->backend_data;
8336 gl_shaders = shader_data->gl_shaders.gs;
8337
8338 for (i = 0; i < shader_data->num_gl_shaders; ++i)
8339 {
8340 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args)))
8341 return gl_shaders[i].id;
8342 }
8343
8344 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
8345
8346 if (shader_data->num_gl_shaders)
8347 {
8348 new_size = shader_data->shader_array_size + 1;
8349 new_array = heap_realloc(shader_data->gl_shaders.gs, new_size * sizeof(*new_array));
8350 }
8351 else
8352 {
8353 new_array = heap_alloc(sizeof(*new_array));
8354 new_size = 1;
8355 }
8356
8357 if (!new_array)
8358 {
8359 ERR("Failed to allocate GL shaders array.\n");
8360 return 0;
8361 }
8362 shader_data->gl_shaders.gs = new_array;
8363 shader_data->shader_array_size = new_size;
8364 gl_shaders = new_array;
8365
8366 string_buffer_clear(&priv->shader_buffer);
8367 ret = shader_glsl_generate_geometry_shader(context, priv, shader, args);
8368 gl_shaders[shader_data->num_gl_shaders].args = *args;
8369 gl_shaders[shader_data->num_gl_shaders++].id = ret;
8370
8371 return ret;
8372 }
8373
8374 static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, const char *material)
8375 {
8376 switch (mcs)
8377 {
8378 case WINED3D_MCS_MATERIAL:
8379 return material;
8380 case WINED3D_MCS_COLOR1:
8381 return "ffp_attrib_diffuse";
8382 case WINED3D_MCS_COLOR2:
8383 return "ffp_attrib_specular";
8384 default:
8385 ERR("Invalid material color source %#x.\n", mcs);
8386 return "<invalid>";
8387 }
8388 }
8389
8390 static void shader_glsl_ffp_vertex_lighting_footer(struct wined3d_string_buffer *buffer,
8391 const struct wined3d_ffp_vs_settings *settings, unsigned int idx)
8392 {
8393 shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
8394 " * ffp_light[%u].diffuse.xyz * att;\n", idx);
8395 if (settings->localviewer)
8396 shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
8397 else
8398 shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
8399 shader_addline(buffer, "if (dot(dir, normal) > 0.0 && t > 0.0) specular +="
8400 " pow(t, ffp_material.shininess) * ffp_light[%u].specular * att;\n", idx);
8401 }
8402
8403 static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer,
8404 const struct wined3d_ffp_vs_settings *settings, BOOL legacy_lighting)
8405 {
8406 const char *diffuse, *specular, *emissive, *ambient;
8407 unsigned int i, idx;
8408
8409 if (!settings->lighting)
8410 {
8411 shader_addline(buffer, "ffp_varying_diffuse = ffp_attrib_diffuse;\n");
8412 shader_addline(buffer, "ffp_varying_specular = ffp_attrib_specular;\n");
8413 return;
8414 }
8415
8416 shader_addline(buffer, "vec3 ambient = ffp_light_ambient;\n");
8417 shader_addline(buffer, "vec3 diffuse = vec3(0.0);\n");
8418 shader_addline(buffer, "vec4 specular = vec4(0.0);\n");
8419 shader_addline(buffer, "vec3 dir, dst;\n");
8420 shader_addline(buffer, "float att, t;\n");
8421
8422 ambient = shader_glsl_ffp_mcs(settings->ambient_source, "ffp_material.ambient");
8423 diffuse = shader_glsl_ffp_mcs(settings->diffuse_source, "ffp_material.diffuse");
8424 specular = shader_glsl_ffp_mcs(settings->specular_source, "ffp_material.specular");
8425 emissive = shader_glsl_ffp_mcs(settings->emissive_source, "ffp_material.emissive");
8426
8427 idx = 0;
8428 for (i = 0; i < settings->point_light_count; ++i, ++idx)
8429 {
8430 shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx);
8431 shader_addline(buffer, "dst.z = dot(dir, dir);\n");
8432 shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
8433 shader_addline(buffer, "dst.x = 1.0;\n");
8434 if (legacy_lighting)
8435 {
8436 shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx);
8437 shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
8438 shader_addline(buffer, "if (dst.y > 0.0)\n{\n");
8439 }
8440 else
8441 {
8442 shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx);
8443 }
8444 shader_addline(buffer, "att = dot(dst.xyz, vec3(ffp_light[%u].c_att,"
8445 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", idx, idx, idx);
8446 if (!legacy_lighting)
8447 shader_addline(buffer, "att = 1.0 / att;\n");
8448 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx);
8449 if (!settings->normal)
8450 {
8451 shader_addline(buffer, "}\n");
8452 continue;
8453 }
8454 shader_addline(buffer, "dir = normalize(dir);\n");
8455 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx);
8456 shader_addline(buffer, "}\n");
8457 }
8458
8459 for (i = 0; i < settings->spot_light_count; ++i, ++idx)
8460 {
8461 shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx);
8462 shader_addline(buffer, "dst.z = dot(dir, dir);\n");
8463 shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
8464 shader_addline(buffer, "dst.x = 1.0;\n");
8465 if (legacy_lighting)
8466 {
8467 shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx);
8468 shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
8469 shader_addline(buffer, "if (dst.y > 0.0)\n{\n");
8470 }
8471 else
8472 {
8473 shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx);
8474 }
8475 shader_addline(buffer, "dir = normalize(dir);\n");
8476 shader_addline(buffer, "t = dot(-dir, normalize(ffp_light[%u].direction));\n", idx);
8477 shader_addline(buffer, "if (t > ffp_light[%u].cos_htheta) att = 1.0;\n", idx);
8478 shader_addline(buffer, "else if (t <= ffp_light[%u].cos_hphi) att = 0.0;\n", idx);
8479 shader_addline(buffer, "else att = pow((t - ffp_light[%u].cos_hphi)"
8480 " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff);\n",
8481 idx, idx, idx, idx);
8482 if (legacy_lighting)
8483 shader_addline(buffer, "att *= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
8484 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
8485 idx, idx, idx);
8486 else
8487 shader_addline(buffer, "att /= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
8488 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
8489 idx, idx, idx);
8490 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx);
8491 if (!settings->normal)
8492 {
8493 shader_addline(buffer, "}\n");
8494 continue;
8495 }
8496 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx);
8497 shader_addline(buffer, "}\n");
8498 }
8499
8500 for (i = 0; i < settings->directional_light_count; ++i, ++idx)
8501 {
8502 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx);
8503 if (!settings->normal)
8504 continue;
8505 shader_addline(buffer, "att = 1.0;\n");
8506 shader_addline(buffer, "dir = normalize(ffp_light[%u].direction.xyz);\n", idx);
8507 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx);
8508 }
8509
8510 for (i = 0; i < settings->parallel_point_light_count; ++i, ++idx)
8511 {
8512 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx);
8513 if (!settings->normal)
8514 continue;
8515 shader_addline(buffer, "att = 1.0;\n");
8516 shader_addline(buffer, "dir = normalize(ffp_light[%u].position.xyz);\n", idx);
8517 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx);
8518 }
8519
8520 shader_addline(buffer, "ffp_varying_diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
8521 ambient, diffuse, emissive);
8522 shader_addline(buffer, "ffp_varying_diffuse.w = %s.w;\n", diffuse);
8523 shader_addline(buffer, "ffp_varying_specular = %s * specular;\n", specular);
8524 }
8525
8526 /* Context activation is done by the caller. */
8527 static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *priv,
8528 const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
8529 {
8530 static const struct attrib_info
8531 {
8532 const char type[6];
8533 const char name[24];
8534 }
8535 attrib_info[] =
8536 {
8537 {"vec4", "ffp_attrib_position"}, /* WINED3D_FFP_POSITION */
8538 {"vec4", "ffp_attrib_blendweight"}, /* WINED3D_FFP_BLENDWEIGHT */
8539 {"vec4", "ffp_attrib_blendindices"}, /* WINED3D_FFP_BLENDINDICES */
8540 {"vec3", "ffp_attrib_normal"}, /* WINED3D_FFP_NORMAL */
8541 {"float", "ffp_attrib_psize"}, /* WINED3D_FFP_PSIZE */
8542 {"vec4", "ffp_attrib_diffuse"}, /* WINED3D_FFP_DIFFUSE */
8543 {"vec4", "ffp_attrib_specular"}, /* WINED3D_FFP_SPECULAR */
8544 };
8545 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
8546 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
8547 BOOL output_legacy_fogcoord = legacy_syntax;
8548 BOOL legacy_lighting = priv->legacy_lighting;
8549 GLuint shader_obj;
8550 unsigned int i;
8551 char var[64];
8552
8553 string_buffer_clear(buffer);
8554
8555 shader_glsl_add_version_declaration(buffer, gl_info);
8556
8557 if (shader_glsl_use_explicit_attrib_location(gl_info))
8558 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n");
8559
8560 for (i = 0; i < WINED3D_FFP_ATTRIBS_COUNT; ++i)
8561 {
8562 const char *type = i < ARRAY_SIZE(attrib_info) ? attrib_info[i].type : "vec4";
8563
8564 if (shader_glsl_use_explicit_attrib_location(gl_info))
8565 shader_addline(buffer, "layout(location = %u) ", i);
8566 shader_addline(buffer, "%s %s vs_in%u;\n", get_attribute_keyword(gl_info), type, i);
8567 }
8568 shader_addline(buffer, "\n");
8569
8570 shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS);
8571 shader_addline(buffer, "uniform mat3 ffp_normal_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS);
8572 shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n");
8573 shader_addline(buffer, "uniform mat4 ffp_texture_matrix[%u];\n", MAX_TEXTURES);
8574
8575 shader_addline(buffer, "uniform struct\n{\n");
8576 shader_addline(buffer, " vec4 emissive;\n");
8577 shader_addline(buffer, " vec4 ambient;\n");
8578 shader_addline(buffer, " vec4 diffuse;\n");
8579 shader_addline(buffer, " vec4 specular;\n");
8580 shader_addline(buffer, " float shininess;\n");
8581 shader_addline(buffer, "} ffp_material;\n");
8582
8583 shader_addline(buffer, "uniform vec3 ffp_light_ambient;\n");
8584 shader_addline(buffer, "uniform struct\n{\n");
8585 shader_addline(buffer, " vec4 diffuse;\n");
8586 shader_addline(buffer, " vec4 specular;\n");
8587 shader_addline(buffer, " vec4 ambient;\n");
8588 shader_addline(buffer, " vec4 position;\n");
8589 shader_addline(buffer, " vec3 direction;\n");
8590 shader_addline(buffer, " float range;\n");
8591 shader_addline(buffer, " float falloff;\n");
8592 shader_addline(buffer, " float c_att;\n");
8593 shader_addline(buffer, " float l_att;\n");
8594 shader_addline(buffer, " float q_att;\n");
8595 shader_addline(buffer, " float cos_htheta;\n");
8596 shader_addline(buffer, " float cos_hphi;\n");
8597 shader_addline(buffer, "} ffp_light[%u];\n", MAX_ACTIVE_LIGHTS);
8598
8599 if (settings->point_size)
8600 {
8601 shader_addline(buffer, "uniform struct\n{\n");
8602 shader_addline(buffer, " float size;\n");
8603 shader_addline(buffer, " float size_min;\n");
8604 shader_addline(buffer, " float size_max;\n");
8605 shader_addline(buffer, " float c_att;\n");
8606 shader_addline(buffer, " float l_att;\n");
8607 shader_addline(buffer, " float q_att;\n");
8608 shader_addline(buffer, "} ffp_point;\n");
8609 }
8610
8611 if (legacy_syntax)
8612 {
8613 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
8614 shader_addline(buffer, "vec4 ffp_varying_specular;\n");
8615 shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
8616 shader_addline(buffer, "float ffp_varying_fogcoord;\n");
8617 }
8618 else
8619 {
8620 if (settings->clipping)
8621 shader_addline(buffer, "uniform vec4 clip_planes[%u];\n", gl_info->limits.user_clip_distances);
8622
8623 declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n");
8624 declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_specular;\n");
8625 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
8626 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
8627 }
8628
8629 shader_addline(buffer, "\nvoid main()\n{\n");
8630 shader_addline(buffer, "float m;\n");
8631 shader_addline(buffer, "vec3 r;\n");
8632
8633 for (i = 0; i < ARRAY_SIZE(attrib_info); ++i)
8634 {
8635 if (attrib_info[i].name[0])
8636 shader_addline(buffer, "%s %s = vs_in%u%s;\n", attrib_info[i].type, attrib_info[i].name,
8637 i, settings->swizzle_map & (1u << i) ? ".zyxw" : "");
8638 }
8639 for (i = 0; i < MAX_TEXTURES; ++i)
8640 {
8641 unsigned int coord_idx = settings->texgen[i] & 0x0000ffff;
8642 if ((settings->texgen[i] & 0xffff0000) == WINED3DTSS_TCI_PASSTHRU
8643 && settings->texcoords & (1u << i))
8644 shader_addline(buffer, "vec4 ffp_attrib_texcoord%u = vs_in%u;\n", i, coord_idx + WINED3D_FFP_TEXCOORD0);
8645 }
8646
8647 shader_addline(buffer, "ffp_attrib_blendweight[%u] = 1.0;\n", settings->vertexblends);
8648
8649 if (settings->transformed)
8650 {
8651 shader_addline(buffer, "vec4 ec_pos = vec4(ffp_attrib_position.xyz, 1.0);\n");
8652 shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n");
8653 shader_addline(buffer, "if (ffp_attrib_position.w != 0.0) gl_Position /= ffp_attrib_position.w;\n");
8654 }
8655 else
8656 {
8657 if (!settings->sw_blending)
8658 {
8659 for (i = 0; i < settings->vertexblends; ++i)
8660 shader_addline(buffer, "ffp_attrib_blendweight[%u] -= ffp_attrib_blendweight[%u];\n", settings->vertexblends, i);
8661
8662 shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n");
8663 for (i = 0; i < settings->vertexblends + 1; ++i)
8664 {
8665 sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i);
8666 shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%s] * ffp_attrib_position);\n", i, var);
8667 }
8668 }
8669 else
8670 {
8671 shader_addline(buffer, "vec4 ec_pos = ffp_attrib_position;\n");
8672 }
8673
8674 shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n");
8675 if (settings->clipping)
8676 {
8677 if (legacy_syntax)
8678 shader_addline(buffer, "gl_ClipVertex = ec_pos;\n");
8679 else
8680 for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
8681 shader_addline(buffer, "gl_ClipDistance[%u] = dot(ec_pos, clip_planes[%u]);\n", i, i);
8682 }
8683 shader_addline(buffer, "ec_pos /= ec_pos.w;\n");
8684 }
8685
8686 shader_addline(buffer, "vec3 normal = vec3(0.0);\n");
8687 if (settings->normal)
8688 {
8689 if (!settings->sw_blending)
8690 {
8691 for (i = 0; i < settings->vertexblends + 1; ++i)
8692 {
8693 sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i);
8694 shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (ffp_normal_matrix[%s] * ffp_attrib_normal);\n", i, var);
8695 }
8696 }
8697 else
8698 {
8699 shader_addline(buffer, "normal = ffp_attrib_normal;\n");
8700 }
8701
8702 if (settings->normalize)
8703 shader_addline(buffer, "normal = normalize(normal);\n");
8704 }
8705
8706 shader_glsl_ffp_vertex_lighting(buffer, settings, legacy_lighting);
8707 if (legacy_syntax)
8708 {
8709 shader_addline(buffer, "gl_FrontColor = ffp_varying_diffuse;\n");
8710 shader_addline(buffer, "gl_FrontSecondaryColor = ffp_varying_specular;\n");
8711 }
8712 else
8713 {
8714 shader_addline(buffer, "ffp_varying_diffuse = clamp(ffp_varying_diffuse, 0.0, 1.0);\n");
8715 shader_addline(buffer, "ffp_varying_specular = clamp(ffp_varying_specular, 0.0, 1.0);\n");
8716 }
8717
8718 for (i = 0; i < MAX_TEXTURES; ++i)
8719 {
8720 BOOL output_legacy_texcoord = legacy_syntax;
8721
8722 switch (settings->texgen[i] & 0xffff0000)
8723 {
8724 case WINED3DTSS_TCI_PASSTHRU:
8725 if (settings->texcoords & (1u << i))
8726 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ffp_attrib_texcoord%u;\n",
8727 i, i, i);
8728 else if (gl_info->limits.glsl_varyings >= wined3d_max_compat_varyings(gl_info))
8729 shader_addline(buffer, "ffp_varying_texcoord[%u] = vec4(0.0);\n", i);
8730 else
8731 output_legacy_texcoord = FALSE;
8732 break;
8733
8734 case WINED3DTSS_TCI_CAMERASPACENORMAL:
8735 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * vec4(normal, 1.0);\n", i, i);
8736 break;
8737
8738 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
8739 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ec_pos;\n", i, i);
8740 break;
8741
8742 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
8743 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]"
8744 " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i);
8745 break;
8746
8747 case WINED3DTSS_TCI_SPHEREMAP:
8748 shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n");
8749 shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n");
8750 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]"
8751 " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);\n", i, i);
8752 break;
8753
8754 default:
8755 ERR("Unhandled texgen %#x.\n", settings->texgen[i]);
8756 break;
8757 }
8758 if (output_legacy_texcoord)
8759 shader_addline(buffer, "gl_TexCoord[%u] = ffp_varying_texcoord[%u];\n", i, i);
8760 }
8761
8762 switch (settings->fog_mode)
8763 {
8764 case WINED3D_FFP_VS_FOG_OFF:
8765 output_legacy_fogcoord = FALSE;
8766 break;
8767
8768 case WINED3D_FFP_VS_FOG_FOGCOORD:
8769 shader_addline(buffer, "ffp_varying_fogcoord = ffp_attrib_specular.w * 255.0;\n");
8770 break;
8771
8772 case WINED3D_FFP_VS_FOG_RANGE:
8773 shader_addline(buffer, "ffp_varying_fogcoord = length(ec_pos.xyz);\n");
8774 break;
8775
8776 case WINED3D_FFP_VS_FOG_DEPTH:
8777 if (settings->ortho_fog)
8778 {
8779 if (gl_info->supported[ARB_CLIP_CONTROL])
8780 shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z;\n");
8781 else
8782 /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */
8783 shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z * 0.5 + 0.5;\n");
8784 }
8785 else if (settings->transformed)
8786 {
8787 shader_addline(buffer, "ffp_varying_fogcoord = ec_pos.z;\n");
8788 }
8789 else
8790 {
8791 shader_addline(buffer, "ffp_varying_fogcoord = abs(ec_pos.z);\n");
8792 }
8793 break;
8794
8795 default:
8796 ERR("Unhandled fog mode %#x.\n", settings->fog_mode);
8797 break;
8798 }
8799 if (output_legacy_fogcoord)
8800 shader_addline(buffer, "gl_FogFragCoord = ffp_varying_fogcoord;\n");
8801
8802 if (settings->point_size)
8803 {
8804 shader_addline(buffer, "gl_PointSize = %s / sqrt(ffp_point.c_att"
8805 " + ffp_point.l_att * length(ec_pos.xyz)"
8806 " + ffp_point.q_att * dot(ec_pos.xyz, ec_pos.xyz));\n",
8807 settings->per_vertex_point_size ? "ffp_attrib_psize" : "ffp_point.size");
8808 shader_addline(buffer, "gl_PointSize = clamp(gl_PointSize, ffp_point.size_min, ffp_point.size_max);\n");
8809 }
8810
8811 shader_addline(buffer, "}\n");
8812
8813 shader_obj = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
8814 shader_glsl_compile(gl_info, shader_obj, buffer->buffer);
8815
8816 return shader_obj;
8817 }
8818
8819 static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buffer *buffer,
8820 DWORD argnum, unsigned int stage, DWORD arg)
8821 {
8822 const char *ret;
8823
8824 if (arg == ARG_UNUSED)
8825 return "<unused arg>";
8826
8827 switch (arg & WINED3DTA_SELECTMASK)
8828 {
8829 case WINED3DTA_DIFFUSE:
8830 ret = "ffp_varying_diffuse";
8831 break;
8832
8833 case WINED3DTA_CURRENT:
8834 ret = "ret";
8835 break;
8836
8837 case WINED3DTA_TEXTURE:
8838 switch (stage)
8839 {
8840 case 0: ret = "tex0"; break;
8841 case 1: ret = "tex1"; break;
8842 case 2: ret = "tex2"; break;
8843 case 3: ret = "tex3"; break;
8844 case 4: ret = "tex4"; break;
8845 case 5: ret = "tex5"; break;
8846 case 6: ret = "tex6"; break;
8847 case 7: ret = "tex7"; break;
8848 default:
8849 ret = "<invalid texture>";
8850 break;
8851 }
8852 break;
8853
8854 case WINED3DTA_TFACTOR:
8855 ret = "tex_factor";
8856 break;
8857
8858 case WINED3DTA_SPECULAR:
8859 ret = "ffp_varying_specular";
8860 break;
8861
8862 case WINED3DTA_TEMP:
8863 ret = "temp_reg";
8864 break;
8865
8866 case WINED3DTA_CONSTANT:
8867 switch (stage)
8868 {
8869 case 0: ret = "tss_const0"; break;
8870 case 1: ret = "tss_const1"; break;
8871 case 2: ret = "tss_const2"; break;
8872 case 3: ret = "tss_const3"; break;
8873 case 4: ret = "tss_const4"; break;
8874 case 5: ret = "tss_const5"; break;
8875 case 6: ret = "tss_const6"; break;
8876 case 7: ret = "tss_const7"; break;
8877 default:
8878 ret = "<invalid constant>";
8879 break;
8880 }
8881 break;
8882
8883 default:
8884 return "<unhandled arg>";
8885 }
8886
8887 if (arg & WINED3DTA_COMPLEMENT)
8888 {
8889 shader_addline(buffer, "arg%u = vec4(1.0) - %s;\n", argnum, ret);
8890 if (argnum == 0)
8891 ret = "arg0";
8892 else if (argnum == 1)
8893 ret = "arg1";
8894 else if (argnum == 2)
8895 ret = "arg2";
8896 }
8897
8898 if (arg & WINED3DTA_ALPHAREPLICATE)
8899 {
8900 shader_addline(buffer, "arg%u = vec4(%s.w);\n", argnum, ret);
8901 if (argnum == 0)
8902 ret = "arg0";
8903 else if (argnum == 1)
8904 ret = "arg1";
8905 else if (argnum == 2)
8906 ret = "arg2";
8907 }
8908
8909 return ret;
8910 }
8911
8912 static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL color,
8913 BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2)
8914 {
8915 const char *dstmask, *dstreg, *arg0, *arg1, *arg2;
8916
8917 if (color && alpha)
8918 dstmask = "";
8919 else if (color)
8920 dstmask = ".xyz";
8921 else
8922 dstmask = ".w";
8923
8924 if (dst == tempreg)
8925 dstreg = "temp_reg";
8926 else
8927 dstreg = "ret";
8928
8929 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0);
8930 arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1);
8931 arg2 = shader_glsl_get_ffp_fragment_op_arg(buffer, 2, stage, dw_arg2);
8932
8933 switch (op)
8934 {
8935 case WINED3D_TOP_DISABLE:
8936 break;
8937
8938 case WINED3D_TOP_SELECT_ARG1:
8939 shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg1, dstmask);
8940 break;
8941
8942 case WINED3D_TOP_SELECT_ARG2:
8943 shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg2, dstmask);
8944 break;
8945
8946 case WINED3D_TOP_MODULATE:
8947 shader_addline(buffer, "%s%s = %s%s * %s%s;\n", dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8948 break;
8949
8950 case WINED3D_TOP_MODULATE_4X:
8951 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 4.0, 0.0, 1.0);\n",
8952 dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8953 break;
8954
8955 case WINED3D_TOP_MODULATE_2X:
8956 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 2.0, 0.0, 1.0);\n",
8957 dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8958 break;
8959
8960 case WINED3D_TOP_ADD:
8961 shader_addline(buffer, "%s%s = clamp(%s%s + %s%s, 0.0, 1.0);\n",
8962 dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8963 break;
8964
8965 case WINED3D_TOP_ADD_SIGNED:
8966 shader_addline(buffer, "%s%s = clamp(%s%s + (%s - vec4(0.5))%s, 0.0, 1.0);\n",
8967 dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8968 break;
8969
8970 case WINED3D_TOP_ADD_SIGNED_2X:
8971 shader_addline(buffer, "%s%s = clamp((%s%s + (%s - vec4(0.5))%s) * 2.0, 0.0, 1.0);\n",
8972 dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8973 break;
8974
8975 case WINED3D_TOP_SUBTRACT:
8976 shader_addline(buffer, "%s%s = clamp(%s%s - %s%s, 0.0, 1.0);\n",
8977 dstreg, dstmask, arg1, dstmask, arg2, dstmask);
8978 break;
8979
8980 case WINED3D_TOP_ADD_SMOOTH:
8981 shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s%s, 0.0, 1.0);\n",
8982 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1, dstmask);
8983 break;
8984
8985 case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
8986 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_DIFFUSE);
8987 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
8988 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
8989 break;
8990
8991 case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
8992 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE);
8993 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
8994 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
8995 break;
8996
8997 case WINED3D_TOP_BLEND_FACTOR_ALPHA:
8998 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TFACTOR);
8999 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
9000 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
9001 break;
9002
9003 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
9004 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE);
9005 shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n",
9006 dstreg, dstmask, arg2, dstmask, arg0, arg1, dstmask);
9007 break;
9008
9009 case WINED3D_TOP_BLEND_CURRENT_ALPHA:
9010 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_CURRENT);
9011 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
9012 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
9013 break;
9014
9015 case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
9016 shader_addline(buffer, "%s%s = clamp(%s%s * %s.w + %s%s, 0.0, 1.0);\n",
9017 dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask);
9018 break;
9019
9020 case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
9021 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s.w, 0.0, 1.0);\n",
9022 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1);
9023 break;
9024
9025 case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
9026 shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n",
9027 dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask);
9028 break;
9029 case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
9030 shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s.w, 0.0, 1.0);\n",
9031 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1);
9032 break;
9033
9034 case WINED3D_TOP_BUMPENVMAP:
9035 case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
9036 /* These are handled in the first pass, nothing to do. */
9037 break;
9038
9039 case WINED3D_TOP_DOTPRODUCT3:
9040 shader_addline(buffer, "%s%s = vec4(clamp(dot(%s.xyz - 0.5, %s.xyz - 0.5) * 4.0, 0.0, 1.0))%s;\n",
9041 dstreg, dstmask, arg1, arg2, dstmask);
9042 break;
9043
9044 case WINED3D_TOP_MULTIPLY_ADD:
9045 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s%s, 0.0, 1.0);\n",
9046 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg0, dstmask);
9047 break;
9048
9049 case WINED3D_TOP_LERP:
9050 /* MSDN isn't quite right here. */
9051 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s%s);\n",
9052 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0, dstmask);
9053 break;
9054
9055 default:
9056 FIXME("Unhandled operation %#x.\n", op);
9057 break;
9058 }
9059 }
9060
9061 /* Context activation is done by the caller. */
9062 static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *priv,
9063 const struct ffp_frag_settings *settings, const struct wined3d_context *context)
9064 {
9065 const char *output = needs_legacy_glsl_syntax(context->gl_info) ? "gl_FragData[0]" : "ps_out0";
9066 struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers);
9067 enum wined3d_cmp_func alpha_test_func = settings->alpha_test_func + 1;
9068 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
9069 BYTE lum_map = 0, bump_map = 0, tex_map = 0, tss_const_map = 0;
9070 const struct wined3d_gl_info *gl_info = context->gl_info;
9071 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
9072 BOOL tempreg_used = FALSE, tfactor_used = FALSE;
9073 UINT lowest_disabled_stage;
9074 GLuint shader_id;
9075 DWORD arg0, arg1, arg2;
9076 unsigned int stage;
9077
9078 string_buffer_clear(buffer);
9079
9080 /* Find out which textures are read */
9081 for (stage = 0; stage < MAX_TEXTURES; ++stage)
9082 {
9083 if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
9084 break;
9085
9086 arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK;
9087 arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK;
9088 arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK;
9089
9090 if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE
9091 || (stage == 0 && settings->color_key_enabled))
9092 tex_map |= 1u << stage;
9093 if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
9094 tfactor_used = TRUE;
9095 if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
9096 tempreg_used = TRUE;
9097 if (settings->op[stage].dst == tempreg)
9098 tempreg_used = TRUE;
9099 if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
9100 tss_const_map |= 1u << stage;
9101
9102 switch (settings->op[stage].cop)
9103 {
9104 case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
9105 lum_map |= 1u << stage;
9106 /* fall through */
9107 case WINED3D_TOP_BUMPENVMAP:
9108 bump_map |= 1u << stage;
9109 /* fall through */
9110 case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
9111 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
9112 tex_map |= 1u << stage;
9113 break;
9114
9115 case WINED3D_TOP_BLEND_FACTOR_ALPHA:
9116 tfactor_used = TRUE;
9117 break;
9118
9119 default:
9120 break;
9121 }
9122
9123 if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
9124 continue;
9125
9126 arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK;
9127 arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK;
9128 arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK;
9129
9130 if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE)
9131 tex_map |= 1u << stage;
9132 if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
9133 tfactor_used = TRUE;
9134 if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
9135 tempreg_used = TRUE;
9136 if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
9137 tss_const_map |= 1u << stage;
9138 }
9139 lowest_disabled_stage = stage;
9140
9141 shader_glsl_add_version_declaration(buffer, gl_info);
9142
9143 if (shader_glsl_use_explicit_attrib_location(gl_info))
9144 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n");
9145 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK])
9146 shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n");
9147 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
9148 shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
9149
9150 if (!needs_legacy_glsl_syntax(gl_info))
9151 {
9152 if (shader_glsl_use_explicit_attrib_location(gl_info))
9153 shader_addline(buffer, "layout(location = 0) ");
9154 shader_addline(buffer, "out vec4 ps_out0;\n");
9155 }
9156
9157 shader_addline(buffer, "vec4 tmp0, tmp1;\n");
9158 shader_addline(buffer, "vec4 ret;\n");
9159 if (tempreg_used || settings->sRGB_write)
9160 shader_addline(buffer, "vec4 temp_reg = vec4(0.0);\n");
9161 shader_addline(buffer, "vec4 arg0, arg1, arg2;\n");
9162
9163 for (stage = 0; stage < MAX_TEXTURES; ++stage)
9164 {
9165 const char *sampler_type;
9166
9167 if (tss_const_map & (1u << stage))
9168 shader_addline(buffer, "uniform vec4 tss_const%u;\n", stage);
9169
9170 if (!(tex_map & (1u << stage)))
9171 continue;
9172
9173 switch (settings->op[stage].tex_type)
9174 {
9175 case WINED3D_GL_RES_TYPE_TEX_1D:
9176 sampler_type = "1D";
9177 break;
9178 case WINED3D_GL_RES_TYPE_TEX_2D:
9179 sampler_type = "2D";
9180 break;
9181 case WINED3D_GL_RES_TYPE_TEX_3D:
9182 sampler_type = "3D";
9183 break;
9184 case WINED3D_GL_RES_TYPE_TEX_CUBE:
9185 sampler_type = "Cube";
9186 break;
9187 case WINED3D_GL_RES_TYPE_TEX_RECT:
9188 sampler_type = "2DRect";
9189 break;
9190 default:
9191 FIXME("Unhandled sampler type %#x.\n", settings->op[stage].tex_type);
9192 sampler_type = NULL;
9193 break;
9194 }
9195 if (sampler_type)
9196 {
9197 if (shader_glsl_use_layout_binding_qualifier(gl_info))
9198 shader_glsl_append_sampler_binding_qualifier(buffer, context, NULL, stage);
9199 shader_addline(buffer, "uniform sampler%s ps_sampler%u;\n", sampler_type, stage);
9200 }
9201
9202 shader_addline(buffer, "vec4 tex%u;\n", stage);
9203
9204 if (!(bump_map & (1u << stage)))
9205 continue;
9206 shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", stage);
9207
9208 if (!(lum_map & (1u << stage)))
9209 continue;
9210 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", stage);
9211 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", stage);
9212 }
9213 if (tfactor_used)
9214 shader_addline(buffer, "uniform vec4 tex_factor;\n");
9215 if (settings->color_key_enabled)
9216 shader_addline(buffer, "uniform vec4 color_key[2];\n");
9217 shader_addline(buffer, "uniform vec4 specular_enable;\n");
9218
9219 if (settings->sRGB_write)
9220 {
9221 shader_addline(buffer, "const vec4 srgb_const0 = ");
9222 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0);
9223 shader_addline(buffer, ";\n");
9224 shader_addline(buffer, "const vec4 srgb_const1 = ");
9225 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1);
9226 shader_addline(buffer, ";\n");
9227 }
9228
9229 shader_addline(buffer, "uniform struct\n{\n");
9230 shader_addline(buffer, " vec4 color;\n");
9231 shader_addline(buffer, " float density;\n");
9232 shader_addline(buffer, " float end;\n");
9233 shader_addline(buffer, " float scale;\n");
9234 shader_addline(buffer, "} ffp_fog;\n");
9235
9236 if (alpha_test_func != WINED3D_CMP_ALWAYS)
9237 shader_addline(buffer, "uniform float alpha_test_ref;\n");
9238
9239 if (legacy_syntax)
9240 {
9241 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
9242 shader_addline(buffer, "vec4 ffp_varying_specular;\n");
9243 shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
9244 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
9245 shader_addline(buffer, "float ffp_varying_fogcoord;\n");
9246 }
9247 else
9248 {
9249 declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n");
9250 declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_specular;\n");
9251 declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
9252 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
9253 declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
9254 }
9255
9256 shader_addline(buffer, "void main()\n{\n");
9257
9258 if (legacy_syntax)
9259 {
9260 shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n");
9261 shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n");
9262 }
9263
9264 for (stage = 0; stage < MAX_TEXTURES; ++stage)
9265 {
9266 if (tex_map & (1u << stage))
9267 {
9268 if (settings->pointsprite)
9269 shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", stage);
9270 else if (settings->texcoords_initialized & (1u << stage))
9271 shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n",
9272 stage, legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", stage);
9273 else
9274 shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", stage);
9275 }
9276 }
9277
9278 if (legacy_syntax && settings->fog != WINED3D_FFP_PS_FOG_OFF)
9279 shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n");
9280
9281 if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
9282 shader_addline(buffer, "if (any(lessThan(ffp_texcoord[7], vec4(0.0)))) discard;\n");
9283
9284 /* Generate texture sampling instructions */
9285 for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage)
9286 {
9287 const char *texture_function, *coord_mask;
9288 BOOL proj;
9289
9290 if (!(tex_map & (1u << stage)))
9291 continue;
9292
9293 if (settings->op[stage].projected == proj_none)
9294 {
9295 proj = FALSE;
9296 }
9297 else if (settings->op[stage].projected == proj_count4
9298 || settings->op[stage].projected == proj_count3)
9299 {
9300 proj = TRUE;
9301 }
9302 else
9303 {
9304 FIXME("Unexpected projection mode %d\n", settings->op[stage].projected);
9305 proj = TRUE;
9306 }
9307
9308 if (settings->op[stage].tex_type == WINED3D_GL_RES_TYPE_TEX_CUBE)
9309 proj = FALSE;
9310
9311 switch (settings->op[stage].tex_type)
9312 {
9313 case WINED3D_GL_RES_TYPE_TEX_1D:
9314 if (proj)
9315 {
9316 texture_function = "texture1DProj";
9317 coord_mask = "xw";
9318 }
9319 else
9320 {
9321 texture_function = "texture1D";
9322 coord_mask = "x";
9323 }
9324 break;
9325 case WINED3D_GL_RES_TYPE_TEX_2D:
9326 if (proj)
9327 {
9328 texture_function = "texture2DProj";
9329 coord_mask = "xyw";
9330 }
9331 else
9332 {
9333 texture_function = "texture2D";
9334 coord_mask = "xy";
9335 }
9336 break;
9337 case WINED3D_GL_RES_TYPE_TEX_3D:
9338 if (proj)
9339 {
9340 texture_function = "texture3DProj";
9341 coord_mask = "xyzw";
9342 }
9343 else
9344 {
9345 texture_function = "texture3D";
9346 coord_mask = "xyz";
9347 }
9348 break;
9349 case WINED3D_GL_RES_TYPE_TEX_CUBE:
9350 texture_function = "textureCube";
9351 coord_mask = "xyz";
9352 break;
9353 case WINED3D_GL_RES_TYPE_TEX_RECT:
9354 if (proj)
9355 {
9356 texture_function = "texture2DRectProj";
9357 coord_mask = "xyw";
9358 }
9359 else
9360 {
9361 texture_function = "texture2DRect";
9362 coord_mask = "xy";
9363 }
9364 break;
9365 default:
9366 FIXME("Unhandled texture type %#x.\n", settings->op[stage].tex_type);
9367 texture_function = "";
9368 coord_mask = "xyzw";
9369 break;
9370 }
9371 if (!legacy_syntax)
9372 texture_function = proj ? "textureProj" : "texture";
9373
9374 if (stage > 0
9375 && (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
9376 || settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
9377 {
9378 shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1);
9379
9380 /* With projective textures, texbem only divides the static
9381 * texture coord, not the displacement, so multiply the
9382 * displacement with the dividing parameter before passing it to
9383 * TXP. */
9384 if (settings->op[stage].projected != proj_none)
9385 {
9386 if (settings->op[stage].projected == proj_count4)
9387 {
9388 shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n",
9389 stage, stage);
9390 shader_addline(buffer, "ret.zw = ffp_texcoord[%u].ww;\n", stage);
9391 }
9392 else
9393 {
9394 shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].z) + ffp_texcoord[%u].xy;\n",
9395 stage, stage);
9396 shader_addline(buffer, "ret.zw = ffp_texcoord[%u].zz;\n", stage);
9397 }
9398 }
9399 else
9400 {
9401 shader_addline(buffer, "ret = ffp_texcoord[%u] + ret.xyxy;\n", stage);
9402 }
9403
9404 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ret.%s);\n",
9405 stage, texture_function, stage, coord_mask);
9406
9407 if (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
9408 shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n",
9409 stage, stage - 1, stage - 1, stage - 1);
9410 }
9411 else if (settings->op[stage].projected == proj_count3)
9412 {
9413 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n",
9414 stage, texture_function, stage, stage);
9415 }
9416 else
9417 {
9418 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].%s);\n",
9419 stage, texture_function, stage, stage, coord_mask);
9420 }
9421
9422 string_buffer_sprintf(tex_reg_name, "tex%u", stage);
9423 shader_glsl_color_correction_ext(buffer, tex_reg_name->buffer, WINED3DSP_WRITEMASK_ALL,
9424 settings->op[stage].color_fixup);
9425 }
9426
9427 if (settings->color_key_enabled)
9428 {
9429 shader_addline(buffer, "if (all(greaterThanEqual(tex0, color_key[0])) && all(lessThan(tex0, color_key[1])))\n");
9430 shader_addline(buffer, " discard;\n");
9431 }
9432
9433 shader_addline(buffer, "ret = ffp_varying_diffuse;\n");
9434
9435 /* Generate the main shader */
9436 for (stage = 0; stage < MAX_TEXTURES; ++stage)
9437 {
9438 BOOL op_equal;
9439
9440 if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
9441 break;
9442
9443 if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1
9444 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1)
9445 op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1;
9446 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1
9447 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2)
9448 op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2;
9449 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2
9450 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1)
9451 op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1;
9452 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2
9453 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2)
9454 op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2;
9455 else
9456 op_equal = settings->op[stage].aop == settings->op[stage].cop
9457 && settings->op[stage].carg0 == settings->op[stage].aarg0
9458 && settings->op[stage].carg1 == settings->op[stage].aarg1
9459 && settings->op[stage].carg2 == settings->op[stage].aarg2;
9460
9461 if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
9462 {
9463 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst,
9464 settings->op[stage].cop, settings->op[stage].carg0,
9465 settings->op[stage].carg1, settings->op[stage].carg2);
9466 }
9467 else if (op_equal)
9468 {
9469 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].dst,
9470 settings->op[stage].cop, settings->op[stage].carg0,
9471 settings->op[stage].carg1, settings->op[stage].carg2);
9472 }
9473 else if (settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP
9474 && settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
9475 {
9476 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst,
9477 settings->op[stage].cop, settings->op[stage].carg0,
9478 settings->op[stage].carg1, settings->op[stage].carg2);
9479 shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].dst,
9480 settings->op[stage].aop, settings->op[stage].aarg0,
9481 settings->op[stage].aarg1, settings->op[stage].aarg2);
9482 }
9483 }
9484
9485 shader_addline(buffer, "%s = ffp_varying_specular * specular_enable + ret;\n", output);
9486
9487 if (settings->sRGB_write)
9488 shader_glsl_generate_srgb_write_correction(buffer, gl_info);
9489
9490 shader_glsl_generate_fog_code(buffer, gl_info, settings->fog);
9491
9492 shader_glsl_generate_alpha_test(buffer, gl_info, alpha_test_func);
9493
9494 shader_addline(buffer, "}\n");
9495
9496 shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
9497 shader_glsl_compile(gl_info, shader_id, buffer->buffer);
9498
9499 string_buffer_release(&priv->string_buffers, tex_reg_name);
9500 return shader_id;
9501 }
9502
9503 static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv *priv,
9504 const struct wined3d_gl_info *gl_info, const struct wined3d_ffp_vs_settings *settings)
9505 {
9506 struct glsl_ffp_vertex_shader *shader;
9507 const struct wine_rb_entry *entry;
9508
9509 if ((entry = wine_rb_get(&priv->ffp_vertex_shaders, settings)))
9510 return WINE_RB_ENTRY_VALUE(entry, struct glsl_ffp_vertex_shader, desc.entry);
9511
9512 if (!(shader = heap_alloc(sizeof(*shader))))
9513 return NULL;
9514
9515 shader->desc.settings = *settings;
9516 shader->id = shader_glsl_generate_ffp_vertex_shader(priv, settings, gl_info);
9517 list_init(&shader->linked_programs);
9518 if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1)
9519 ERR("Failed to insert ffp vertex shader.\n");
9520
9521 return shader;
9522 }
9523
9524 static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv,
9525 const struct ffp_frag_settings *args, const struct wined3d_context *context)
9526 {
9527 struct glsl_ffp_fragment_shader *glsl_desc;
9528 const struct ffp_frag_desc *desc;
9529
9530 if ((desc = find_ffp_frag_shader(&priv->ffp_fragment_shaders, args)))
9531 return CONTAINING_RECORD(desc, struct glsl_ffp_fragment_shader, entry);
9532
9533 if (!(glsl_desc = heap_alloc(sizeof(*glsl_desc))))
9534 return NULL;
9535
9536 glsl_desc->entry.settings = *args;
9537 glsl_desc->id = shader_glsl_generate_ffp_fragment_shader(priv, args, context);
9538 list_init(&glsl_desc->linked_programs);
9539 add_ffp_frag_shader(&priv->ffp_fragment_shaders, &glsl_desc->entry);
9540
9541 return glsl_desc;
9542 }
9543
9544
9545 static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info *gl_info,
9546 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_vs_program *vs, unsigned int vs_c_count)
9547 {
9548 unsigned int i;
9549 struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers);
9550
9551 for (i = 0; i < vs_c_count; ++i)
9552 {
9553 string_buffer_sprintf(name, "vs_c[%u]", i);
9554 vs->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9555 }
9556 memset(&vs->uniform_f_locations[vs_c_count], 0xff, (WINED3D_MAX_VS_CONSTS_F - vs_c_count) * sizeof(GLuint));
9557
9558 for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i)
9559 {
9560 string_buffer_sprintf(name, "vs_i[%u]", i);
9561 vs->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9562 }
9563
9564 for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i)
9565 {
9566 string_buffer_sprintf(name, "vs_b[%u]", i);
9567 vs->uniform_b_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9568 }
9569
9570 vs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup"));
9571
9572 for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i)
9573 {
9574 string_buffer_sprintf(name, "ffp_modelview_matrix[%u]", i);
9575 vs->modelview_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9576 }
9577 for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i)
9578 {
9579 string_buffer_sprintf(name, "ffp_normal_matrix[%u]", i);
9580 vs->normal_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9581 }
9582 vs->projection_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_projection_matrix"));
9583 for (i = 0; i < MAX_TEXTURES; ++i)
9584 {
9585 string_buffer_sprintf(name, "ffp_texture_matrix[%u]", i);
9586 vs->texture_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9587 }
9588 vs->material_ambient_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.ambient"));
9589 vs->material_diffuse_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.diffuse"));
9590 vs->material_specular_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.specular"));
9591 vs->material_emissive_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.emissive"));
9592 vs->material_shininess_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.shininess"));
9593 vs->light_ambient_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_light_ambient"));
9594 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
9595 {
9596 string_buffer_sprintf(name, "ffp_light[%u].diffuse", i);
9597 vs->light_location[i].diffuse = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9598 string_buffer_sprintf(name, "ffp_light[%u].specular", i);
9599 vs->light_location[i].specular = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9600 string_buffer_sprintf(name, "ffp_light[%u].ambient", i);
9601 vs->light_location[i].ambient = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9602 string_buffer_sprintf(name, "ffp_light[%u].position", i);
9603 vs->light_location[i].position = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9604 string_buffer_sprintf(name, "ffp_light[%u].direction", i);
9605 vs->light_location[i].direction = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9606 string_buffer_sprintf(name, "ffp_light[%u].range", i);
9607 vs->light_location[i].range = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9608 string_buffer_sprintf(name, "ffp_light[%u].falloff", i);
9609 vs->light_location[i].falloff = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9610 string_buffer_sprintf(name, "ffp_light[%u].c_att", i);
9611 vs->light_location[i].c_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9612 string_buffer_sprintf(name, "ffp_light[%u].l_att", i);
9613 vs->light_location[i].l_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9614 string_buffer_sprintf(name, "ffp_light[%u].q_att", i);
9615 vs->light_location[i].q_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9616 string_buffer_sprintf(name, "ffp_light[%u].cos_htheta", i);
9617 vs->light_location[i].cos_htheta = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9618 string_buffer_sprintf(name, "ffp_light[%u].cos_hphi", i);
9619 vs->light_location[i].cos_hphi = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9620 }
9621 vs->pointsize_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size"));
9622 vs->pointsize_min_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size_min"));
9623 vs->pointsize_max_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size_max"));
9624 vs->pointsize_c_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.c_att"));
9625 vs->pointsize_l_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.l_att"));
9626 vs->pointsize_q_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.q_att"));
9627 vs->clip_planes_location = GL_EXTCALL(glGetUniformLocation(program_id, "clip_planes"));
9628
9629 string_buffer_release(&priv->string_buffers, name);
9630 }
9631
9632 static void shader_glsl_init_ds_uniform_locations(const struct wined3d_gl_info *gl_info,
9633 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ds_program *ds)
9634 {
9635 ds->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup"));
9636 }
9637
9638 static void shader_glsl_init_gs_uniform_locations(const struct wined3d_gl_info *gl_info,
9639 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_gs_program *gs)
9640 {
9641 gs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup"));
9642 }
9643
9644 static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *gl_info,
9645 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ps_program *ps, unsigned int ps_c_count)
9646 {
9647 unsigned int i;
9648 struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers);
9649
9650 for (i = 0; i < ps_c_count; ++i)
9651 {
9652 string_buffer_sprintf(name, "ps_c[%u]", i);
9653 ps->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9654 }
9655 memset(&ps->uniform_f_locations[ps_c_count], 0xff, (WINED3D_MAX_PS_CONSTS_F - ps_c_count) * sizeof(GLuint));
9656
9657 for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i)
9658 {
9659 string_buffer_sprintf(name, "ps_i[%u]", i);
9660 ps->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9661 }
9662
9663 for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i)
9664 {
9665 string_buffer_sprintf(name, "ps_b[%u]", i);
9666 ps->uniform_b_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9667 }
9668
9669 for (i = 0; i < MAX_TEXTURES; ++i)
9670 {
9671 string_buffer_sprintf(name, "bumpenv_mat%u", i);
9672 ps->bumpenv_mat_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9673 string_buffer_sprintf(name, "bumpenv_lum_scale%u", i);
9674 ps->bumpenv_lum_scale_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9675 string_buffer_sprintf(name, "bumpenv_lum_offset%u", i);
9676 ps->bumpenv_lum_offset_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9677 string_buffer_sprintf(name, "tss_const%u", i);
9678 ps->tss_constant_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
9679 }
9680
9681 ps->tex_factor_location = GL_EXTCALL(glGetUniformLocation(program_id, "tex_factor"));
9682 ps->specular_enable_location = GL_EXTCALL(glGetUniformLocation(program_id, "specular_enable"));
9683
9684 ps->fog_color_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.color"));
9685 ps->fog_density_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.density"));
9686 ps->fog_end_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.end"));
9687 ps->fog_scale_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.scale"));
9688
9689 ps->alpha_test_ref_location = GL_EXTCALL(glGetUniformLocation(program_id, "alpha_test_ref"));
9690
9691 ps->np2_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "ps_samplerNP2Fixup"));
9692 ps->ycorrection_location = GL_EXTCALL(glGetUniformLocation(program_id, "ycorrection"));
9693 ps->color_key_location = GL_EXTCALL(glGetUniformLocation(program_id, "color_key"));
9694
9695 string_buffer_release(&priv->string_buffers, name);
9696 }
9697
9698 static HRESULT shader_glsl_compile_compute_shader(struct shader_glsl_priv *priv,
9699 const struct wined3d_context *context, struct wined3d_shader *shader)
9700 {
9701 struct glsl_context_data *ctx_data = context->shader_backend_data;
9702 struct wined3d_string_buffer *buffer = &priv->shader_buffer;
9703 const struct wined3d_gl_info *gl_info = context->gl_info;
9704 struct glsl_cs_compiled_shader *gl_shaders;
9705 struct glsl_shader_private *shader_data;
9706 struct glsl_shader_prog_link *entry;
9707 GLuint shader_id, program_id;
9708
9709 if (!(entry = heap_alloc(sizeof(*entry))))
9710 {
9711 ERR("Out of memory.\n");
9712 return E_OUTOFMEMORY;
9713 }
9714
9715 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data))))
9716 {
9717 ERR("Failed to allocate backend data.\n");
9718 heap_free(entry);
9719 return E_OUTOFMEMORY;
9720 }
9721 shader_data = shader->backend_data;
9722 gl_shaders = shader_data->gl_shaders.cs;
9723
9724 if (!(shader_data->gl_shaders.cs = heap_alloc(sizeof(*gl_shaders))))
9725 {
9726 ERR("Failed to allocate GL shader array.\n");
9727 heap_free(entry);
9728 heap_free(shader->backend_data);
9729 shader->backend_data = NULL;
9730 return E_OUTOFMEMORY;
9731 }
9732 shader_data->shader_array_size = 1;
9733 gl_shaders = shader_data->gl_shaders.cs;
9734
9735 TRACE("Compiling compute shader %p.\n", shader);
9736
9737 string_buffer_clear(buffer);
9738 shader_id = shader_glsl_generate_compute_shader(context, buffer, &priv->string_buffers, shader);
9739 gl_shaders[shader_data->num_gl_shaders++].id = shader_id;
9740
9741 program_id = GL_EXTCALL(glCreateProgram());
9742 TRACE("Created new GLSL shader program %u.\n", program_id);
9743
9744 entry->id = program_id;
9745 entry->vs.id = 0;
9746 entry->hs.id = 0;
9747 entry->ds.id = 0;
9748 entry->gs.id = 0;
9749 entry->ps.id = 0;
9750 entry->cs.id = shader_id;
9751 entry->constant_version = 0;
9752 entry->shader_controlled_clip_distances = 0;
9753 entry->ps.np2_fixup_info = NULL;
9754 add_glsl_program_entry(priv, entry);
9755
9756 TRACE("Attaching GLSL shader object %u to program %u.\n", shader_id, program_id);
9757 GL_EXTCALL(glAttachShader(program_id, shader_id));
9758 checkGLcall("glAttachShader");
9759
9760 list_add_head(&shader->linked_programs, &entry->cs.shader_entry);
9761
9762 TRACE("Linking GLSL shader program %u.\n", program_id);
9763 GL_EXTCALL(glLinkProgram(program_id));
9764 shader_glsl_validate_link(gl_info, program_id);
9765
9766 GL_EXTCALL(glUseProgram(program_id));
9767 checkGLcall("glUseProgram");
9768 shader_glsl_load_program_resources(context, priv, program_id, shader);
9769 shader_glsl_load_images(gl_info, priv, program_id, &shader->reg_maps);
9770
9771 entry->constant_update_mask = 0;
9772
9773 GL_EXTCALL(glUseProgram(ctx_data->glsl_program ? ctx_data->glsl_program->id : 0));
9774 checkGLcall("glUseProgram");
9775 return WINED3D_OK;
9776 }
9777
9778 static GLuint find_glsl_compute_shader(const struct wined3d_context *context,
9779 struct shader_glsl_priv *priv, struct wined3d_shader *shader)
9780 {
9781 struct glsl_shader_private *shader_data;
9782
9783 if (!shader->backend_data)
9784 {
9785 WARN("Failed to find GLSL program for compute shader %p.\n", shader);
9786 if (FAILED(shader_glsl_compile_compute_shader(priv, context, shader)))
9787 {
9788 ERR("Failed to compile compute shader %p.\n", shader);
9789 return 0;
9790 }
9791 }
9792 shader_data = shader->backend_data;
9793 return shader_data->gl_shaders.cs[0].id;
9794 }
9795
9796 /* Context activation is done by the caller. */
9797 static void set_glsl_compute_shader_program(const struct wined3d_context *context,
9798 const struct wined3d_state *state, struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data)
9799 {
9800 struct glsl_shader_prog_link *entry;
9801 struct wined3d_shader *shader;
9802 struct glsl_program_key key;
9803 GLuint cs_id;
9804
9805 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE)))
9806 return;
9807
9808 if (!(shader = state->shader[WINED3D_SHADER_TYPE_COMPUTE]))
9809 {
9810 WARN("Compute shader is NULL.\n");
9811 ctx_data->glsl_program = NULL;
9812 return;
9813 }
9814
9815 cs_id = find_glsl_compute_shader(context, priv, shader);
9816 memset(&key, 0, sizeof(key));
9817 key.cs_id = cs_id;
9818 if (!(entry = get_glsl_program_entry(priv, &key)))
9819 ERR("Failed to find GLSL program for compute shader %p.\n", shader);
9820 ctx_data->glsl_program = entry;
9821 }
9822
9823 /* Context activation is done by the caller. */
9824 static void set_glsl_shader_program(const struct wined3d_context *context, const struct wined3d_state *state,
9825 struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data)
9826 {
9827 const struct wined3d_d3d_info *d3d_info = context->d3d_info;
9828 const struct wined3d_gl_info *gl_info = context->gl_info;
9829 const struct wined3d_shader *pre_rasterization_shader;
9830 const struct ps_np2fixup_info *np2fixup_info = NULL;
9831 struct wined3d_shader *hshader, *dshader, *gshader;
9832 struct glsl_shader_prog_link *entry = NULL;
9833 struct wined3d_shader *vshader = NULL;
9834 struct wined3d_shader *pshader = NULL;
9835 GLuint reorder_shader_id = 0;
9836 struct glsl_program_key key;
9837 GLuint program_id;
9838 unsigned int i;
9839 GLuint vs_id = 0;
9840 GLuint hs_id = 0;
9841 GLuint ds_id = 0;
9842 GLuint gs_id = 0;
9843 GLuint ps_id = 0;
9844 struct list *ps_list = NULL, *vs_list = NULL;
9845 WORD attribs_map;
9846 struct wined3d_string_buffer *tmp_name;
9847
9848 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_VERTEX)) && ctx_data->glsl_program)
9849 {
9850 vs_id = ctx_data->glsl_program->vs.id;
9851 vs_list = &ctx_data->glsl_program->vs.shader_entry;
9852
9853 if (use_vs(state))
9854 vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
9855 }
9856 else if (use_vs(state))
9857 {
9858 struct vs_compile_args vs_compile_args;
9859
9860 vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
9861
9862 find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args, context);
9863 vs_id = find_glsl_vshader(context, priv, vshader, &vs_compile_args);
9864 vs_list = &vshader->linked_programs;
9865 }
9866 else if (priv->vertex_pipe == &glsl_vertex_pipe)
9867 {
9868 struct glsl_ffp_vertex_shader *ffp_shader;
9869 struct wined3d_ffp_vs_settings settings;
9870
9871 wined3d_ffp_get_vs_settings(context, state, &settings);
9872 ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings);
9873 vs_id = ffp_shader->id;
9874 vs_list = &ffp_shader->linked_programs;
9875 }
9876
9877 hshader = state->shader[WINED3D_SHADER_TYPE_HULL];
9878 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_HULL)) && ctx_data->glsl_program)
9879 hs_id = ctx_data->glsl_program->hs.id;
9880 else if (hshader)
9881 hs_id = find_glsl_hull_shader(context, priv, hshader);
9882
9883 dshader = state->shader[WINED3D_SHADER_TYPE_DOMAIN];
9884 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_DOMAIN)) && ctx_data->glsl_program)
9885 {
9886 ds_id = ctx_data->glsl_program->ds.id;
9887 }
9888 else if (dshader)
9889 {
9890 struct ds_compile_args args;
9891
9892 find_ds_compile_args(state, dshader, &args, context);
9893 ds_id = find_glsl_domain_shader(context, priv, dshader, &args);
9894 }
9895
9896 gshader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
9897 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_GEOMETRY)) && ctx_data->glsl_program)
9898 {
9899 gs_id = ctx_data->glsl_program->gs.id;
9900 }
9901 else if (gshader)
9902 {
9903 struct gs_compile_args args;
9904
9905 find_gs_compile_args(state, gshader, &args, context);
9906 gs_id = find_glsl_geometry_shader(context, priv, gshader, &args);
9907 }
9908
9909 /* A pixel shader is not used when rasterization is disabled. */
9910 if (is_rasterization_disabled(gshader))
9911 {
9912 ps_id = 0;
9913 ps_list = NULL;
9914 }
9915 else if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_PIXEL)) && ctx_data->glsl_program)
9916 {
9917 ps_id = ctx_data->glsl_program->ps.id;
9918 ps_list = &ctx_data->glsl_program->ps.shader_entry;
9919
9920 if (use_ps(state))
9921 pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
9922 }
9923 else if (use_ps(state))
9924 {
9925 struct ps_compile_args ps_compile_args;
9926 pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
9927 find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, context);
9928 ps_id = find_glsl_pshader(context, &priv->shader_buffer, &priv->string_buffers,
9929 pshader, &ps_compile_args, &np2fixup_info);
9930 ps_list = &pshader->linked_programs;
9931 }
9932 else if (priv->fragment_pipe == &glsl_fragment_pipe
9933 && !(vshader && vshader->reg_maps.shader_version.major >= 4))
9934 {
9935 struct glsl_ffp_fragment_shader *ffp_shader;
9936 struct ffp_frag_settings settings;
9937
9938 gen_ffp_frag_op(context, state, &settings, FALSE);
9939 ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, &settings, context);
9940 ps_id = ffp_shader->id;
9941 ps_list = &ffp_shader->linked_programs;
9942 }
9943
9944 key.vs_id = vs_id;
9945 key.hs_id = hs_id;
9946 key.ds_id = ds_id;
9947 key.gs_id = gs_id;
9948 key.ps_id = ps_id;
9949 key.cs_id = 0;
9950 if ((!vs_id && !hs_id && !ds_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, &key)))
9951 {
9952 ctx_data->glsl_program = entry;
9953 return;
9954 }
9955
9956 /* If we get to this point, then no matching program exists, so we create one */
9957 program_id = GL_EXTCALL(glCreateProgram());
9958 TRACE("Created new GLSL shader program %u.\n", program_id);
9959
9960 /* Create the entry */
9961 entry = heap_alloc(sizeof(*entry));
9962 entry->id = program_id;
9963 entry->vs.id = vs_id;
9964 entry->hs.id = hs_id;
9965 entry->ds.id = ds_id;
9966 entry->gs.id = gs_id;
9967 entry->ps.id = ps_id;
9968 entry->cs.id = 0;
9969 entry->constant_version = 0;
9970 entry->shader_controlled_clip_distances = 0;
9971 entry->ps.np2_fixup_info = np2fixup_info;
9972 /* Add the hash table entry */
9973 add_glsl_program_entry(priv, entry);
9974
9975 /* Set the current program */
9976 ctx_data->glsl_program = entry;
9977
9978 /* Attach GLSL vshader */
9979 if (vs_id)
9980 {
9981 TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, program_id);
9982 GL_EXTCALL(glAttachShader(program_id, vs_id));
9983 checkGLcall("glAttachShader");
9984
9985 list_add_head(vs_list, &entry->vs.shader_entry);
9986 }
9987
9988 if (vshader)
9989 {
9990 attribs_map = vshader->reg_maps.input_registers;
9991 if (vshader->reg_maps.shader_version.major < 4)
9992 {
9993 reorder_shader_id = shader_glsl_generate_vs3_rasterizer_input_setup(priv, vshader, pshader,
9994 state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size,
9995 d3d_info->emulated_flatshading
9996 && state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT, gl_info);
9997 TRACE("Attaching GLSL shader object %u to program %u.\n", reorder_shader_id, program_id);
9998 GL_EXTCALL(glAttachShader(program_id, reorder_shader_id));
9999 checkGLcall("glAttachShader");
10000 /* Flag the reorder function for deletion, it will be freed
10001 * automatically when the program is destroyed. */
10002 GL_EXTCALL(glDeleteShader(reorder_shader_id));
10003 }
10004 }
10005 else
10006 {
10007 attribs_map = (1u << WINED3D_FFP_ATTRIBS_COUNT) - 1;
10008 }
10009
10010 if (!shader_glsl_use_explicit_attrib_location(gl_info))
10011 {
10012 /* Bind vertex attributes to a corresponding index number to match
10013 * the same index numbers as ARB_vertex_programs (makes loading
10014 * vertex attributes simpler). With this method, we can use the
10015 * exact same code to load the attributes later for both ARB and
10016 * GLSL shaders.
10017 *
10018 * We have to do this here because we need to know the Program ID
10019 * in order to make the bindings work, and it has to be done prior
10020 * to linking the GLSL program. */
10021 tmp_name = string_buffer_get(&priv->string_buffers);
10022 for (i = 0; attribs_map; attribs_map >>= 1, ++i)
10023 {
10024 if (!(attribs_map & 1))
10025 continue;
10026
10027 string_buffer_sprintf(tmp_name, "vs_in%u", i);
10028 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer));
10029 if (vshader && vshader->reg_maps.shader_version.major >= 4)
10030 {
10031 string_buffer_sprintf(tmp_name, "vs_in_uint%u", i);
10032 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer));
10033 string_buffer_sprintf(tmp_name, "vs_in_int%u", i);
10034 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer));
10035 }
10036 }
10037 checkGLcall("glBindAttribLocation");
10038 string_buffer_release(&priv->string_buffers, tmp_name);
10039
10040 if (!needs_legacy_glsl_syntax(gl_info))
10041 {
10042 char var[12];
10043
10044 if (wined3d_dualblend_enabled(state, gl_info))
10045 {
10046 for (i = 0; i < gl_info->limits.dual_buffers * 2; i++)
10047 {
10048 sprintf(var, "ps_out%u", i);
10049 GL_EXTCALL(glBindFragDataLocationIndexed(program_id, i / 2, i % 2, var));
10050 checkGLcall("glBindFragDataLocationIndexed");
10051 }
10052 }
10053 else
10054 {
10055 for (i = 0; i < gl_info->limits.buffers; i++)
10056 {
10057 sprintf(var, "ps_out%u", i);
10058 GL_EXTCALL(glBindFragDataLocation(program_id, i, var));
10059 checkGLcall("glBindFragDataLocation");
10060 }
10061 }
10062 }
10063 }
10064
10065 if (hshader)
10066 {
10067 TRACE("Attaching GLSL tessellation control shader object %u to program %u.\n", hs_id, program_id);
10068 GL_EXTCALL(glAttachShader(program_id, hs_id));
10069 checkGLcall("glAttachShader");
10070
10071 list_add_head(&hshader->linked_programs, &entry->hs.shader_entry);
10072 }
10073
10074 if (dshader)
10075 {
10076 TRACE("Attaching GLSL tessellation evaluation shader object %u to program %u.\n", ds_id, program_id);
10077 GL_EXTCALL(glAttachShader(program_id, ds_id));
10078 checkGLcall("glAttachShader");
10079
10080 list_add_head(&dshader->linked_programs, &entry->ds.shader_entry);
10081 }
10082
10083 if (gshader)
10084 {
10085 TRACE("Attaching GLSL geometry shader object %u to program %u.\n", gs_id, program_id);
10086 GL_EXTCALL(glAttachShader(program_id, gs_id));
10087 checkGLcall("glAttachShader");
10088
10089 shader_glsl_init_transform_feedback(context, priv, program_id, gshader);
10090
10091 list_add_head(&gshader->linked_programs, &entry->gs.shader_entry);
10092 }
10093
10094 /* Attach GLSL pshader */
10095 if (ps_id)
10096 {
10097 TRACE("Attaching GLSL shader object %u to program %u.\n", ps_id, program_id);
10098 GL_EXTCALL(glAttachShader(program_id, ps_id));
10099 checkGLcall("glAttachShader");
10100
10101 list_add_head(ps_list, &entry->ps.shader_entry);
10102 }
10103
10104 /* Link the program */
10105 TRACE("Linking GLSL shader program %u.\n", program_id);
10106 GL_EXTCALL(glLinkProgram(program_id));
10107 shader_glsl_validate_link(gl_info, program_id);
10108
10109 shader_glsl_init_vs_uniform_locations(gl_info, priv, program_id, &entry->vs,
10110 vshader ? vshader->limits->constant_float : 0);
10111 shader_glsl_init_ds_uniform_locations(gl_info, priv, program_id, &entry->ds);
10112 shader_glsl_init_gs_uniform_locations(gl_info, priv, program_id, &entry->gs);
10113 shader_glsl_init_ps_uniform_locations(gl_info, priv, program_id, &entry->ps,
10114 pshader ? pshader->limits->constant_float : 0);
10115 checkGLcall("find glsl program uniform locations");
10116
10117 pre_rasterization_shader = gshader ? gshader : dshader ? dshader : vshader;
10118 if (pre_rasterization_shader && pre_rasterization_shader->reg_maps.shader_version.major >= 4)
10119 {
10120 unsigned int clip_distance_count = wined3d_popcount(pre_rasterization_shader->reg_maps.clip_distance_mask);
10121 entry->shader_controlled_clip_distances = 1;
10122 entry->clip_distance_mask = (1u << clip_distance_count) - 1;
10123 }
10124
10125 if (needs_legacy_glsl_syntax(gl_info))
10126 {
10127 if (pshader && pshader->reg_maps.shader_version.major >= 3
10128 && pshader->u.ps.declared_in_count > vec4_varyings(3, gl_info))
10129 {
10130 TRACE("Shader %d needs vertex color clamping disabled.\n", program_id);
10131 entry->vs.vertex_color_clamp = GL_FALSE;
10132 }
10133 else
10134 {
10135 entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB;
10136 }
10137 }
10138 else
10139 {
10140 /* With core profile we never change vertex_color_clamp from
10141 * GL_FIXED_ONLY_MODE (which is also the initial value) so we never call
10142 * glClampColorARB(). */
10143 entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB;
10144 }
10145
10146 /* Set the shader to allow uniform loading on it */
10147 GL_EXTCALL(glUseProgram(program_id));
10148 checkGLcall("glUseProgram");
10149
10150 entry->constant_update_mask = 0;
10151 if (vshader)
10152 {
10153 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_F;
10154 if (vshader->reg_maps.integer_constants)
10155 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_I;
10156 if (vshader->reg_maps.boolean_constants)
10157 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_B;
10158 if (entry->vs.pos_fixup_location != -1)
10159 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
10160
10161 shader_glsl_load_program_resources(context, priv, program_id, vshader);
10162 }
10163 else
10164 {
10165 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW
10166 | WINED3D_SHADER_CONST_FFP_PROJ;
10167
10168 for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i)
10169 {
10170 if (entry->vs.modelview_matrix_location[i] != -1)
10171 {
10172 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND;
10173 break;
10174 }
10175 }
10176
10177 for (i = 0; i < MAX_TEXTURES; ++i)
10178 {
10179 if (entry->vs.texture_matrix_location[i] != -1)
10180 {
10181 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
10182 break;
10183 }
10184 }
10185 if (entry->vs.material_ambient_location != -1 || entry->vs.material_diffuse_location != -1
10186 || entry->vs.material_specular_location != -1
10187 || entry->vs.material_emissive_location != -1
10188 || entry->vs.material_shininess_location != -1)
10189 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MATERIAL;
10190 if (entry->vs.light_ambient_location != -1)
10191 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_LIGHTS;
10192 }
10193 if (entry->vs.clip_planes_location != -1)
10194 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES;
10195 if (entry->vs.pointsize_min_location != -1)
10196 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE;
10197
10198 if (hshader)
10199 shader_glsl_load_program_resources(context, priv, program_id, hshader);
10200
10201 if (dshader)
10202 {
10203 if (entry->ds.pos_fixup_location != -1)
10204 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
10205
10206 shader_glsl_load_program_resources(context, priv, program_id, dshader);
10207 }
10208
10209 if (gshader)
10210 {
10211 if (entry->gs.pos_fixup_location != -1)
10212 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
10213
10214 shader_glsl_load_program_resources(context, priv, program_id, gshader);
10215 }
10216
10217 if (ps_id)
10218 {
10219 if (pshader)
10220 {
10221 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_F;
10222 if (pshader->reg_maps.integer_constants)
10223 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_I;
10224 if (pshader->reg_maps.boolean_constants)
10225 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_B;
10226 if (entry->ps.ycorrection_location != -1)
10227 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_Y_CORR;
10228
10229 shader_glsl_load_program_resources(context, priv, program_id, pshader);
10230 shader_glsl_load_images(gl_info, priv, program_id, &pshader->reg_maps);
10231 }
10232 else
10233 {
10234 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS;
10235
10236 shader_glsl_load_samplers(context, priv, program_id, NULL);
10237 }
10238
10239 for (i = 0; i < MAX_TEXTURES; ++i)
10240 {
10241 if (entry->ps.bumpenv_mat_location[i] != -1)
10242 {
10243 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
10244 break;
10245 }
10246 }
10247
10248 if (entry->ps.fog_color_location != -1)
10249 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG;
10250 if (entry->ps.alpha_test_ref_location != -1)
10251 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST;
10252 if (entry->ps.np2_fixup_location != -1)
10253 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
10254 if (entry->ps.color_key_location != -1)
10255 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY;
10256 }
10257 }
10258
10259 static void shader_glsl_precompile(void *shader_priv, struct wined3d_shader *shader)
10260 {
10261 struct wined3d_device *device = shader->device;
10262 struct wined3d_context *context;
10263
10264 if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_COMPUTE)
10265 {
10266 context = context_acquire(device, NULL, 0);
10267 shader_glsl_compile_compute_shader(shader_priv, context, shader);
10268 context_release(context);
10269 }
10270 }
10271
10272 /* Context activation is done by the caller. */
10273 static void shader_glsl_select(void *shader_priv, struct wined3d_context *context,
10274 const struct wined3d_state *state)
10275 {
10276 struct glsl_context_data *ctx_data = context->shader_backend_data;
10277 const struct wined3d_gl_info *gl_info = context->gl_info;
10278 struct shader_glsl_priv *priv = shader_priv;
10279 struct glsl_shader_prog_link *glsl_program;
10280 GLenum current_vertex_color_clamp;
10281 GLuint program_id, prev_id;
10282
10283 priv->vertex_pipe->vp_enable(gl_info, !use_vs(state));
10284 priv->fragment_pipe->enable_extension(gl_info, !use_ps(state));
10285
10286 prev_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0;
10287 set_glsl_shader_program(context, state, priv, ctx_data);
10288 glsl_program = ctx_data->glsl_program;
10289
10290 if (glsl_program)
10291 {
10292 program_id = glsl_program->id;
10293 current_vertex_color_clamp = glsl_program->vs.vertex_color_clamp;
10294 if (glsl_program->shader_controlled_clip_distances)
10295 context_enable_clip_distances(context, glsl_program->clip_distance_mask);
10296 }
10297 else
10298 {
10299 program_id = 0;
10300 current_vertex_color_clamp = GL_FIXED_ONLY_ARB;
10301 }
10302
10303 if (ctx_data->vertex_color_clamp != current_vertex_color_clamp)
10304 {
10305 ctx_data->vertex_color_clamp = current_vertex_color_clamp;
10306 if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
10307 {
10308 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, current_vertex_color_clamp));
10309 checkGLcall("glClampColorARB");
10310 }
10311 else
10312 {
10313 FIXME("Vertex color clamp needs to be changed, but extension not supported.\n");
10314 }
10315 }
10316
10317 TRACE("Using GLSL program %u.\n", program_id);
10318
10319 if (prev_id != program_id)
10320 {
10321 GL_EXTCALL(glUseProgram(program_id));
10322 checkGLcall("glUseProgram");
10323
10324 if (glsl_program)
10325 context->constant_update_mask |= glsl_program->constant_update_mask;
10326 }
10327
10328 context->shader_update_mask |= (1u << WINED3D_SHADER_TYPE_COMPUTE);
10329 }
10330
10331 /* Context activation is done by the caller. */
10332 static void shader_glsl_select_compute(void *shader_priv, struct wined3d_context *context,
10333 const struct wined3d_state *state)
10334 {
10335 struct glsl_context_data *ctx_data = context->shader_backend_data;
10336 const struct wined3d_gl_info *gl_info = context->gl_info;
10337 struct shader_glsl_priv *priv = shader_priv;
10338 GLuint program_id, prev_id;
10339
10340 prev_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0;
10341 set_glsl_compute_shader_program(context, state, priv, ctx_data);
10342 program_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0;
10343
10344 TRACE("Using GLSL program %u.\n", program_id);
10345
10346 if (prev_id != program_id)
10347 {
10348 GL_EXTCALL(glUseProgram(program_id));
10349 checkGLcall("glUseProgram");
10350 }
10351
10352 context->shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL)
10353 | (1u << WINED3D_SHADER_TYPE_VERTEX)
10354 | (1u << WINED3D_SHADER_TYPE_GEOMETRY)
10355 | (1u << WINED3D_SHADER_TYPE_HULL)
10356 | (1u << WINED3D_SHADER_TYPE_DOMAIN);
10357 }
10358
10359 /* "context" is not necessarily the currently active context. */
10360 static void shader_glsl_invalidate_current_program(struct wined3d_context *context)
10361 {
10362 struct glsl_context_data *ctx_data = context->shader_backend_data;
10363
10364 ctx_data->glsl_program = NULL;
10365 context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
10366 | (1u << WINED3D_SHADER_TYPE_VERTEX)
10367 | (1u << WINED3D_SHADER_TYPE_GEOMETRY)
10368 | (1u << WINED3D_SHADER_TYPE_HULL)
10369 | (1u << WINED3D_SHADER_TYPE_DOMAIN)
10370 | (1u << WINED3D_SHADER_TYPE_COMPUTE);
10371 }
10372
10373 /* Context activation is done by the caller. */
10374 static void shader_glsl_disable(void *shader_priv, struct wined3d_context *context)
10375 {
10376 struct glsl_context_data *ctx_data = context->shader_backend_data;
10377 const struct wined3d_gl_info *gl_info = context->gl_info;
10378 struct shader_glsl_priv *priv = shader_priv;
10379
10380 shader_glsl_invalidate_current_program(context);
10381 GL_EXTCALL(glUseProgram(0));
10382 checkGLcall("glUseProgram");
10383
10384 priv->vertex_pipe->vp_enable(gl_info, FALSE);
10385 priv->fragment_pipe->enable_extension(gl_info, FALSE);
10386
10387 if (needs_legacy_glsl_syntax(gl_info) && gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
10388 {
10389 ctx_data->vertex_color_clamp = GL_FIXED_ONLY_ARB;
10390 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB));
10391 checkGLcall("glClampColorARB");
10392 }
10393 }
10394
10395 static void shader_glsl_invalidate_contexts_program(struct wined3d_device *device,
10396 const struct glsl_shader_prog_link *program)
10397 {
10398 const struct glsl_context_data *ctx_data;
10399 struct wined3d_context *context;
10400 unsigned int i;
10401
10402 for (i = 0; i < device->context_count; ++i)
10403 {
10404 context = device->contexts[i];
10405 ctx_data = context->shader_backend_data;
10406
10407 if (ctx_data->glsl_program == program)
10408 shader_glsl_invalidate_current_program(context);
10409 }
10410 }
10411
10412 static void shader_glsl_destroy(struct wined3d_shader *shader)
10413 {
10414 struct glsl_shader_private *shader_data = shader->backend_data;
10415 struct wined3d_device *device = shader->device;
10416 struct shader_glsl_priv *priv = device->shader_priv;
10417 const struct wined3d_gl_info *gl_info;
10418 const struct list *linked_programs;
10419 struct wined3d_context *context;
10420
10421 if (!shader_data || !shader_data->num_gl_shaders)
10422 {
10423 heap_free(shader_data);
10424 shader->backend_data = NULL;
10425 return;
10426 }
10427
10428 context = context_acquire(device, NULL, 0);
10429 gl_info = context->gl_info;
10430
10431 TRACE("Deleting linked programs.\n");
10432 linked_programs = &shader->linked_programs;
10433 if (linked_programs->next)
10434 {
10435 struct glsl_shader_prog_link *entry, *entry2;
10436 UINT i;
10437
10438 switch (shader->reg_maps.shader_version.type)
10439 {
10440 case WINED3D_SHADER_TYPE_PIXEL:
10441 {
10442 struct glsl_ps_compiled_shader *gl_shaders = shader_data->gl_shaders.ps;
10443
10444 for (i = 0; i < shader_data->num_gl_shaders; ++i)
10445 {
10446 TRACE("Deleting pixel shader %u.\n", gl_shaders[i].id);
10447 GL_EXTCALL(glDeleteShader(gl_shaders[i].id));
10448 checkGLcall("glDeleteShader");
10449 }
10450 heap_free(shader_data->gl_shaders.ps);
10451
10452 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
10453 struct glsl_shader_prog_link, ps.shader_entry)
10454 {
10455 shader_glsl_invalidate_contexts_program(device, entry);
10456 delete_glsl_program_entry(priv, gl_info, entry);
10457 }
10458
10459 break;
10460 }
10461
10462 case WINED3D_SHADER_TYPE_VERTEX:
10463 {
10464 struct glsl_vs_compiled_shader *gl_shaders = shader_data->gl_shaders.vs;
10465
10466 for (i = 0; i < shader_data->num_gl_shaders; ++i)
10467 {
10468 TRACE("Deleting vertex shader %u.\n", gl_shaders[i].id);
10469 GL_EXTCALL(glDeleteShader(gl_shaders[i].id));
10470 checkGLcall("glDeleteShader");
10471 }
10472 heap_free(shader_data->gl_shaders.vs);
10473
10474 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
10475 struct glsl_shader_prog_link, vs.shader_entry)
10476 {
10477 shader_glsl_invalidate_contexts_program(device, entry);
10478 delete_glsl_program_entry(priv, gl_info, entry);
10479 }
10480
10481 break;
10482 }
10483
10484 case WINED3D_SHADER_TYPE_HULL:
10485 {
10486 struct glsl_hs_compiled_shader *gl_shaders = shader_data->gl_shaders.hs;
10487
10488 for (i = 0; i < shader_data->num_gl_shaders; ++i)
10489 {
10490 TRACE("Deleting hull shader %u.\n", gl_shaders[i].id);
10491 GL_EXTCALL(glDeleteShader(gl_shaders[i].id));
10492 checkGLcall("glDeleteShader");
10493 }
10494 heap_free(shader_data->gl_shaders.hs);
10495
10496 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
10497 struct glsl_shader_prog_link, hs.shader_entry)
10498 {
10499 shader_glsl_invalidate_contexts_program(device, entry);
10500 delete_glsl_program_entry(priv, gl_info, entry);
10501 }
10502
10503 break;
10504 }
10505
10506 case WINED3D_SHADER_TYPE_DOMAIN:
10507 {
10508 struct glsl_ds_compiled_shader *gl_shaders = shader_data->gl_shaders.ds;
10509
10510 for (i = 0; i < shader_data->num_gl_shaders; ++i)
10511 {
10512 TRACE("Deleting domain shader %u.\n", gl_shaders[i].id);
10513 GL_EXTCALL(glDeleteShader(gl_shaders[i].id));
10514 checkGLcall("glDeleteShader");
10515 }
10516 heap_free(shader_data->gl_shaders.ds);
10517
10518 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
10519 struct glsl_shader_prog_link, ds.shader_entry)
10520 {
10521 shader_glsl_invalidate_contexts_program(device, entry);
10522 delete_glsl_program_entry(priv, gl_info, entry);
10523 }
10524
10525 break;
10526 }
10527
10528 case WINED3D_SHADER_TYPE_GEOMETRY:
10529 {
10530 struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs;
10531
10532 for (i = 0; i < shader_data->num_gl_shaders; ++i)
10533 {
10534 TRACE("Deleting geometry shader %u.\n", gl_shaders[i].id);
10535 GL_EXTCALL(glDeleteShader(gl_shaders[i].id));
10536 checkGLcall("glDeleteShader");
10537 }
10538 heap_free(shader_data->gl_shaders.gs);
10539
10540 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
10541 struct glsl_shader_prog_link, gs.shader_entry)
10542 {
10543 shader_glsl_invalidate_contexts_program(device, entry);
10544 delete_glsl_program_entry(priv, gl_info, entry);
10545 }
10546
10547 break;
10548 }
10549
10550 case WINED3D_SHADER_TYPE_COMPUTE:
10551 {
10552 struct glsl_cs_compiled_shader *gl_shaders = shader_data->gl_shaders.cs;
10553
10554 for (i = 0; i < shader_data->num_gl_shaders; ++i)
10555 {
10556 TRACE("Deleting compute shader %u.\n", gl_shaders[i].id);
10557 GL_EXTCALL(glDeleteShader(gl_shaders[i].id));
10558 checkGLcall("glDeleteShader");
10559 }
10560 heap_free(shader_data->gl_shaders.cs);
10561
10562 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
10563 struct glsl_shader_prog_link, cs.shader_entry)
10564 {
10565 shader_glsl_invalidate_contexts_program(device, entry);
10566 delete_glsl_program_entry(priv, gl_info, entry);
10567 }
10568
10569 break;
10570 }
10571
10572 default:
10573 ERR("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type);
10574 break;
10575 }
10576 }
10577
10578 heap_free(shader->backend_data);
10579 shader->backend_data = NULL;
10580
10581 context_release(context);
10582 }
10583
10584 static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry)
10585 {
10586 const struct glsl_program_key *k = key;
10587 const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry,
10588 const struct glsl_shader_prog_link, program_lookup_entry);
10589
10590 if (k->vs_id > prog->vs.id) return 1;
10591 else if (k->vs_id < prog->vs.id) return -1;
10592
10593 if (k->gs_id > prog->gs.id) return 1;
10594 else if (k->gs_id < prog->gs.id) return -1;
10595
10596 if (k->ps_id > prog->ps.id) return 1;
10597 else if (k->ps_id < prog->ps.id) return -1;
10598
10599 if (k->hs_id > prog->hs.id) return 1;
10600 else if (k->hs_id < prog->hs.id) return -1;
10601
10602 if (k->ds_id > prog->ds.id) return 1;
10603 else if (k->ds_id < prog->ds.id) return -1;
10604
10605 if (k->cs_id > prog->cs.id) return 1;
10606 else if (k->cs_id < prog->cs.id) return -1;
10607
10608 return 0;
10609 }
10610
10611 static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count)
10612 {
10613 SIZE_T size = (constant_count + 1) * sizeof(*heap->entries)
10614 + constant_count * sizeof(*heap->contained)
10615 + constant_count * sizeof(*heap->positions);
10616 void *mem;
10617
10618 if (!(mem = heap_alloc(size)))
10619 {
10620 ERR("Failed to allocate memory\n");
10621 return FALSE;
10622 }
10623
10624 heap->entries = mem;
10625 heap->entries[1].version = 0;
10626 heap->contained = (BOOL *)(heap->entries + constant_count + 1);
10627 memset(heap->contained, 0, constant_count * sizeof(*heap->contained));
10628 heap->positions = (unsigned int *)(heap->contained + constant_count);
10629 heap->size = 1;
10630
10631 return TRUE;
10632 }
10633
10634 static void constant_heap_free(struct constant_heap *heap)
10635 {
10636 heap_free(heap->entries);
10637 }
10638
10639 static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
10640 const struct fragment_pipeline *fragment_pipe)
10641 {
10642 SIZE_T stack_size = wined3d_log2i(max(WINED3D_MAX_VS_CONSTS_F, WINED3D_MAX_PS_CONSTS_F)) + 1;
10643 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
10644 struct fragment_caps fragment_caps;
10645 void *vertex_priv, *fragment_priv;
10646 struct shader_glsl_priv *priv;
10647
10648 if (!(priv = heap_alloc_zero(sizeof(*priv))))
10649 return E_OUTOFMEMORY;
10650
10651 string_buffer_list_init(&priv->string_buffers);
10652
10653 if (!(vertex_priv = vertex_pipe->vp_alloc(&glsl_shader_backend, priv)))
10654 {
10655 ERR("Failed to initialize vertex pipe.\n");
10656 heap_free(priv);
10657 return E_FAIL;
10658 }
10659
10660 if (!(fragment_priv = fragment_pipe->alloc_private(&glsl_shader_backend, priv)))
10661 {
10662 ERR("Failed to initialize fragment pipe.\n");
10663 vertex_pipe->vp_free(device);
10664 heap_free(priv);
10665 return E_FAIL;
10666 }
10667
10668 if (!string_buffer_init(&priv->shader_buffer))
10669 {
10670 ERR("Failed to initialize shader buffer.\n");
10671 goto fail;
10672 }
10673
10674 if (!(priv->stack = heap_calloc(stack_size, sizeof(*priv->stack))))
10675 {
10676 ERR("Failed to allocate memory.\n");
10677 goto fail;
10678 }
10679
10680 if (!constant_heap_init(&priv->vconst_heap, WINED3D_MAX_VS_CONSTS_F))
10681 {
10682 ERR("Failed to initialize vertex shader constant heap\n");
10683 goto fail;
10684 }
10685
10686 if (!constant_heap_init(&priv->pconst_heap, WINED3D_MAX_PS_CONSTS_F))
10687 {
10688 ERR("Failed to initialize pixel shader constant heap\n");
10689 goto fail;
10690 }
10691
10692 wine_rb_init(&priv->program_lookup, glsl_program_key_compare);
10693
10694 priv->next_constant_version = 1;
10695 priv->vertex_pipe = vertex_pipe;
10696 priv->fragment_pipe = fragment_pipe;
10697 fragment_pipe->get_caps(gl_info, &fragment_caps);
10698 priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
10699 priv->legacy_lighting = device->wined3d->flags & WINED3D_LEGACY_FFP_LIGHTING;
10700
10701 device->vertex_priv = vertex_priv;
10702 device->fragment_priv = fragment_priv;
10703 device->shader_priv = priv;
10704
10705 return WINED3D_OK;
10706
10707 fail:
10708 constant_heap_free(&priv->pconst_heap);
10709 constant_heap_free(&priv->vconst_heap);
10710 heap_free(priv->stack);
10711 string_buffer_free(&priv->shader_buffer);
10712 fragment_pipe->free_private(device);
10713 vertex_pipe->vp_free(device);
10714 heap_free(priv);
10715 return E_OUTOFMEMORY;
10716 }
10717
10718 /* Context activation is done by the caller. */
10719 static void shader_glsl_free(struct wined3d_device *device)
10720 {
10721 struct shader_glsl_priv *priv = device->shader_priv;
10722
10723 wine_rb_destroy(&priv->program_lookup, NULL, NULL);
10724 constant_heap_free(&priv->pconst_heap);
10725 constant_heap_free(&priv->vconst_heap);
10726 heap_free(priv->stack);
10727 string_buffer_list_cleanup(&priv->string_buffers);
10728 string_buffer_free(&priv->shader_buffer);
10729 priv->fragment_pipe->free_private(device);
10730 priv->vertex_pipe->vp_free(device);
10731
10732 heap_free(device->shader_priv);
10733 device->shader_priv = NULL;
10734 }
10735
10736 static BOOL shader_glsl_allocate_context_data(struct wined3d_context *context)
10737 {
10738 struct glsl_context_data *ctx_data;
10739
10740 if (!(ctx_data = heap_alloc_zero(sizeof(*ctx_data))))
10741 return FALSE;
10742 ctx_data->vertex_color_clamp = GL_FIXED_ONLY_ARB;
10743 context->shader_backend_data = ctx_data;
10744 return TRUE;
10745 }
10746
10747 static void shader_glsl_free_context_data(struct wined3d_context *context)
10748 {
10749 heap_free(context->shader_backend_data);
10750 }
10751
10752 static void shader_glsl_init_context_state(struct wined3d_context *context)
10753 {
10754 const struct wined3d_gl_info *gl_info = context->gl_info;
10755
10756 gl_info->gl_ops.gl.p_glEnable(GL_PROGRAM_POINT_SIZE);
10757 checkGLcall("GL_PROGRAM_POINT_SIZE");
10758 }
10759
10760 static unsigned int shader_glsl_get_shader_model(const struct wined3d_gl_info *gl_info)
10761 {
10762 BOOL shader_model_4 = gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)
10763 && gl_info->supported[WINED3D_GL_VERSION_3_2]
10764 && gl_info->supported[ARB_SAMPLER_OBJECTS]
10765 && gl_info->supported[ARB_SHADER_BIT_ENCODING]
10766 && gl_info->supported[ARB_TEXTURE_SWIZZLE];
10767
10768 if (shader_model_4
10769 && gl_info->supported[ARB_COMPUTE_SHADER]
10770 && gl_info->supported[ARB_CULL_DISTANCE]
10771 && gl_info->supported[ARB_DERIVATIVE_CONTROL]
10772 && gl_info->supported[ARB_DRAW_INDIRECT]
10773 && gl_info->supported[ARB_GPU_SHADER5]
10774 && gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS]
10775 && gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE]
10776 && gl_info->supported[ARB_SHADER_IMAGE_SIZE]
10777 && gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]
10778 && gl_info->supported[ARB_TESSELLATION_SHADER]
10779 && gl_info->supported[ARB_TEXTURE_GATHER]
10780 && gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
10781 return 5;
10782
10783 if (shader_model_4)
10784 return 4;
10785
10786 /* Support for texldd and texldl instructions in pixel shaders is required
10787 * for SM3. */
10788 if (shader_glsl_has_core_grad(gl_info) || gl_info->supported[ARB_SHADER_TEXTURE_LOD])
10789 return 3;
10790
10791 return 2;
10792 }
10793
10794 static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
10795 {
10796 unsigned int shader_model = shader_glsl_get_shader_model(gl_info);
10797
10798 TRACE("Shader model %u.\n", shader_model);
10799
10800 caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model);
10801 caps->hs_version = min(wined3d_settings.max_sm_hs, shader_model);
10802 caps->ds_version = min(wined3d_settings.max_sm_ds, shader_model);
10803 caps->gs_version = min(wined3d_settings.max_sm_gs, shader_model);
10804 caps->ps_version = min(wined3d_settings.max_sm_ps, shader_model);
10805 caps->cs_version = min(wined3d_settings.max_sm_cs, shader_model);
10806
10807 caps->vs_version = gl_info->supported[ARB_VERTEX_SHADER] ? caps->vs_version : 0;
10808 caps->ps_version = gl_info->supported[ARB_FRAGMENT_SHADER] ? caps->ps_version : 0;
10809
10810 caps->vs_uniform_count = min(WINED3D_MAX_VS_CONSTS_F, gl_info->limits.glsl_vs_float_constants);
10811 caps->ps_uniform_count = min(WINED3D_MAX_PS_CONSTS_F, gl_info->limits.glsl_ps_float_constants);
10812 caps->varying_count = gl_info->limits.glsl_varyings;
10813
10814 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
10815 * Direct3D minimum requirement.
10816 *
10817 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
10818 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
10819 *
10820 * The problem is that the refrast clamps temporary results in the shader to
10821 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
10822 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
10823 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
10824 * offer a way to query this.
10825 */
10826 if (shader_model >= 4)
10827 caps->ps_1x_max_value = FLT_MAX;
10828 else
10829 caps->ps_1x_max_value = 1024.0f;
10830
10831 /* Ideally we'd only set caps like sRGB writes here if supported by both
10832 * the shader backend and the fragment pipe, but we can get called before
10833 * shader_glsl_alloc(). */
10834 caps->wined3d_caps = WINED3D_SHADER_CAP_VS_CLIPPING
10835 | WINED3D_SHADER_CAP_SRGB_WRITE;
10836 }
10837
10838 static BOOL shader_glsl_color_fixup_supported(struct color_fixup_desc fixup)
10839 {
10840 /* We support everything except YUV conversions. */
10841 return !is_complex_fixup(fixup);
10842 }
10843
10844 static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TABLE_SIZE] =
10845 {
10846 /* WINED3DSIH_ABS */ shader_glsl_map2gl,
10847 /* WINED3DSIH_ADD */ shader_glsl_binop,
10848 /* WINED3DSIH_AND */ shader_glsl_binop,
10849 /* WINED3DSIH_ATOMIC_AND */ shader_glsl_atomic,
10850 /* WINED3DSIH_ATOMIC_CMP_STORE */ shader_glsl_atomic,
10851 /* WINED3DSIH_ATOMIC_IADD */ shader_glsl_atomic,
10852 /* WINED3DSIH_ATOMIC_IMAX */ shader_glsl_atomic,
10853 /* WINED3DSIH_ATOMIC_IMIN */ shader_glsl_atomic,
10854 /* WINED3DSIH_ATOMIC_OR */ shader_glsl_atomic,
10855 /* WINED3DSIH_ATOMIC_UMAX */ shader_glsl_atomic,
10856 /* WINED3DSIH_ATOMIC_UMIN */ shader_glsl_atomic,
10857 /* WINED3DSIH_ATOMIC_XOR */ shader_glsl_atomic,
10858 /* WINED3DSIH_BEM */ shader_glsl_bem,
10859 /* WINED3DSIH_BFI */ shader_glsl_bitwise_op,
10860 /* WINED3DSIH_BFREV */ shader_glsl_map2gl,
10861 /* WINED3DSIH_BREAK */ shader_glsl_break,
10862 /* WINED3DSIH_BREAKC */ shader_glsl_breakc,
10863 /* WINED3DSIH_BREAKP */ shader_glsl_conditional_op,
10864 /* WINED3DSIH_BUFINFO */ shader_glsl_bufinfo,
10865 /* WINED3DSIH_CALL */ shader_glsl_call,
10866 /* WINED3DSIH_CALLNZ */ shader_glsl_callnz,
10867 /* WINED3DSIH_CASE */ shader_glsl_case,
10868 /* WINED3DSIH_CMP */ shader_glsl_conditional_move,
10869 /* WINED3DSIH_CND */ shader_glsl_cnd,
10870 /* WINED3DSIH_CONTINUE */ shader_glsl_continue,
10871 /* WINED3DSIH_CONTINUEP */ shader_glsl_conditional_op,
10872 /* WINED3DSIH_COUNTBITS */ shader_glsl_map2gl,
10873 /* WINED3DSIH_CRS */ shader_glsl_cross,
10874 /* WINED3DSIH_CUT */ shader_glsl_cut,
10875 /* WINED3DSIH_CUT_STREAM */ shader_glsl_cut,
10876 /* WINED3DSIH_DCL */ shader_glsl_nop,
10877 /* WINED3DSIH_DCL_CONSTANT_BUFFER */ shader_glsl_nop,
10878 /* WINED3DSIH_DCL_FUNCTION_BODY */ NULL,
10879 /* WINED3DSIH_DCL_FUNCTION_TABLE */ NULL,
10880 /* WINED3DSIH_DCL_GLOBAL_FLAGS */ shader_glsl_nop,
10881 /* WINED3DSIH_DCL_GS_INSTANCES */ shader_glsl_nop,
10882 /* WINED3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT */ shader_glsl_nop,
10883 /* WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ shader_glsl_nop,
10884 /* WINED3DSIH_DCL_HS_MAX_TESSFACTOR */ shader_glsl_nop,
10885 /* WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ shader_glsl_nop,
10886 /* WINED3DSIH_DCL_INDEX_RANGE */ shader_glsl_nop,
10887 /* WINED3DSIH_DCL_INDEXABLE_TEMP */ shader_glsl_nop,
10888 /* WINED3DSIH_DCL_INPUT */ shader_glsl_nop,
10889 /* WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ shader_glsl_nop,
10890 /* WINED3DSIH_DCL_INPUT_PRIMITIVE */ shader_glsl_nop,
10891 /* WINED3DSIH_DCL_INPUT_PS */ shader_glsl_nop,
10892 /* WINED3DSIH_DCL_INPUT_PS_SGV */ NULL,
10893 /* WINED3DSIH_DCL_INPUT_PS_SIV */ NULL,
10894 /* WINED3DSIH_DCL_INPUT_SGV */ shader_glsl_nop,
10895 /* WINED3DSIH_DCL_INPUT_SIV */ shader_glsl_nop,
10896 /* WINED3DSIH_DCL_INTERFACE */ NULL,
10897 /* WINED3DSIH_DCL_OUTPUT */ shader_glsl_nop,
10898 /* WINED3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT */ shader_glsl_nop,
10899 /* WINED3DSIH_DCL_OUTPUT_SIV */ shader_glsl_nop,
10900 /* WINED3DSIH_DCL_OUTPUT_TOPOLOGY */ shader_glsl_nop,
10901 /* WINED3DSIH_DCL_RESOURCE_RAW */ shader_glsl_nop,
10902 /* WINED3DSIH_DCL_RESOURCE_STRUCTURED */ shader_glsl_nop,
10903 /* WINED3DSIH_DCL_SAMPLER */ shader_glsl_nop,
10904 /* WINED3DSIH_DCL_STREAM */ NULL,
10905 /* WINED3DSIH_DCL_TEMPS */ shader_glsl_nop,
10906 /* WINED3DSIH_DCL_TESSELLATOR_DOMAIN */ shader_glsl_nop,
10907 /* WINED3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ shader_glsl_nop,
10908 /* WINED3DSIH_DCL_TESSELLATOR_PARTITIONING */ shader_glsl_nop,
10909 /* WINED3DSIH_DCL_TGSM_RAW */ shader_glsl_nop,
10910 /* WINED3DSIH_DCL_TGSM_STRUCTURED */ shader_glsl_nop,
10911 /* WINED3DSIH_DCL_THREAD_GROUP */ shader_glsl_nop,
10912 /* WINED3DSIH_DCL_UAV_RAW */ shader_glsl_nop,
10913 /* WINED3DSIH_DCL_UAV_STRUCTURED */ shader_glsl_nop,
10914 /* WINED3DSIH_DCL_UAV_TYPED */ shader_glsl_nop,
10915 /* WINED3DSIH_DCL_VERTICES_OUT */ shader_glsl_nop,
10916 /* WINED3DSIH_DEF */ shader_glsl_nop,
10917 /* WINED3DSIH_DEFAULT */ shader_glsl_default,
10918 /* WINED3DSIH_DEFB */ shader_glsl_nop,
10919 /* WINED3DSIH_DEFI */ shader_glsl_nop,
10920 /* WINED3DSIH_DIV */ shader_glsl_binop,
10921 /* WINED3DSIH_DP2 */ shader_glsl_dot,
10922 /* WINED3DSIH_DP2ADD */ shader_glsl_dp2add,
10923 /* WINED3DSIH_DP3 */ shader_glsl_dot,
10924 /* WINED3DSIH_DP4 */ shader_glsl_dot,
10925 /* WINED3DSIH_DST */ shader_glsl_dst,
10926 /* WINED3DSIH_DSX */ shader_glsl_map2gl,
10927 /* WINED3DSIH_DSX_COARSE */ shader_glsl_map2gl,
10928 /* WINED3DSIH_DSX_FINE */ shader_glsl_map2gl,
10929 /* WINED3DSIH_DSY */ shader_glsl_map2gl,
10930 /* WINED3DSIH_DSY_COARSE */ shader_glsl_map2gl,
10931 /* WINED3DSIH_DSY_FINE */ shader_glsl_map2gl,
10932 /* WINED3DSIH_EVAL_SAMPLE_INDEX */ NULL,
10933 /* WINED3DSIH_ELSE */ shader_glsl_else,
10934 /* WINED3DSIH_EMIT */ shader_glsl_emit,
10935 /* WINED3DSIH_EMIT_STREAM */ shader_glsl_emit,
10936 /* WINED3DSIH_ENDIF */ shader_glsl_end,
10937 /* WINED3DSIH_ENDLOOP */ shader_glsl_end,
10938 /* WINED3DSIH_ENDREP */ shader_glsl_end,
10939 /* WINED3DSIH_ENDSWITCH */ shader_glsl_end,
10940 /* WINED3DSIH_EQ */ shader_glsl_relop,
10941 /* WINED3DSIH_EXP */ shader_glsl_scalar_op,
10942 /* WINED3DSIH_EXPP */ shader_glsl_expp,
10943 /* WINED3DSIH_F16TOF32 */ shader_glsl_float16,
10944 /* WINED3DSIH_F32TOF16 */ shader_glsl_float16,
10945 /* WINED3DSIH_FCALL */ NULL,
10946 /* WINED3DSIH_FIRSTBIT_HI */ shader_glsl_map2gl,
10947 /* WINED3DSIH_FIRSTBIT_LO */ shader_glsl_map2gl,
10948 /* WINED3DSIH_FIRSTBIT_SHI */ shader_glsl_map2gl,
10949 /* WINED3DSIH_FRC */ shader_glsl_map2gl,
10950 /* WINED3DSIH_FTOI */ shader_glsl_to_int,
10951 /* WINED3DSIH_FTOU */ shader_glsl_to_uint,
10952 /* WINED3DSIH_GATHER4 */ shader_glsl_gather4,
10953 /* WINED3DSIH_GATHER4_C */ shader_glsl_gather4,
10954 /* WINED3DSIH_GATHER4_PO */ shader_glsl_gather4,
10955 /* WINED3DSIH_GATHER4_PO_C */ shader_glsl_gather4,
10956 /* WINED3DSIH_GE */ shader_glsl_relop,
10957 /* WINED3DSIH_HS_CONTROL_POINT_PHASE */ shader_glsl_nop,
10958 /* WINED3DSIH_HS_DECLS */ shader_glsl_nop,
10959 /* WINED3DSIH_HS_FORK_PHASE */ shader_glsl_nop,
10960 /* WINED3DSIH_HS_JOIN_PHASE */ shader_glsl_nop,
10961 /* WINED3DSIH_IADD */ shader_glsl_binop,
10962 /* WINED3DSIH_IBFE */ shader_glsl_bitwise_op,
10963 /* WINED3DSIH_IEQ */ shader_glsl_relop,
10964 /* WINED3DSIH_IF */ shader_glsl_if,
10965 /* WINED3DSIH_IFC */ shader_glsl_ifc,
10966 /* WINED3DSIH_IGE */ shader_glsl_relop,
10967 /* WINED3DSIH_ILT */ shader_glsl_relop,
10968 /* WINED3DSIH_IMAD */ shader_glsl_mad,
10969 /* WINED3DSIH_IMAX */ shader_glsl_map2gl,
10970 /* WINED3DSIH_IMIN */ shader_glsl_map2gl,
10971 /* WINED3DSIH_IMM_ATOMIC_ALLOC */ shader_glsl_uav_counter,
10972 /* WINED3DSIH_IMM_ATOMIC_AND */ shader_glsl_atomic,
10973 /* WINED3DSIH_IMM_ATOMIC_CMP_EXCH */ shader_glsl_atomic,
10974 /* WINED3DSIH_IMM_ATOMIC_CONSUME */ shader_glsl_uav_counter,
10975 /* WINED3DSIH_IMM_ATOMIC_EXCH */ shader_glsl_atomic,
10976 /* WINED3DSIH_IMM_ATOMIC_IADD */ shader_glsl_atomic,
10977 /* WINED3DSIH_IMM_ATOMIC_IMAX */ shader_glsl_atomic,
10978 /* WINED3DSIH_IMM_ATOMIC_IMIN */ shader_glsl_atomic,
10979 /* WINED3DSIH_IMM_ATOMIC_OR */ shader_glsl_atomic,
10980 /* WINED3DSIH_IMM_ATOMIC_UMAX */ shader_glsl_atomic,
10981 /* WINED3DSIH_IMM_ATOMIC_UMIN */ shader_glsl_atomic,
10982 /* WINED3DSIH_IMM_ATOMIC_XOR */ shader_glsl_atomic,
10983 /* WINED3DSIH_IMUL */ shader_glsl_mul_extended,
10984 /* WINED3DSIH_INE */ shader_glsl_relop,
10985 /* WINED3DSIH_INEG */ shader_glsl_unary_op,
10986 /* WINED3DSIH_ISHL */ shader_glsl_binop,
10987 /* WINED3DSIH_ISHR */ shader_glsl_binop,
10988 /* WINED3DSIH_ITOF */ shader_glsl_to_float,
10989 /* WINED3DSIH_LABEL */ shader_glsl_label,
10990 /* WINED3DSIH_LD */ shader_glsl_ld,
10991 /* WINED3DSIH_LD2DMS */ shader_glsl_ld,
10992 /* WINED3DSIH_LD_RAW */ shader_glsl_ld_raw_structured,
10993 /* WINED3DSIH_LD_STRUCTURED */ shader_glsl_ld_raw_structured,
10994 /* WINED3DSIH_LD_UAV_TYPED */ shader_glsl_ld_uav,
10995 /* WINED3DSIH_LIT */ shader_glsl_lit,
10996 /* WINED3DSIH_LOD */ NULL,
10997 /* WINED3DSIH_LOG */ shader_glsl_scalar_op,
10998 /* WINED3DSIH_LOGP */ shader_glsl_scalar_op,
10999 /* WINED3DSIH_LOOP */ shader_glsl_loop,
11000 /* WINED3DSIH_LRP */ shader_glsl_lrp,
11001 /* WINED3DSIH_LT */ shader_glsl_relop,
11002 /* WINED3DSIH_M3x2 */ shader_glsl_mnxn,
11003 /* WINED3DSIH_M3x3 */ shader_glsl_mnxn,
11004 /* WINED3DSIH_M3x4 */ shader_glsl_mnxn,
11005 /* WINED3DSIH_M4x3 */ shader_glsl_mnxn,
11006 /* WINED3DSIH_M4x4 */ shader_glsl_mnxn,
11007 /* WINED3DSIH_MAD */ shader_glsl_mad,
11008 /* WINED3DSIH_MAX */ shader_glsl_map2gl,
11009 /* WINED3DSIH_MIN */ shader_glsl_map2gl,
11010 /* WINED3DSIH_MOV */ shader_glsl_mov,
11011 /* WINED3DSIH_MOVA */ shader_glsl_mov,
11012 /* WINED3DSIH_MOVC */ shader_glsl_conditional_move,
11013 /* WINED3DSIH_MUL */ shader_glsl_binop,
11014 /* WINED3DSIH_NE */ shader_glsl_relop,
11015 /* WINED3DSIH_NOP */ shader_glsl_nop,
11016 /* WINED3DSIH_NOT */ shader_glsl_unary_op,
11017 /* WINED3DSIH_NRM */ shader_glsl_nrm,
11018 /* WINED3DSIH_OR */ shader_glsl_binop,
11019 /* WINED3DSIH_PHASE */ shader_glsl_nop,
11020 /* WINED3DSIH_POW */ shader_glsl_pow,
11021 /* WINED3DSIH_RCP */ shader_glsl_scalar_op,
11022 /* WINED3DSIH_REP */ shader_glsl_rep,
11023 /* WINED3DSIH_RESINFO */ shader_glsl_resinfo,
11024 /* WINED3DSIH_RET */ shader_glsl_ret,
11025 /* WINED3DSIH_RETP */ shader_glsl_conditional_op,
11026 /* WINED3DSIH_ROUND_NE */ shader_glsl_map2gl,
11027 /* WINED3DSIH_ROUND_NI */ shader_glsl_map2gl,
11028 /* WINED3DSIH_ROUND_PI */ shader_glsl_map2gl,
11029 /* WINED3DSIH_ROUND_Z */ shader_glsl_map2gl,
11030 /* WINED3DSIH_RSQ */ shader_glsl_scalar_op,
11031 /* WINED3DSIH_SAMPLE */ shader_glsl_sample,
11032 /* WINED3DSIH_SAMPLE_B */ shader_glsl_sample,
11033 /* WINED3DSIH_SAMPLE_C */ shader_glsl_sample_c,
11034 /* WINED3DSIH_SAMPLE_C_LZ */ shader_glsl_sample_c,
11035 /* WINED3DSIH_SAMPLE_GRAD */ shader_glsl_sample,
11036 /* WINED3DSIH_SAMPLE_INFO */ NULL,
11037 /* WINED3DSIH_SAMPLE_LOD */ shader_glsl_sample,
11038 /* WINED3DSIH_SAMPLE_POS */ NULL,
11039 /* WINED3DSIH_SETP */ NULL,
11040 /* WINED3DSIH_SGE */ shader_glsl_compare,
11041 /* WINED3DSIH_SGN */ shader_glsl_sgn,
11042 /* WINED3DSIH_SINCOS */ shader_glsl_sincos,
11043 /* WINED3DSIH_SLT */ shader_glsl_compare,
11044 /* WINED3DSIH_SQRT */ shader_glsl_map2gl,
11045 /* WINED3DSIH_STORE_RAW */ shader_glsl_store_raw_structured,
11046 /* WINED3DSIH_STORE_STRUCTURED */ shader_glsl_store_raw_structured,
11047 /* WINED3DSIH_STORE_UAV_TYPED */ shader_glsl_store_uav,
11048 /* WINED3DSIH_SUB */ shader_glsl_binop,
11049 /* WINED3DSIH_SWAPC */ shader_glsl_swapc,
11050 /* WINED3DSIH_SWITCH */ shader_glsl_switch,
11051 /* WINED3DSIH_SYNC */ shader_glsl_sync,
11052 /* WINED3DSIH_TEX */ shader_glsl_tex,
11053 /* WINED3DSIH_TEXBEM */ shader_glsl_texbem,
11054 /* WINED3DSIH_TEXBEML */ shader_glsl_texbem,
11055 /* WINED3DSIH_TEXCOORD */ shader_glsl_texcoord,
11056 /* WINED3DSIH_TEXDEPTH */ shader_glsl_texdepth,
11057 /* WINED3DSIH_TEXDP3 */ shader_glsl_texdp3,
11058 /* WINED3DSIH_TEXDP3TEX */ shader_glsl_texdp3tex,
11059 /* WINED3DSIH_TEXKILL */ shader_glsl_texkill,
11060 /* WINED3DSIH_TEXLDD */ shader_glsl_texldd,
11061 /* WINED3DSIH_TEXLDL */ shader_glsl_texldl,
11062 /* WINED3DSIH_TEXM3x2DEPTH */ shader_glsl_texm3x2depth,
11063 /* WINED3DSIH_TEXM3x2PAD */ shader_glsl_texm3x2pad,
11064 /* WINED3DSIH_TEXM3x2TEX */ shader_glsl_texm3x2tex,
11065 /* WINED3DSIH_TEXM3x3 */ shader_glsl_texm3x3,
11066 /* WINED3DSIH_TEXM3x3DIFF */ NULL,
11067 /* WINED3DSIH_TEXM3x3PAD */ shader_glsl_texm3x3pad,
11068 /* WINED3DSIH_TEXM3x3SPEC */ shader_glsl_texm3x3spec,
11069 /* WINED3DSIH_TEXM3x3TEX */ shader_glsl_texm3x3tex,
11070 /* WINED3DSIH_TEXM3x3VSPEC */ shader_glsl_texm3x3vspec,
11071 /* WINED3DSIH_TEXREG2AR */ shader_glsl_texreg2ar,
11072 /* WINED3DSIH_TEXREG2GB */ shader_glsl_texreg2gb,
11073 /* WINED3DSIH_TEXREG2RGB */ shader_glsl_texreg2rgb,
11074 /* WINED3DSIH_UBFE */ shader_glsl_bitwise_op,
11075 /* WINED3DSIH_UDIV */ shader_glsl_udiv,
11076 /* WINED3DSIH_UGE */ shader_glsl_relop,
11077 /* WINED3DSIH_ULT */ shader_glsl_relop,
11078 /* WINED3DSIH_UMAX */ shader_glsl_map2gl,
11079 /* WINED3DSIH_UMIN */ shader_glsl_map2gl,
11080 /* WINED3DSIH_UMUL */ shader_glsl_mul_extended,
11081 /* WINED3DSIH_USHR */ shader_glsl_binop,
11082 /* WINED3DSIH_UTOF */ shader_glsl_to_float,
11083 /* WINED3DSIH_XOR */ shader_glsl_binop,
11084 };
11085
11086 static void shader_glsl_handle_instruction(const struct wined3d_shader_instruction *ins) {
11087 SHADER_HANDLER hw_fct;
11088
11089 /* Select handler */
11090 hw_fct = shader_glsl_instruction_handler_table[ins->handler_idx];
11091
11092 /* Unhandled opcode */
11093 if (!hw_fct)
11094 {
11095 FIXME("Backend can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
11096 return;
11097 }
11098 hw_fct(ins);
11099
11100 shader_glsl_add_instruction_modifiers(ins);
11101 }
11102
11103 static BOOL shader_glsl_has_ffp_proj_control(void *shader_priv)
11104 {
11105 struct shader_glsl_priv *priv = shader_priv;
11106
11107 return priv->ffp_proj_control;
11108 }
11109
11110 const struct wined3d_shader_backend_ops glsl_shader_backend =
11111 {
11112 shader_glsl_handle_instruction,
11113 shader_glsl_precompile,
11114 shader_glsl_select,
11115 shader_glsl_select_compute,
11116 shader_glsl_disable,
11117 shader_glsl_update_float_vertex_constants,
11118 shader_glsl_update_float_pixel_constants,
11119 shader_glsl_load_constants,
11120 shader_glsl_destroy,
11121 shader_glsl_alloc,
11122 shader_glsl_free,
11123 shader_glsl_allocate_context_data,
11124 shader_glsl_free_context_data,
11125 shader_glsl_init_context_state,
11126 shader_glsl_get_caps,
11127 shader_glsl_color_fixup_supported,
11128 shader_glsl_has_ffp_proj_control,
11129 };
11130
11131 static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
11132
11133 static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
11134 {
11135 caps->xyzrhw = TRUE;
11136 caps->emulated_flatshading = !needs_legacy_glsl_syntax(gl_info);
11137 caps->ffp_generic_attributes = TRUE;
11138 caps->max_active_lights = MAX_ACTIVE_LIGHTS;
11139 caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS;
11140 caps->max_vertex_blend_matrix_index = MAX_VERTEX_INDEX_BLENDS - 1;
11141 caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN
11142 | WINED3DVTXPCAPS_MATERIALSOURCE7
11143 | WINED3DVTXPCAPS_VERTEXFOG
11144 | WINED3DVTXPCAPS_DIRECTIONALLIGHTS
11145 | WINED3DVTXPCAPS_POSITIONALLIGHTS
11146 | WINED3DVTXPCAPS_LOCALVIEWER
11147 | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP;
11148 caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 8; /* 8 texture coordinates. */
11149 caps->max_user_clip_planes = gl_info->limits.user_clip_distances;
11150 caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE;
11151 }
11152
11153 static DWORD glsl_vertex_pipe_vp_get_emul_mask(const struct wined3d_gl_info *gl_info)
11154 {
11155 if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
11156 return GL_EXT_EMUL_ARB_MULTITEXTURE;
11157 return 0;
11158 }
11159
11160 static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
11161 {
11162 struct shader_glsl_priv *priv;
11163
11164 if (shader_backend == &glsl_shader_backend)
11165 {
11166 priv = shader_priv;
11167 wine_rb_init(&priv->ffp_vertex_shaders, wined3d_ffp_vertex_program_key_compare);
11168 return priv;
11169 }
11170
11171 FIXME("GLSL vertex pipe without GLSL shader backend not implemented.\n");
11172
11173 return NULL;
11174 }
11175
11176 static void shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context)
11177 {
11178 struct glsl_ffp_vertex_shader *shader = WINE_RB_ENTRY_VALUE(entry,
11179 struct glsl_ffp_vertex_shader, desc.entry);
11180 struct glsl_shader_prog_link *program, *program2;
11181 struct glsl_ffp_destroy_ctx *ctx = context;
11182
11183 LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs,
11184 struct glsl_shader_prog_link, vs.shader_entry)
11185 {
11186 delete_glsl_program_entry(ctx->priv, ctx->gl_info, program);
11187 }
11188 ctx->gl_info->gl_ops.ext.p_glDeleteShader(shader->id);
11189 heap_free(shader);
11190 }
11191
11192 /* Context activation is done by the caller. */
11193 static void glsl_vertex_pipe_vp_free(struct wined3d_device *device)
11194 {
11195 struct shader_glsl_priv *priv = device->vertex_priv;
11196 struct glsl_ffp_destroy_ctx ctx;
11197
11198 ctx.priv = priv;
11199 ctx.gl_info = &device->adapter->gl_info;
11200 wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx);
11201 }
11202
11203 static void glsl_vertex_pipe_nop(struct wined3d_context *context,
11204 const struct wined3d_state *state, DWORD state_id) {}
11205
11206 static void glsl_vertex_pipe_shader(struct wined3d_context *context,
11207 const struct wined3d_state *state, DWORD state_id)
11208 {
11209 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11210 }
11211
11212 static void glsl_vertex_pipe_vdecl(struct wined3d_context *context,
11213 const struct wined3d_state *state, DWORD state_id)
11214 {
11215 const struct wined3d_gl_info *gl_info = context->gl_info;
11216 BOOL normal = !!(context->stream_info.use_map & (1u << WINED3D_FFP_NORMAL));
11217 const BOOL legacy_clip_planes = needs_legacy_glsl_syntax(gl_info);
11218 BOOL transformed = context->stream_info.position_transformed;
11219 BOOL wasrhw = context->last_was_rhw;
11220 unsigned int i;
11221
11222 context->last_was_rhw = transformed;
11223
11224 /* If the vertex declaration contains a transformed position attribute,
11225 * the draw uses the fixed function vertex pipeline regardless of any
11226 * vertex shader set by the application. */
11227 if (transformed != wasrhw
11228 || context->stream_info.swizzle_map != context->last_swizzle_map)
11229 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11230
11231 context->last_swizzle_map = context->stream_info.swizzle_map;
11232
11233 if (!use_vs(state))
11234 {
11235 if (context->last_was_vshader)
11236 {
11237 if (legacy_clip_planes)
11238 for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
11239 clipplane(context, state, STATE_CLIPPLANE(i));
11240 else
11241 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES;
11242 }
11243
11244 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
11245
11246 /* Because of settings->texcoords, we have to regenerate the vertex
11247 * shader on a vdecl change if there aren't enough varyings to just
11248 * always output all the texture coordinates. */
11249 if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info)
11250 || normal != context->last_was_normal)
11251 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11252
11253 if (use_ps(state)
11254 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.major == 1
11255 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3)
11256 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11257 }
11258 else
11259 {
11260 if (!context->last_was_vshader)
11261 {
11262 /* Vertex shader clipping ignores the view matrix. Update all clip planes. */
11263 if (legacy_clip_planes)
11264 for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
11265 clipplane(context, state, STATE_CLIPPLANE(i));
11266 else
11267 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES;
11268 }
11269 }
11270
11271 context->last_was_vshader = use_vs(state);
11272 context->last_was_normal = normal;
11273 }
11274
11275 static void glsl_vertex_pipe_vs(struct wined3d_context *context,
11276 const struct wined3d_state *state, DWORD state_id)
11277 {
11278 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11279 /* Different vertex shaders potentially require a different vertex attributes setup. */
11280 if (!isStateDirty(context, STATE_VDECL))
11281 context_apply_state(context, state, STATE_VDECL);
11282 }
11283
11284 static void glsl_vertex_pipe_hs(struct wined3d_context *context,
11285 const struct wined3d_state *state, DWORD state_id)
11286 {
11287 /* In Direct3D tessellator options (e.g. output primitive type, primitive
11288 * winding) are defined in Hull Shaders, while in GLSL those are
11289 * specified in Tessellation Evaluation Shaders. */
11290 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN;
11291
11292 if (state->shader[WINED3D_SHADER_TYPE_VERTEX])
11293 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11294 }
11295
11296 static void glsl_vertex_pipe_geometry_shader(struct wined3d_context *context,
11297 const struct wined3d_state *state, DWORD state_id)
11298 {
11299 struct glsl_context_data *ctx_data = context->shader_backend_data;
11300 BOOL rasterization_disabled;
11301
11302 rasterization_disabled = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
11303 if (ctx_data->rasterization_disabled != rasterization_disabled)
11304 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11305 ctx_data->rasterization_disabled = rasterization_disabled;
11306
11307 if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
11308 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN;
11309 else if (state->shader[WINED3D_SHADER_TYPE_VERTEX]
11310 && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4)
11311 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11312 }
11313
11314 static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context,
11315 const struct wined3d_state *state, DWORD state_id)
11316 {
11317 if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY])
11318 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_GEOMETRY;
11319 else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
11320 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN;
11321 else if (state->shader[WINED3D_SHADER_TYPE_VERTEX]
11322 && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4)
11323 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11324 }
11325
11326 static void glsl_vertex_pipe_world(struct wined3d_context *context,
11327 const struct wined3d_state *state, DWORD state_id)
11328 {
11329 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW;
11330 }
11331
11332 static void glsl_vertex_pipe_vertexblend(struct wined3d_context *context,
11333 const struct wined3d_state *state, DWORD state_id)
11334 {
11335 int i = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0));
11336 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i);
11337 }
11338
11339 static void glsl_vertex_pipe_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
11340 {
11341 const struct wined3d_gl_info *gl_info = context->gl_info;
11342 unsigned int k;
11343
11344 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW
11345 | WINED3D_SHADER_CONST_FFP_LIGHTS
11346 | WINED3D_SHADER_CONST_FFP_VERTEXBLEND;
11347
11348 if (needs_legacy_glsl_syntax(gl_info))
11349 {
11350 for (k = 0; k < gl_info->limits.user_clip_distances; ++k)
11351 {
11352 if (!isStateDirty(context, STATE_CLIPPLANE(k)))
11353 clipplane(context, state, STATE_CLIPPLANE(k));
11354 }
11355 }
11356 else
11357 {
11358 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES;
11359 }
11360 }
11361
11362 static void glsl_vertex_pipe_projection(struct wined3d_context *context,
11363 const struct wined3d_state *state, DWORD state_id)
11364 {
11365 /* Table fog behavior depends on the projection matrix. */
11366 if (state->render_states[WINED3D_RS_FOGENABLE]
11367 && state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
11368 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11369 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PROJ;
11370 }
11371
11372 static void glsl_vertex_pipe_viewport(struct wined3d_context *context,
11373 const struct wined3d_state *state, DWORD state_id)
11374 {
11375 if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
11376 glsl_vertex_pipe_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
11377 if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE))
11378 && state->render_states[WINED3D_RS_POINTSCALEENABLE])
11379 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE;
11380 context->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
11381 }
11382
11383 static void glsl_vertex_pipe_texmatrix(struct wined3d_context *context,
11384 const struct wined3d_state *state, DWORD state_id)
11385 {
11386 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
11387 }
11388
11389 static void glsl_vertex_pipe_texmatrix_np2(struct wined3d_context *context,
11390 const struct wined3d_state *state, DWORD state_id)
11391 {
11392 DWORD sampler = state_id - STATE_SAMPLER(0);
11393 const struct wined3d_texture *texture = state->textures[sampler];
11394 BOOL np2;
11395
11396 if (!texture)
11397 return;
11398
11399 if (sampler >= MAX_TEXTURES)
11400 return;
11401
11402 if ((np2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
11403 || context->lastWasPow2Texture & (1u << sampler))
11404 {
11405 if (np2)
11406 context->lastWasPow2Texture |= 1u << sampler;
11407 else
11408 context->lastWasPow2Texture &= ~(1u << sampler);
11409
11410 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
11411 }
11412 }
11413
11414 static void glsl_vertex_pipe_material(struct wined3d_context *context,
11415 const struct wined3d_state *state, DWORD state_id)
11416 {
11417 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MATERIAL;
11418 }
11419
11420 static void glsl_vertex_pipe_light(struct wined3d_context *context,
11421 const struct wined3d_state *state, DWORD state_id)
11422 {
11423 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_LIGHTS;
11424 }
11425
11426 static void glsl_vertex_pipe_pointsize(struct wined3d_context *context,
11427 const struct wined3d_state *state, DWORD state_id)
11428 {
11429 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE;
11430 }
11431
11432 static void glsl_vertex_pipe_pointscale(struct wined3d_context *context,
11433 const struct wined3d_state *state, DWORD state_id)
11434 {
11435 if (!use_vs(state))
11436 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE;
11437 }
11438
11439 static void glsl_vertex_pointsprite_core(struct wined3d_context *context,
11440 const struct wined3d_state *state, DWORD state_id)
11441 {
11442 static unsigned int once;
11443
11444 if (state->gl_primitive_type == GL_POINTS && !state->render_states[WINED3D_RS_POINTSPRITEENABLE] && !once++)
11445 FIXME("Non-point sprite points not supported in core profile.\n");
11446 }
11447
11448 static void glsl_vertex_pipe_shademode(struct wined3d_context *context,
11449 const struct wined3d_state *state, DWORD state_id)
11450 {
11451 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
11452 }
11453
11454 static void glsl_vertex_pipe_clip_plane(struct wined3d_context *context,
11455 const struct wined3d_state *state, DWORD state_id)
11456 {
11457 const struct wined3d_gl_info *gl_info = context->gl_info;
11458 UINT index = state_id - STATE_CLIPPLANE(0);
11459
11460 if (index >= gl_info->limits.user_clip_distances)
11461 return;
11462
11463 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES;
11464 }
11465
11466 static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] =
11467 {
11468 {STATE_VDECL, {STATE_VDECL, glsl_vertex_pipe_vdecl }, WINED3D_GL_EXT_NONE },
11469 {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_vertex_pipe_vs }, WINED3D_GL_EXT_NONE },
11470 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), glsl_vertex_pipe_hs }, WINED3D_GL_EXT_NONE },
11471 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), glsl_vertex_pipe_geometry_shader}, WINED3D_GL_EXT_NONE },
11472 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_vertex_pipe_pixel_shader}, WINED3D_GL_EXT_NONE },
11473 {STATE_MATERIAL, {STATE_RENDER(WINED3D_RS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE },
11474 {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_vertex_pipe_material}, WINED3D_GL_EXT_NONE },
11475 /* Clip planes */
11476 {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11477 {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE },
11478 {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11479 {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE },
11480 {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11481 {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE },
11482 {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11483 {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE },
11484 {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11485 {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE },
11486 {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11487 {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE },
11488 {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11489 {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE },
11490 {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 },
11491 {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE },
11492 /* Lights */
11493 {STATE_LIGHT_TYPE, {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
11494 {STATE_ACTIVELIGHT(0), {STATE_ACTIVELIGHT(0), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11495 {STATE_ACTIVELIGHT(1), {STATE_ACTIVELIGHT(1), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11496 {STATE_ACTIVELIGHT(2), {STATE_ACTIVELIGHT(2), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11497 {STATE_ACTIVELIGHT(3), {STATE_ACTIVELIGHT(3), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11498 {STATE_ACTIVELIGHT(4), {STATE_ACTIVELIGHT(4), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11499 {STATE_ACTIVELIGHT(5), {STATE_ACTIVELIGHT(5), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11500 {STATE_ACTIVELIGHT(6), {STATE_ACTIVELIGHT(6), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11501 {STATE_ACTIVELIGHT(7), {STATE_ACTIVELIGHT(7), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11502 /* Viewport */
11503 {STATE_VIEWPORT, {STATE_VIEWPORT, glsl_vertex_pipe_viewport}, WINED3D_GL_EXT_NONE },
11504 /* Transform states */
11505 {STATE_TRANSFORM(WINED3D_TS_VIEW), {STATE_TRANSFORM(WINED3D_TS_VIEW), glsl_vertex_pipe_view }, WINED3D_GL_EXT_NONE },
11506 {STATE_TRANSFORM(WINED3D_TS_PROJECTION), {STATE_TRANSFORM(WINED3D_TS_PROJECTION), glsl_vertex_pipe_projection}, WINED3D_GL_EXT_NONE },
11507 {STATE_TRANSFORM(WINED3D_TS_TEXTURE0), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11508 {STATE_TRANSFORM(WINED3D_TS_TEXTURE1), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11509 {STATE_TRANSFORM(WINED3D_TS_TEXTURE2), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11510 {STATE_TRANSFORM(WINED3D_TS_TEXTURE3), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11511 {STATE_TRANSFORM(WINED3D_TS_TEXTURE4), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11512 {STATE_TRANSFORM(WINED3D_TS_TEXTURE5), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11513 {STATE_TRANSFORM(WINED3D_TS_TEXTURE6), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11514 {STATE_TRANSFORM(WINED3D_TS_TEXTURE7), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE },
11515 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), glsl_vertex_pipe_world }, WINED3D_GL_EXT_NONE },
11516 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11517 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11518 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11519 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11520 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11521 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11522 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11523 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE },
11524 {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11525 {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11526 {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11527 {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11528 {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11529 {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11530 {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11531 {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE },
11532 {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11533 {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11534 {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11535 {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11536 {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11537 {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11538 {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11539 {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11540 /* Fog */
11541 {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE },
11542 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
11543 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
11544 {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
11545 {STATE_RENDER(WINED3D_RS_CLIPPING), {STATE_RENDER(WINED3D_RS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
11546 {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE), {STATE_RENDER(WINED3D_RS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE },
11547 {STATE_RENDER(WINED3D_RS_LIGHTING), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11548 {STATE_RENDER(WINED3D_RS_AMBIENT), {STATE_RENDER(WINED3D_RS_AMBIENT), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE },
11549 {STATE_RENDER(WINED3D_RS_COLORVERTEX), {STATE_RENDER(WINED3D_RS_COLORVERTEX), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE },
11550 {STATE_RENDER(WINED3D_RS_LOCALVIEWER), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11551 {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11552 {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11553 {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11554 {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11555 {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11556 {STATE_RENDER(WINED3D_RS_VERTEXBLEND), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11557 {STATE_RENDER(WINED3D_RS_POINTSIZE), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE },
11558 {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), glsl_vertex_pipe_pointsize}, WINED3D_GL_EXT_NONE },
11559 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
11560 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_LEGACY_CONTEXT },
11561 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_vertex_pointsprite_core}, WINED3D_GL_EXT_NONE },
11562 {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), glsl_vertex_pipe_pointscale}, WINED3D_GL_EXT_NONE },
11563 {STATE_RENDER(WINED3D_RS_POINTSCALE_A), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
11564 {STATE_RENDER(WINED3D_RS_POINTSCALE_B), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
11565 {STATE_RENDER(WINED3D_RS_POINTSCALE_C), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
11566 {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE },
11567 {STATE_RENDER(WINED3D_RS_TWEENFACTOR), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11568 {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE },
11569 /* NP2 texture matrix fixups. They are not needed if
11570 * GL_ARB_texture_non_power_of_two is supported. Otherwise, register
11571 * glsl_vertex_pipe_texmatrix(), which takes care of updating the texture
11572 * matrix. */
11573 {STATE_SAMPLER(0), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11574 {STATE_SAMPLER(0), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11575 {STATE_SAMPLER(0), {STATE_SAMPLER(0), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11576 {STATE_SAMPLER(1), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11577 {STATE_SAMPLER(1), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11578 {STATE_SAMPLER(1), {STATE_SAMPLER(1), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11579 {STATE_SAMPLER(2), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11580 {STATE_SAMPLER(2), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11581 {STATE_SAMPLER(2), {STATE_SAMPLER(2), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11582 {STATE_SAMPLER(3), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11583 {STATE_SAMPLER(3), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11584 {STATE_SAMPLER(3), {STATE_SAMPLER(3), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11585 {STATE_SAMPLER(4), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11586 {STATE_SAMPLER(4), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11587 {STATE_SAMPLER(4), {STATE_SAMPLER(4), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11588 {STATE_SAMPLER(5), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11589 {STATE_SAMPLER(5), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11590 {STATE_SAMPLER(5), {STATE_SAMPLER(5), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11591 {STATE_SAMPLER(6), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11592 {STATE_SAMPLER(6), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11593 {STATE_SAMPLER(6), {STATE_SAMPLER(6), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11594 {STATE_SAMPLER(7), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
11595 {STATE_SAMPLER(7), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT},
11596 {STATE_SAMPLER(7), {STATE_SAMPLER(7), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE },
11597 {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE },
11598 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_vertex_pipe_shademode}, WINED3D_GLSL_130 },
11599 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_vertex_pipe_nop }, WINED3D_GL_EXT_NONE },
11600 {0 /* Terminate */, {0, NULL }, WINED3D_GL_EXT_NONE },
11601 };
11602
11603 /* TODO:
11604 * - Implement vertex tweening. */
11605 const struct wined3d_vertex_pipe_ops glsl_vertex_pipe =
11606 {
11607 glsl_vertex_pipe_vp_enable,
11608 glsl_vertex_pipe_vp_get_caps,
11609 glsl_vertex_pipe_vp_get_emul_mask,
11610 glsl_vertex_pipe_vp_alloc,
11611 glsl_vertex_pipe_vp_free,
11612 glsl_vertex_pipe_vp_states,
11613 };
11614
11615 static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
11616 {
11617 /* Nothing to do. */
11618 }
11619
11620 static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
11621 {
11622 caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL
11623 | WINED3D_FRAGMENT_CAP_SRGB_WRITE
11624 | WINED3D_FRAGMENT_CAP_COLOR_KEY;
11625 caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP
11626 | WINED3DPMISCCAPS_PERSTAGECONSTANT;
11627 caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE
11628 | WINED3DTEXOPCAPS_SELECTARG1
11629 | WINED3DTEXOPCAPS_SELECTARG2
11630 | WINED3DTEXOPCAPS_MODULATE4X
11631 | WINED3DTEXOPCAPS_MODULATE2X
11632 | WINED3DTEXOPCAPS_MODULATE
11633 | WINED3DTEXOPCAPS_ADDSIGNED2X
11634 | WINED3DTEXOPCAPS_ADDSIGNED
11635 | WINED3DTEXOPCAPS_ADD
11636 | WINED3DTEXOPCAPS_SUBTRACT
11637 | WINED3DTEXOPCAPS_ADDSMOOTH
11638 | WINED3DTEXOPCAPS_BLENDCURRENTALPHA
11639 | WINED3DTEXOPCAPS_BLENDFACTORALPHA
11640 | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
11641 | WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
11642 | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
11643 | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
11644 | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
11645 | WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
11646 | WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
11647 | WINED3DTEXOPCAPS_DOTPRODUCT3
11648 | WINED3DTEXOPCAPS_MULTIPLYADD
11649 | WINED3DTEXOPCAPS_LERP
11650 | WINED3DTEXOPCAPS_BUMPENVMAP
11651 | WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE;
11652 caps->MaxTextureBlendStages = MAX_TEXTURES;
11653 caps->MaxSimultaneousTextures = min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_TEXTURES);
11654 }
11655
11656 static DWORD glsl_fragment_pipe_get_emul_mask(const struct wined3d_gl_info *gl_info)
11657 {
11658 if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
11659 return GL_EXT_EMUL_ARB_MULTITEXTURE;
11660 return 0;
11661 }
11662
11663 static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
11664 {
11665 struct shader_glsl_priv *priv;
11666
11667 if (shader_backend == &glsl_shader_backend)
11668 {
11669 priv = shader_priv;
11670 wine_rb_init(&priv->ffp_fragment_shaders, wined3d_ffp_frag_program_key_compare);
11671 return priv;
11672 }
11673
11674 FIXME("GLSL fragment pipe without GLSL shader backend not implemented.\n");
11675
11676 return NULL;
11677 }
11678
11679 static void shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry *entry, void *context)
11680 {
11681 struct glsl_ffp_fragment_shader *shader = WINE_RB_ENTRY_VALUE(entry,
11682 struct glsl_ffp_fragment_shader, entry.entry);
11683 struct glsl_shader_prog_link *program, *program2;
11684 struct glsl_ffp_destroy_ctx *ctx = context;
11685
11686 LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs,
11687 struct glsl_shader_prog_link, ps.shader_entry)
11688 {
11689 delete_glsl_program_entry(ctx->priv, ctx->gl_info, program);
11690 }
11691 ctx->gl_info->gl_ops.ext.p_glDeleteShader(shader->id);
11692 heap_free(shader);
11693 }
11694
11695 /* Context activation is done by the caller. */
11696 static void glsl_fragment_pipe_free(struct wined3d_device *device)
11697 {
11698 struct shader_glsl_priv *priv = device->fragment_priv;
11699 struct glsl_ffp_destroy_ctx ctx;
11700
11701 ctx.priv = priv;
11702 ctx.gl_info = &device->adapter->gl_info;
11703 wine_rb_destroy(&priv->ffp_fragment_shaders, shader_glsl_free_ffp_fragment_shader, &ctx);
11704 }
11705
11706 static void glsl_fragment_pipe_shader(struct wined3d_context *context,
11707 const struct wined3d_state *state, DWORD state_id)
11708 {
11709 context->last_was_pshader = use_ps(state);
11710
11711 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11712 }
11713
11714 static void glsl_fragment_pipe_fogparams(struct wined3d_context *context,
11715 const struct wined3d_state *state, DWORD state_id)
11716 {
11717 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG;
11718 }
11719
11720 static void glsl_fragment_pipe_fog(struct wined3d_context *context,
11721 const struct wined3d_state *state, DWORD state_id)
11722 {
11723 BOOL use_vshader = use_vs(state);
11724 enum fogsource new_source;
11725 DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
11726 DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
11727
11728 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11729
11730 if (!state->render_states[WINED3D_RS_FOGENABLE])
11731 return;
11732
11733 if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
11734 {
11735 if (use_vshader)
11736 new_source = FOGSOURCE_VS;
11737 else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->stream_info.position_transformed)
11738 new_source = FOGSOURCE_COORD;
11739 else
11740 new_source = FOGSOURCE_FFP;
11741 }
11742 else
11743 {
11744 new_source = FOGSOURCE_FFP;
11745 }
11746
11747 if (new_source != context->fog_source || fogstart == fogend)
11748 {
11749 context->fog_source = new_source;
11750 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG;
11751 }
11752 }
11753
11754 static void glsl_fragment_pipe_vdecl(struct wined3d_context *context,
11755 const struct wined3d_state *state, DWORD state_id)
11756 {
11757 /* Because of settings->texcoords_initialized and args->texcoords_initialized. */
11758 if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
11759 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11760
11761 if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_FOGENABLE)))
11762 glsl_fragment_pipe_fog(context, state, state_id);
11763 }
11764
11765 static void glsl_fragment_pipe_vs(struct wined3d_context *context,
11766 const struct wined3d_state *state, DWORD state_id)
11767 {
11768 /* Because of settings->texcoords_initialized and args->texcoords_initialized. */
11769 if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
11770 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11771 }
11772
11773 static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context,
11774 const struct wined3d_state *state, DWORD state_id)
11775 {
11776 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11777 }
11778
11779 static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context,
11780 const struct wined3d_state *state, DWORD state_id)
11781 {
11782 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS;
11783 }
11784
11785 static void glsl_fragment_pipe_alpha_test_func(struct wined3d_context *context,
11786 const struct wined3d_state *state, DWORD state_id)
11787 {
11788 const struct wined3d_gl_info *gl_info = context->gl_info;
11789 GLint func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
11790 float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f;
11791
11792 if (func)
11793 {
11794 gl_info->gl_ops.gl.p_glAlphaFunc(func, ref);
11795 checkGLcall("glAlphaFunc");
11796 }
11797 }
11798
11799 static void glsl_fragment_pipe_core_alpha_test(struct wined3d_context *context,
11800 const struct wined3d_state *state, DWORD state_id)
11801 {
11802 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11803 }
11804
11805 static void glsl_fragment_pipe_alpha_test(struct wined3d_context *context,
11806 const struct wined3d_state *state, DWORD state_id)
11807 {
11808 const struct wined3d_gl_info *gl_info = context->gl_info;
11809
11810 if (state->render_states[WINED3D_RS_ALPHATESTENABLE])
11811 {
11812 gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
11813 checkGLcall("glEnable(GL_ALPHA_TEST)");
11814 }
11815 else
11816 {
11817 gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
11818 checkGLcall("glDisable(GL_ALPHA_TEST)");
11819 }
11820 }
11821
11822 static void glsl_fragment_pipe_core_alpha_test_ref(struct wined3d_context *context,
11823 const struct wined3d_state *state, DWORD state_id)
11824 {
11825 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST;
11826 }
11827
11828 static void glsl_fragment_pipe_color_key(struct wined3d_context *context,
11829 const struct wined3d_state *state, DWORD state_id)
11830 {
11831 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY;
11832 }
11833
11834 static void glsl_fragment_pipe_shademode(struct wined3d_context *context,
11835 const struct wined3d_state *state, DWORD state_id)
11836 {
11837 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
11838 }
11839
11840 static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
11841 {
11842 {STATE_VDECL, {STATE_VDECL, glsl_fragment_pipe_vdecl }, WINED3D_GL_EXT_NONE },
11843 {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_fragment_pipe_vs }, WINED3D_GL_EXT_NONE },
11844 {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11845 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11846 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11847 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11848 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11849 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11850 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11851 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11852 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11853 {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11854 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11855 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11856 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11857 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11858 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11859 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11860 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11861 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11862 {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11863 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11864 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11865 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11866 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11867 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11868 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11869 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11870 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11871 {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11872 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11873 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11874 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11875 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11876 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11877 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11878 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11879 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11880 {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11881 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11882 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11883 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11884 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11885 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11886 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11887 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11888 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11889 {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11890 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11891 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11892 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11893 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11894 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11895 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11896 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11897 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11898 {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11899 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11900 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11901 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11902 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11903 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11904 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11905 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11906 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11907 {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11908 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11909 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11910 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11911 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11912 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11913 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11914 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11915 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11916 {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11917 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE },
11918 {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), glsl_fragment_pipe_alpha_test_func }, WINED3D_GL_LEGACY_CONTEXT},
11919 {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
11920 {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), NULL }, WINED3D_GL_LEGACY_CONTEXT},
11921 {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAREF), glsl_fragment_pipe_core_alpha_test_ref }, WINED3D_GL_EXT_NONE },
11922 {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_alpha_test }, WINED3D_GL_LEGACY_CONTEXT},
11923 {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_core_alpha_test }, WINED3D_GL_EXT_NONE },
11924 {STATE_RENDER(WINED3D_RS_COLORKEYENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11925 {STATE_COLOR_KEY, { STATE_COLOR_KEY, glsl_fragment_pipe_color_key }, WINED3D_GL_EXT_NONE },
11926 {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_fragment_pipe_fog }, WINED3D_GL_EXT_NONE },
11927 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
11928 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
11929 {STATE_RENDER(WINED3D_RS_FOGSTART), {STATE_RENDER(WINED3D_RS_FOGSTART), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE },
11930 {STATE_RENDER(WINED3D_RS_FOGEND), {STATE_RENDER(WINED3D_RS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE },
11931 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), state_srgbwrite }, ARB_FRAMEBUFFER_SRGB},
11932 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
11933 {STATE_RENDER(WINED3D_RS_FOGCOLOR), {STATE_RENDER(WINED3D_RS_FOGCOLOR), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE },
11934 {STATE_RENDER(WINED3D_RS_FOGDENSITY), {STATE_RENDER(WINED3D_RS_FOGDENSITY), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE },
11935 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_fragment_pipe_shader }, ARB_POINT_SPRITE },
11936 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_fragment_pipe_shader }, WINED3D_GL_VERSION_2_0},
11937 {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11938 {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11939 {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11940 {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11941 {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11942 {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11943 {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11944 {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
11945 {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11946 {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11947 {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11948 {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11949 {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11950 {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11951 {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11952 {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11953 {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
11954 {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE },
11955 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_fragment_pipe_shademode }, WINED3D_GLSL_130 },
11956 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE },
11957 {0 /* Terminate */, {0, 0 }, WINED3D_GL_EXT_NONE },
11958 };
11959
11960 static BOOL glsl_fragment_pipe_alloc_context_data(struct wined3d_context *context)
11961 {
11962 return TRUE;
11963 }
11964
11965 static void glsl_fragment_pipe_free_context_data(struct wined3d_context *context)
11966 {
11967 }
11968
11969 const struct fragment_pipeline glsl_fragment_pipe =
11970 {
11971 glsl_fragment_pipe_enable,
11972 glsl_fragment_pipe_get_caps,
11973 glsl_fragment_pipe_get_emul_mask,
11974 glsl_fragment_pipe_alloc,
11975 glsl_fragment_pipe_free,
11976 glsl_fragment_pipe_alloc_context_data,
11977 glsl_fragment_pipe_free_context_data,
11978 shader_glsl_color_fixup_supported,
11979 glsl_fragment_pipe_state_template,
11980 };