xref: /reactos/dll/directx/wine/wined3d/glsl_shader.c (revision 81cffd76)
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 
debug_gl_shader_type(GLenum type)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 
shader_glsl_get_prefix(enum wined3d_shader_type type)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 
shader_glsl_get_version(const struct wined3d_gl_info * gl_info)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 
shader_glsl_add_version_declaration(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info)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 
shader_glsl_append_imm_vec4(struct wined3d_string_buffer * buffer,const float * values)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 
shader_glsl_append_imm_ivec(struct wined3d_string_buffer * buffer,const int * values,unsigned int size)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 
get_info_log_line(const char ** ptr)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. */
print_glsl_info_log(const struct wined3d_gl_info * gl_info,GLuint id,BOOL program)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. */
shader_glsl_compile(const struct wined3d_gl_info * gl_info,GLuint shader,const char * src)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. */
shader_glsl_dump_program_source(const struct wined3d_gl_info * gl_info,GLuint program)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. */
shader_glsl_validate_link(const struct wined3d_gl_info * gl_info,GLuint program)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 
shader_glsl_use_layout_qualifier(const struct wined3d_gl_info * gl_info)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 
shader_glsl_use_layout_binding_qualifier(const struct wined3d_gl_info * gl_info)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 
shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,const struct wined3d_shader_reg_maps * reg_maps)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. */
shader_glsl_load_samplers_range(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,const char * prefix,unsigned int base,unsigned int count,const DWORD * tex_unit_map)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 
shader_glsl_map_tex_unit(const struct wined3d_context * context,const struct wined3d_shader_version * shader_version,unsigned int sampler_idx)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 
shader_glsl_append_sampler_binding_qualifier(struct wined3d_string_buffer * buffer,const struct wined3d_context * context,const struct wined3d_shader_version * shader_version,unsigned int sampler_idx)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. */
shader_glsl_load_samplers(const struct wined3d_context * context,struct shader_glsl_priv * priv,GLuint program_id,const struct wined3d_shader_reg_maps * reg_maps)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 
shader_glsl_load_icb(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,const struct wined3d_shader_reg_maps * reg_maps)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. */
shader_glsl_load_images(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,const struct wined3d_shader_reg_maps * reg_maps)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. */
shader_glsl_load_program_resources(const struct wined3d_context * context,struct shader_glsl_priv * priv,GLuint program_id,const struct wined3d_shader * shader)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 
append_transform_feedback_varying(const char ** varyings,unsigned int * varying_count,char ** strings,unsigned int * strings_length,struct wined3d_string_buffer * buffer)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 
append_transform_feedback_skip_components(const char ** varyings,unsigned int * varying_count,char ** strings,unsigned int * strings_length,struct wined3d_string_buffer * buffer,unsigned int component_count)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 
shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc * so_desc,struct wined3d_string_buffer * buffer,const char ** varyings,unsigned int * varying_count,char * strings,unsigned int * strings_length,GLenum buffer_mode)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 
shader_glsl_init_transform_feedback(const struct wined3d_context * context,struct shader_glsl_priv * priv,GLuint program_id,const struct wined3d_shader * shader)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. */
walk_constant_heap(const struct wined3d_gl_info * gl_info,const struct wined3d_vec4 * constants,const GLint * constant_locations,const struct constant_heap * heap,unsigned char * stack,DWORD version)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. */
apply_clamped_constant(const struct wined3d_gl_info * gl_info,GLint location,const struct wined3d_vec4 * data)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. */
walk_constant_heap_clamped(const struct wined3d_gl_info * gl_info,const struct wined3d_vec4 * constants,const GLint * constant_locations,const struct constant_heap * heap,unsigned char * stack,DWORD version)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. */
shader_glsl_load_constants_f(const struct wined3d_shader * shader,const struct wined3d_gl_info * gl_info,const struct wined3d_vec4 * constants,const GLint * constant_locations,const struct constant_heap * heap,unsigned char * stack,unsigned int version)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. */
shader_glsl_load_constants_i(const struct wined3d_shader * shader,const struct wined3d_gl_info * gl_info,const struct wined3d_ivec4 * constants,const GLint locations[WINED3D_MAX_CONSTS_I],WORD constants_set)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. */
shader_glsl_load_constantsB(const struct wined3d_shader * shader,const struct wined3d_gl_info * gl_info,const GLint locations[WINED3D_MAX_CONSTS_B],const BOOL * constants,WORD constants_set)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 
reset_program_constant_version(struct wine_rb_entry * entry,void * context)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). */
shader_glsl_load_np2fixup_constants(const struct glsl_ps_program * ps,const struct wined3d_gl_info * gl_info,const struct wined3d_state * state)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 
shader_glsl_ffp_vertex_texmatrix_uniform(const struct wined3d_context * context,const struct wined3d_state * state,unsigned int tex,struct glsl_shader_prog_link * prog)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 
shader_glsl_ffp_vertex_material_uniform(const struct wined3d_context * context,const struct wined3d_state * state,struct glsl_shader_prog_link * prog)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 
shader_glsl_ffp_vertex_lightambient_uniform(const struct wined3d_context * context,const struct wined3d_state * state,struct glsl_shader_prog_link * prog)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 
multiply_vector_matrix(struct wined3d_vec4 * dest,const struct wined3d_vec4 * src1,const struct wined3d_matrix * src2)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 
shader_glsl_ffp_vertex_light_uniform(const struct wined3d_context * context,const struct wined3d_state * state,unsigned int light,const struct wined3d_light_info * light_info,struct glsl_shader_prog_link * prog)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 
shader_glsl_pointsize_uniform(const struct wined3d_context * context,const struct wined3d_state * state,struct glsl_shader_prog_link * prog)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 
shader_glsl_load_fog_uniform(const struct wined3d_context * context,const struct wined3d_state * state,struct glsl_shader_prog_link * prog)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 
shader_glsl_clip_plane_uniform(const struct wined3d_context * context,const struct wined3d_state * state,unsigned int index,struct glsl_shader_prog_link * prog)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). */
shader_glsl_load_color_key_constant(const struct glsl_ps_program * ps,const struct wined3d_gl_info * gl_info,const struct wined3d_state * state)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. */
get_normal_matrix(struct wined3d_context * context,struct wined3d_matrix * mat,float * normal)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). */
shader_glsl_load_constants(void * shader_priv,struct wined3d_context * context,const struct wined3d_state * state)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 
update_heap_entry(struct constant_heap * heap,unsigned int idx,DWORD new_version)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 
shader_glsl_update_float_vertex_constants(struct wined3d_device * device,UINT start,UINT count)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 
shader_glsl_update_float_pixel_constants(struct wined3d_device * device,UINT start,UINT count)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 
vec4_varyings(DWORD shader_major,const struct wined3d_gl_info * gl_info)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 
needs_legacy_glsl_syntax(const struct wined3d_gl_info * gl_info)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 
shader_glsl_use_explicit_attrib_location(const struct wined3d_gl_info * gl_info)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 
shader_glsl_use_interface_blocks(const struct wined3d_gl_info * gl_info)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 
get_attribute_keyword(const struct wined3d_gl_info * gl_info)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 
declare_in_varying(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,BOOL flat,const char * format,...)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 
declare_out_varying(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,BOOL flat,const char * format,...)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 
shader_glsl_shader_input_name(const struct wined3d_gl_info * gl_info)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 
shader_glsl_shader_output_name(const struct wined3d_gl_info * gl_info)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 
shader_glsl_interpolation_qualifiers(enum wined3d_shader_interpolation_mode mode)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 
wined3d_extract_interpolation_mode(const DWORD * packed_interpolation_mode,unsigned int register_idx)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 
shader_glsl_declare_shader_inputs(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,unsigned int element_count,const DWORD * interpolation_mode,BOOL unroll)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 
shader_glsl_declare_shader_outputs(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,unsigned int element_count,BOOL rasterizer_setup,const DWORD * interpolation_mode)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 
glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)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 
glsl_is_color_reg_read(const struct wined3d_shader * shader,unsigned int idx)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 
glsl_is_shadow_sampler(const struct wined3d_shader * shader,const struct ps_compile_args * ps_args,unsigned int resource_idx,unsigned int sampler_idx)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 
shader_glsl_declare_typed_vertex_attribute(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info,const char * vector_type,const char * scalar_type,unsigned int index)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 
shader_glsl_declare_generic_vertex_attribute(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info,const struct wined3d_shader_signature_element * e)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 */
shader_generate_glsl_declarations(const struct wined3d_context * context,struct wined3d_string_buffer * buffer,const struct wined3d_shader * shader,const struct wined3d_shader_reg_maps * reg_maps,const struct shader_glsl_ctx_priv * ctx_priv)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 */
shader_glsl_gen_modifier(enum wined3d_shader_src_modifier src_modifier,const char * in_reg,const char * in_regswizzle,char * out_str)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 
shader_glsl_fixup_scalar_register_variable(char * register_name,const char * glsl_variable,const struct wined3d_gl_info * gl_info)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 */
shader_glsl_get_register_name(const struct wined3d_shader_register * reg,enum wined3d_data_type data_type,char * register_name,BOOL * is_color,const struct wined3d_shader_instruction * ins)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 
shader_glsl_write_mask_to_str(DWORD write_mask,char * str)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 */
shader_glsl_get_write_mask(const struct wined3d_shader_dst_param * param,char * write_mask)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 
shader_glsl_get_write_mask_size(DWORD write_mask)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 
shader_glsl_swizzle_get_component(DWORD swizzle,unsigned int component_idx)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 
shader_glsl_swizzle_to_str(DWORD swizzle,BOOL fixup,DWORD mask,char * str)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 
shader_glsl_get_swizzle(const struct wined3d_shader_src_param * param,BOOL fixup,DWORD mask,char * swizzle_str)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 
shader_glsl_sprintf_cast(struct wined3d_string_buffer * dst_param,const char * src_param,enum wined3d_data_type dst_data_type,enum wined3d_data_type src_data_type)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. */
shader_glsl_add_src_param_ext(const struct wined3d_shader_instruction * ins,const struct wined3d_shader_src_param * wined3d_src,DWORD mask,struct glsl_src_param * glsl_src,enum wined3d_data_type data_type)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 
shader_glsl_add_src_param(const struct wined3d_shader_instruction * ins,const struct wined3d_shader_src_param * wined3d_src,DWORD mask,struct glsl_src_param * glsl_src)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. */
shader_glsl_add_dst_param(const struct wined3d_shader_instruction * ins,const struct wined3d_shader_dst_param * wined3d_dst,struct glsl_dst_param * glsl_dst)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 */
shader_glsl_append_dst_ext(struct wined3d_string_buffer * buffer,const struct wined3d_shader_instruction * ins,const struct wined3d_shader_dst_param * dst,enum wined3d_data_type data_type)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 */
shader_glsl_append_dst(struct wined3d_string_buffer * buffer,const struct wined3d_shader_instruction * ins)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 */
shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction * ins)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 
shader_glsl_get_rel_op(enum wined3d_shader_rel_op op)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 
shader_glsl_has_core_grad(const struct wined3d_gl_info * gl_info)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 
shader_glsl_get_coord_size(enum wined3d_shader_resource_type resource_type,unsigned int * coord_size,unsigned int * deriv_size)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 
shader_glsl_get_sample_function(const struct wined3d_shader_context * ctx,DWORD resource_idx,DWORD sampler_idx,DWORD flags,struct glsl_sample_function * sample_function)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 
shader_glsl_release_sample_function(const struct wined3d_shader_context * ctx,struct glsl_sample_function * sample_function)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 
shader_glsl_append_fixup_arg(char * arguments,const char * reg_name,BOOL sign_fixup,enum fixup_channel_source channel_source)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 
shader_glsl_color_correction_ext(struct wined3d_string_buffer * buffer,const char * reg_name,DWORD mask,struct color_fixup_desc fixup)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 
shader_glsl_color_correction(const struct wined3d_shader_instruction * ins,struct color_fixup_desc fixup)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 
shader_glsl_gen_sample_code(const struct wined3d_shader_instruction * ins,unsigned int sampler_bind_idx,const struct glsl_sample_function * sample_function,DWORD swizzle,const char * dx,const char * dy,const char * bias,const struct wined3d_shader_texel_offset * offset,const char * coord_reg_fmt,...)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 
shader_glsl_fixup_position(struct wined3d_string_buffer * buffer)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 
shader_glsl_binop(const struct wined3d_shader_instruction * ins)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 
shader_glsl_relop(const struct wined3d_shader_instruction * ins)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 
shader_glsl_unary_op(const struct wined3d_shader_instruction * ins)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 
shader_glsl_mul_extended(const struct wined3d_shader_instruction * ins)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 
shader_glsl_udiv(const struct wined3d_shader_instruction * ins)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) */
shader_glsl_mov(const struct wined3d_shader_instruction * ins)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)) */
shader_glsl_dot(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_cross(const struct wined3d_shader_instruction * ins)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 
shader_glsl_cut(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_pow(const struct wined3d_shader_instruction * ins)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, ...) */
shader_glsl_map2gl(const struct wined3d_shader_instruction * ins)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 
shader_glsl_float16(const struct wined3d_shader_instruction * ins)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 
shader_glsl_bitwise_op(const struct wined3d_shader_instruction * ins)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 
shader_glsl_nop(const struct wined3d_shader_instruction * ins)4053 static void shader_glsl_nop(const struct wined3d_shader_instruction *ins) {}
4054 
shader_glsl_nrm(const struct wined3d_shader_instruction * ins)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 
shader_glsl_scalar_op(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_expp(const struct wined3d_shader_instruction * ins)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 
shader_glsl_cast(const struct wined3d_shader_instruction * ins,const char * vector_constructor,const char * scalar_constructor)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 
shader_glsl_to_int(const struct wined3d_shader_instruction * ins)4188 static void shader_glsl_to_int(const struct wined3d_shader_instruction *ins)
4189 {
4190     shader_glsl_cast(ins, "ivec", "int");
4191 }
4192 
shader_glsl_to_uint(const struct wined3d_shader_instruction * ins)4193 static void shader_glsl_to_uint(const struct wined3d_shader_instruction *ins)
4194 {
4195     shader_glsl_cast(ins, "uvec", "uint");
4196 }
4197 
shader_glsl_to_float(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_compare(const struct wined3d_shader_instruction * ins)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 
shader_glsl_swapc(const struct wined3d_shader_instruction * ins)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 
shader_glsl_conditional_move(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_cnd(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_mad(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_mnxn(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_lrp(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_lit(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_dst(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_sincos(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_sgn(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_loop(const struct wined3d_shader_instruction * ins)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 
shader_glsl_end(const struct wined3d_shader_instruction * ins)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 
shader_glsl_rep(const struct wined3d_shader_instruction * ins)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 
shader_glsl_switch(const struct wined3d_shader_instruction * ins)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 
shader_glsl_case(const struct wined3d_shader_instruction * ins)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 
shader_glsl_default(const struct wined3d_shader_instruction * ins)4860 static void shader_glsl_default(const struct wined3d_shader_instruction *ins)
4861 {
4862     shader_addline(ins->ctx->buffer, "default:\n");
4863 }
4864 
shader_glsl_generate_conditional_op(const struct wined3d_shader_instruction * ins,const char * op)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 
shader_glsl_if(const struct wined3d_shader_instruction * ins)4876 static void shader_glsl_if(const struct wined3d_shader_instruction *ins)
4877 {
4878     shader_glsl_generate_conditional_op(ins, "{");
4879 }
4880 
shader_glsl_ifc(const struct wined3d_shader_instruction * ins)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 
shader_glsl_else(const struct wined3d_shader_instruction * ins)4893 static void shader_glsl_else(const struct wined3d_shader_instruction *ins)
4894 {
4895     shader_addline(ins->ctx->buffer, "} else {\n");
4896 }
4897 
shader_glsl_emit(const struct wined3d_shader_instruction * ins)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 
shader_glsl_break(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_breakc(const struct wined3d_shader_instruction * ins)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 
shader_glsl_conditional_op(const struct wined3d_shader_instruction * ins)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 
shader_glsl_continue(const struct wined3d_shader_instruction * ins)4947 static void shader_glsl_continue(const struct wined3d_shader_instruction *ins)
4948 {
4949     shader_addline(ins->ctx->buffer, "continue;\n");
4950 }
4951 
shader_glsl_label(const struct wined3d_shader_instruction * ins)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 
shader_glsl_call(const struct wined3d_shader_instruction * ins)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 
shader_glsl_callnz(const struct wined3d_shader_instruction * ins)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 
shader_glsl_ret(const struct wined3d_shader_instruction * ins)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 
shader_glsl_tex(const struct wined3d_shader_instruction * ins)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 
shader_glsl_texldd(const struct wined3d_shader_instruction * ins)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 
shader_glsl_texldl(const struct wined3d_shader_instruction * ins)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 
shader_glsl_find_sampler(const struct wined3d_shader_sampler_map * sampler_map,unsigned int resource_idx,unsigned int sampler_idx)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 
shader_glsl_atomic(const struct wined3d_shader_instruction * ins)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 
shader_glsl_uav_counter(const struct wined3d_shader_instruction * ins)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 
shader_glsl_ld_uav(const struct wined3d_shader_instruction * ins)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 
shader_glsl_ld_raw_structured(const struct wined3d_shader_instruction * ins)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 
shader_glsl_store_uav(const struct wined3d_shader_instruction * ins)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 
shader_glsl_store_raw_structured(const struct wined3d_shader_instruction * ins)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 
shader_glsl_sync(const struct wined3d_shader_instruction * ins)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 
shader_glsl_get_resource_info(const struct wined3d_shader_instruction * ins,const struct wined3d_shader_register * reg)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 
shader_glsl_bufinfo(const struct wined3d_shader_instruction * ins)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 
is_multisampled(enum wined3d_shader_resource_type resource_type)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 
is_mipmapped(enum wined3d_shader_resource_type resource_type)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 
shader_glsl_resinfo(const struct wined3d_shader_instruction * ins)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 
shader_glsl_ld(const struct wined3d_shader_instruction * ins)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 
shader_glsl_sample(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_gen_sample_c_lz(const struct wined3d_shader_instruction * ins,unsigned int sampler_bind_idx,const struct glsl_sample_function * sample_function,unsigned int coord_size,const char * coord_param,const char * ref_param)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 
shader_glsl_sample_c(const struct wined3d_shader_instruction * ins)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 
shader_glsl_gather4(const struct wined3d_shader_instruction * ins)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 
shader_glsl_texcoord(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_texdp3tex(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_texdp3(const struct wined3d_shader_instruction * ins)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   */
shader_glsl_texdepth(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_texm3x2depth(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_texm3x2pad(const struct wined3d_shader_instruction * ins)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. */
shader_glsl_texm3x3pad(const struct wined3d_shader_instruction * ins)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 
shader_glsl_texm3x2tex(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texm3x3tex(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texm3x3(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texm3x3spec(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction * ins)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  */
shader_glsl_texbem(const struct wined3d_shader_instruction * ins)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 
shader_glsl_bem(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texreg2ar(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texreg2gb(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texreg2rgb(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_texkill(const struct wined3d_shader_instruction * ins)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 */
shader_glsl_dp2add(const struct wined3d_shader_instruction * ins)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 
shader_glsl_input_pack(const struct wined3d_shader * shader,struct wined3d_string_buffer * buffer,const struct wined3d_shader_signature * input_signature,const struct wined3d_shader_reg_maps * reg_maps,const struct ps_compile_args * args,const struct wined3d_gl_info * gl_info,BOOL unroll)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 
add_glsl_program_entry(struct shader_glsl_priv * priv,struct glsl_shader_prog_link * entry)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 
get_glsl_program_entry(const struct shader_glsl_priv * priv,const struct glsl_program_key * key)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. */
delete_glsl_program_entry(struct shader_glsl_priv * priv,const struct wined3d_gl_info * gl_info,struct glsl_shader_prog_link * entry)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 
shader_glsl_setup_vs3_output(struct shader_glsl_priv * priv,const struct wined3d_gl_info * gl_info,const DWORD * map,const struct wined3d_shader_signature * input_signature,const struct wined3d_shader_reg_maps * reg_maps_in,const struct wined3d_shader_signature * output_signature,const struct wined3d_shader_reg_maps * reg_maps_out)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 
shader_glsl_setup_sm4_shader_output(struct shader_glsl_priv * priv,unsigned int input_count,const struct wined3d_shader_signature * output_signature,const struct wined3d_shader_reg_maps * reg_maps_out,const char * output_variable_name,BOOL rasterizer_setup)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 
shader_glsl_generate_clip_or_cull_distances(struct wined3d_string_buffer * buffer,const struct wined3d_shader_signature_element * element,DWORD clip_or_cull_distance_mask)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 
shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv * priv,const struct wined3d_gl_info * gl_info,const DWORD * map,const struct wined3d_shader_signature * input_signature,const struct wined3d_shader_reg_maps * reg_maps_in,unsigned int input_count,const struct wined3d_shader_signature * output_signature,const struct wined3d_shader_reg_maps * reg_maps_out,BOOL per_vertex_point_size)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. */
shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl_priv * priv,const struct wined3d_shader * vs,const struct wined3d_shader * ps,BOOL per_vertex_point_size,BOOL flatshading,const struct wined3d_gl_info * gl_info)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 
shader_glsl_generate_stream_output_setup(struct shader_glsl_priv * priv,const struct wined3d_shader * shader,const struct wined3d_stream_output_desc * so_desc)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 
shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv * priv,const struct wined3d_shader * shader,unsigned int input_count,const struct wined3d_gl_info * gl_info,BOOL rasterizer_setup,const DWORD * interpolation_mode)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 
shader_glsl_generate_patch_constant_name(struct wined3d_string_buffer * buffer,const struct wined3d_shader_signature_element * constant,unsigned int * user_constant_idx,const char * reg_mask)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 
shader_glsl_generate_patch_constant_setup(struct wined3d_string_buffer * buffer,const struct wined3d_shader_signature * signature,BOOL input_setup)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 
shader_glsl_generate_srgb_write_correction(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info)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 
shader_glsl_generate_fog_code(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info,enum wined3d_ffp_ps_fog_mode mode)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 
shader_glsl_generate_alpha_test(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info,enum wined3d_cmp_func alpha_func)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 
shader_glsl_enable_extensions(struct wined3d_string_buffer * buffer,const struct wined3d_gl_info * gl_info)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 
shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,const struct wined3d_shader * shader,const struct ps_compile_args * args)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. */
shader_glsl_generate_pshader(const struct wined3d_context * context,struct wined3d_string_buffer * buffer,struct wined3d_string_buffer_list * string_buffers,const struct wined3d_shader * shader,const struct ps_compile_args * args,struct ps_np2fixup_info * np2fixup_info)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 
shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,const struct wined3d_shader * shader,const struct vs_compile_args * args)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. */
shader_glsl_generate_vshader(const struct wined3d_context * context,struct shader_glsl_priv * priv,const struct wined3d_shader * shader,const struct vs_compile_args * args)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 
shader_glsl_generate_default_control_point_phase(const struct wined3d_shader * shader,struct wined3d_string_buffer * buffer,const struct wined3d_shader_reg_maps * reg_maps)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 
shader_glsl_generate_shader_phase(const struct wined3d_shader * shader,struct wined3d_string_buffer * buffer,const struct wined3d_shader_reg_maps * reg_maps,struct shader_glsl_ctx_priv * priv_ctx,const struct wined3d_shader_phase * phase,const char * phase_name,unsigned phase_idx)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 
shader_glsl_generate_shader_phase_invocation(struct wined3d_string_buffer * buffer,const struct wined3d_shader_phase * phase,const char * phase_name,unsigned int phase_idx)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 
shader_glsl_generate_hull_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,const struct wined3d_shader * shader)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 
shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info * gl_info,struct wined3d_string_buffer * buffer,const struct wined3d_shader * shader,const struct ds_compile_args * args)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 
shader_glsl_generate_domain_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,const struct wined3d_shader * shader,const struct ds_compile_args * args)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. */
shader_glsl_generate_geometry_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,const struct wined3d_shader * shader,const struct gs_compile_args * args)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 
shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context * ctx)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. */
shader_glsl_generate_compute_shader(const struct wined3d_context * context,struct wined3d_string_buffer * buffer,struct wined3d_string_buffer_list * string_buffers,const struct wined3d_shader * shader)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 
find_glsl_pshader(const struct wined3d_context * context,struct wined3d_string_buffer * buffer,struct wined3d_string_buffer_list * string_buffers,struct wined3d_shader * shader,const struct ps_compile_args * args,const struct ps_np2fixup_info ** np2fixup_info)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 
vs_args_equal(const struct vs_compile_args * stored,const struct vs_compile_args * new,const DWORD use_map)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 
find_glsl_vshader(const struct wined3d_context * context,struct shader_glsl_priv * priv,struct wined3d_shader * shader,const struct vs_compile_args * args)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 
find_glsl_hull_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,struct wined3d_shader * shader)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 
find_glsl_domain_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,struct wined3d_shader * shader,const struct ds_compile_args * args)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 
find_glsl_geometry_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,struct wined3d_shader * shader,const struct gs_compile_args * args)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 
shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs,const char * material)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 
shader_glsl_ffp_vertex_lighting_footer(struct wined3d_string_buffer * buffer,const struct wined3d_ffp_vs_settings * settings,unsigned int idx)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 
shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer * buffer,const struct wined3d_ffp_vs_settings * settings,BOOL legacy_lighting)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. */
shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv * priv,const struct wined3d_ffp_vs_settings * settings,const struct wined3d_gl_info * gl_info)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 
shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buffer * buffer,DWORD argnum,unsigned int stage,DWORD arg)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 
shader_glsl_ffp_fragment_op(struct wined3d_string_buffer * buffer,unsigned int stage,BOOL color,BOOL alpha,DWORD dst,DWORD op,DWORD dw_arg0,DWORD dw_arg1,DWORD dw_arg2)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. */
shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * priv,const struct ffp_frag_settings * settings,const struct wined3d_context * context)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 
shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv * priv,const struct wined3d_gl_info * gl_info,const struct wined3d_ffp_vs_settings * settings)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 
shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv * priv,const struct ffp_frag_settings * args,const struct wined3d_context * context)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 
shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,struct glsl_vs_program * vs,unsigned int vs_c_count)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 
shader_glsl_init_ds_uniform_locations(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,struct glsl_ds_program * ds)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 
shader_glsl_init_gs_uniform_locations(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,struct glsl_gs_program * gs)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 
shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info * gl_info,struct shader_glsl_priv * priv,GLuint program_id,struct glsl_ps_program * ps,unsigned int ps_c_count)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 
shader_glsl_compile_compute_shader(struct shader_glsl_priv * priv,const struct wined3d_context * context,struct wined3d_shader * shader)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 
find_glsl_compute_shader(const struct wined3d_context * context,struct shader_glsl_priv * priv,struct wined3d_shader * shader)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. */
set_glsl_compute_shader_program(const struct wined3d_context * context,const struct wined3d_state * state,struct shader_glsl_priv * priv,struct glsl_context_data * ctx_data)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. */
set_glsl_shader_program(const struct wined3d_context * context,const struct wined3d_state * state,struct shader_glsl_priv * priv,struct glsl_context_data * ctx_data)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 
shader_glsl_precompile(void * shader_priv,struct wined3d_shader * shader)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. */
shader_glsl_select(void * shader_priv,struct wined3d_context * context,const struct wined3d_state * state)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. */
shader_glsl_select_compute(void * shader_priv,struct wined3d_context * context,const struct wined3d_state * state)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. */
shader_glsl_invalidate_current_program(struct wined3d_context * 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. */
shader_glsl_disable(void * shader_priv,struct wined3d_context * context)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 
shader_glsl_invalidate_contexts_program(struct wined3d_device * device,const struct glsl_shader_prog_link * program)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 
shader_glsl_destroy(struct wined3d_shader * shader)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 
glsl_program_key_compare(const void * key,const struct wine_rb_entry * entry)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 
constant_heap_init(struct constant_heap * heap,unsigned int constant_count)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 
constant_heap_free(struct constant_heap * heap)10634 static void constant_heap_free(struct constant_heap *heap)
10635 {
10636     heap_free(heap->entries);
10637 }
10638 
shader_glsl_alloc(struct wined3d_device * device,const struct wined3d_vertex_pipe_ops * vertex_pipe,const struct fragment_pipeline * fragment_pipe)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. */
shader_glsl_free(struct wined3d_device * device)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 
shader_glsl_allocate_context_data(struct wined3d_context * context)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 
shader_glsl_free_context_data(struct wined3d_context * context)10747 static void shader_glsl_free_context_data(struct wined3d_context *context)
10748 {
10749     heap_free(context->shader_backend_data);
10750 }
10751 
shader_glsl_init_context_state(struct wined3d_context * context)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 
shader_glsl_get_shader_model(const struct wined3d_gl_info * gl_info)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 
shader_glsl_get_caps(const struct wined3d_gl_info * gl_info,struct shader_caps * caps)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 
shader_glsl_color_fixup_supported(struct color_fixup_desc fixup)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 
shader_glsl_handle_instruction(const struct wined3d_shader_instruction * ins)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 
shader_glsl_has_ffp_proj_control(void * shader_priv)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 
glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info * gl_info,BOOL enable)11131 static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
11132 
glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info * gl_info,struct wined3d_vertex_caps * caps)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 
glsl_vertex_pipe_vp_get_emul_mask(const struct wined3d_gl_info * gl_info)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 
glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops * shader_backend,void * shader_priv)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 
shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry * entry,void * context)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. */
glsl_vertex_pipe_vp_free(struct wined3d_device * device)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 
glsl_vertex_pipe_nop(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)11203 static void glsl_vertex_pipe_nop(struct wined3d_context *context,
11204         const struct wined3d_state *state, DWORD state_id) {}
11205 
glsl_vertex_pipe_shader(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_vdecl(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_vs(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_hs(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_geometry_shader(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_pixel_shader(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_world(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_vertexblend(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_view(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_projection(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_viewport(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_texmatrix(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_texmatrix_np2(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_material(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_light(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_pointsize(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_pointscale(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pointsprite_core(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_shademode(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_vertex_pipe_clip_plane(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_enable(const struct wined3d_gl_info * gl_info,BOOL enable)11615 static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
11616 {
11617     /* Nothing to do. */
11618 }
11619 
glsl_fragment_pipe_get_caps(const struct wined3d_gl_info * gl_info,struct fragment_caps * caps)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 
glsl_fragment_pipe_get_emul_mask(const struct wined3d_gl_info * gl_info)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 
glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops * shader_backend,void * shader_priv)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 
shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry * entry,void * context)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. */
glsl_fragment_pipe_free(struct wined3d_device * device)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 
glsl_fragment_pipe_shader(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_fogparams(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_fog(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_vdecl(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_vs(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_tex_transform(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_invalidate_constants(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_alpha_test_func(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_core_alpha_test(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_alpha_test(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_core_alpha_test_ref(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_color_key(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_shademode(struct wined3d_context * context,const struct wined3d_state * state,DWORD state_id)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 
glsl_fragment_pipe_alloc_context_data(struct wined3d_context * context)11960 static BOOL glsl_fragment_pipe_alloc_context_data(struct wined3d_context *context)
11961 {
11962     return TRUE;
11963 }
11964 
glsl_fragment_pipe_free_context_data(struct wined3d_context * context)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 };
11981