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 }; 95 96 enum heap_node_op 97 { 98 HEAP_NODE_TRAVERSE_LEFT, 99 HEAP_NODE_TRAVERSE_RIGHT, 100 HEAP_NODE_POP, 101 }; 102 103 struct constant_entry 104 { 105 unsigned int idx; 106 unsigned int version; 107 }; 108 109 struct constant_heap 110 { 111 struct constant_entry *entries; 112 BOOL *contained; 113 unsigned int *positions; 114 unsigned int size; 115 }; 116 117 /* GLSL shader private data */ 118 struct shader_glsl_priv 119 { 120 struct wined3d_string_buffer shader_buffer; 121 struct wined3d_string_buffer_list string_buffers; 122 struct wine_rb_tree program_lookup; 123 struct constant_heap vconst_heap; 124 struct constant_heap pconst_heap; 125 unsigned char *stack; 126 UINT next_constant_version; 127 128 const struct wined3d_vertex_pipe_ops *vertex_pipe; 129 const struct fragment_pipeline *fragment_pipe; 130 struct wine_rb_tree ffp_vertex_shaders; 131 struct wine_rb_tree ffp_fragment_shaders; 132 BOOL ffp_proj_control; 133 BOOL legacy_lighting; 134 }; 135 136 struct glsl_vs_program 137 { 138 struct list shader_entry; 139 GLuint id; 140 GLenum vertex_color_clamp; 141 GLint uniform_f_locations[WINED3D_MAX_VS_CONSTS_F]; 142 GLint uniform_i_locations[WINED3D_MAX_CONSTS_I]; 143 GLint uniform_b_locations[WINED3D_MAX_CONSTS_B]; 144 GLint pos_fixup_location; 145 146 GLint modelview_matrix_location[MAX_VERTEX_INDEX_BLENDS]; 147 GLint normal_matrix_location[MAX_VERTEX_INDEX_BLENDS]; 148 GLint projection_matrix_location; 149 GLint texture_matrix_location[MAX_TEXTURES]; 150 GLint material_ambient_location; 151 GLint material_diffuse_location; 152 GLint material_specular_location; 153 GLint material_emissive_location; 154 GLint material_shininess_location; 155 GLint light_ambient_location; 156 struct 157 { 158 GLint diffuse; 159 GLint specular; 160 GLint ambient; 161 GLint position; 162 GLint direction; 163 GLint range; 164 GLint falloff; 165 GLint c_att; 166 GLint l_att; 167 GLint q_att; 168 GLint cos_htheta; 169 GLint cos_hphi; 170 } light_location[MAX_ACTIVE_LIGHTS]; 171 GLint pointsize_location; 172 GLint pointsize_min_location; 173 GLint pointsize_max_location; 174 GLint pointsize_c_att_location; 175 GLint pointsize_l_att_location; 176 GLint pointsize_q_att_location; 177 GLint clip_planes_location; 178 }; 179 180 struct glsl_hs_program 181 { 182 struct list shader_entry; 183 GLuint id; 184 }; 185 186 struct glsl_ds_program 187 { 188 struct list shader_entry; 189 GLuint id; 190 191 GLint pos_fixup_location; 192 }; 193 194 struct glsl_gs_program 195 { 196 struct list shader_entry; 197 GLuint id; 198 199 GLint pos_fixup_location; 200 }; 201 202 struct glsl_ps_program 203 { 204 struct list shader_entry; 205 GLuint id; 206 GLint uniform_f_locations[WINED3D_MAX_PS_CONSTS_F]; 207 GLint uniform_i_locations[WINED3D_MAX_CONSTS_I]; 208 GLint uniform_b_locations[WINED3D_MAX_CONSTS_B]; 209 GLint bumpenv_mat_location[MAX_TEXTURES]; 210 GLint bumpenv_lum_scale_location[MAX_TEXTURES]; 211 GLint bumpenv_lum_offset_location[MAX_TEXTURES]; 212 GLint tss_constant_location[MAX_TEXTURES]; 213 GLint tex_factor_location; 214 GLint specular_enable_location; 215 GLint fog_color_location; 216 GLint fog_density_location; 217 GLint fog_end_location; 218 GLint fog_scale_location; 219 GLint alpha_test_ref_location; 220 GLint ycorrection_location; 221 GLint np2_fixup_location; 222 GLint color_key_location; 223 const struct ps_np2fixup_info *np2_fixup_info; 224 }; 225 226 struct glsl_cs_program 227 { 228 struct list shader_entry; 229 GLuint id; 230 }; 231 232 /* Struct to maintain data about a linked GLSL program */ 233 struct glsl_shader_prog_link 234 { 235 struct wine_rb_entry program_lookup_entry; 236 struct glsl_vs_program vs; 237 struct glsl_hs_program hs; 238 struct glsl_ds_program ds; 239 struct glsl_gs_program gs; 240 struct glsl_ps_program ps; 241 struct glsl_cs_program cs; 242 GLuint id; 243 DWORD constant_update_mask; 244 unsigned int constant_version; 245 DWORD shader_controlled_clip_distances : 1; 246 DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */ 247 DWORD padding : 23; 248 }; 249 250 struct glsl_program_key 251 { 252 GLuint vs_id; 253 GLuint hs_id; 254 GLuint ds_id; 255 GLuint gs_id; 256 GLuint ps_id; 257 GLuint cs_id; 258 }; 259 260 struct shader_glsl_ctx_priv { 261 const struct vs_compile_args *cur_vs_args; 262 const struct ds_compile_args *cur_ds_args; 263 const struct ps_compile_args *cur_ps_args; 264 struct ps_np2fixup_info *cur_np2fixup_info; 265 struct wined3d_string_buffer_list *string_buffers; 266 }; 267 268 struct glsl_context_data 269 { 270 struct glsl_shader_prog_link *glsl_program; 271 GLenum vertex_color_clamp; 272 BOOL rasterization_disabled; 273 }; 274 275 struct glsl_ps_compiled_shader 276 { 277 struct ps_compile_args args; 278 struct ps_np2fixup_info np2fixup; 279 GLuint id; 280 }; 281 282 struct glsl_vs_compiled_shader 283 { 284 struct vs_compile_args args; 285 GLuint id; 286 }; 287 288 struct glsl_hs_compiled_shader 289 { 290 GLuint id; 291 }; 292 293 struct glsl_ds_compiled_shader 294 { 295 struct ds_compile_args args; 296 GLuint id; 297 }; 298 299 struct glsl_gs_compiled_shader 300 { 301 struct gs_compile_args args; 302 GLuint id; 303 }; 304 305 struct glsl_cs_compiled_shader 306 { 307 GLuint id; 308 }; 309 310 struct glsl_shader_private 311 { 312 union 313 { 314 struct glsl_vs_compiled_shader *vs; 315 struct glsl_hs_compiled_shader *hs; 316 struct glsl_ds_compiled_shader *ds; 317 struct glsl_gs_compiled_shader *gs; 318 struct glsl_ps_compiled_shader *ps; 319 struct glsl_cs_compiled_shader *cs; 320 } gl_shaders; 321 unsigned int num_gl_shaders, shader_array_size; 322 }; 323 324 struct glsl_ffp_vertex_shader 325 { 326 struct wined3d_ffp_vs_desc desc; 327 GLuint id; 328 struct list linked_programs; 329 }; 330 331 struct glsl_ffp_fragment_shader 332 { 333 struct ffp_frag_desc entry; 334 GLuint id; 335 struct list linked_programs; 336 }; 337 338 struct glsl_ffp_destroy_ctx 339 { 340 struct shader_glsl_priv *priv; 341 const struct wined3d_gl_info *gl_info; 342 }; 343 344 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx); 345 346 static const char *debug_gl_shader_type(GLenum type) 347 { 348 switch (type) 349 { 350 #define WINED3D_TO_STR(u) case u: return #u 351 WINED3D_TO_STR(GL_VERTEX_SHADER); 352 WINED3D_TO_STR(GL_TESS_CONTROL_SHADER); 353 WINED3D_TO_STR(GL_TESS_EVALUATION_SHADER); 354 WINED3D_TO_STR(GL_GEOMETRY_SHADER); 355 WINED3D_TO_STR(GL_FRAGMENT_SHADER); 356 WINED3D_TO_STR(GL_COMPUTE_SHADER); 357 #undef WINED3D_TO_STR 358 default: 359 return wine_dbg_sprintf("UNKNOWN(%#x)", type); 360 } 361 } 362 363 static const char *shader_glsl_get_prefix(enum wined3d_shader_type type) 364 { 365 switch (type) 366 { 367 case WINED3D_SHADER_TYPE_VERTEX: 368 return "vs"; 369 370 case WINED3D_SHADER_TYPE_HULL: 371 return "hs"; 372 373 case WINED3D_SHADER_TYPE_DOMAIN: 374 return "ds"; 375 376 case WINED3D_SHADER_TYPE_GEOMETRY: 377 return "gs"; 378 379 case WINED3D_SHADER_TYPE_PIXEL: 380 return "ps"; 381 382 case WINED3D_SHADER_TYPE_COMPUTE: 383 return "cs"; 384 385 default: 386 FIXME("Unhandled shader type %#x.\n", type); 387 return "unknown"; 388 } 389 } 390 391 static unsigned int shader_glsl_get_version(const struct wined3d_gl_info *gl_info) 392 { 393 if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 40)) 394 return 440; 395 else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)) 396 return 150; 397 else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 30)) 398 return 130; 399 else 400 return 120; 401 } 402 403 static void shader_glsl_add_version_declaration(struct wined3d_string_buffer *buffer, 404 const struct wined3d_gl_info *gl_info) 405 { 406 shader_addline(buffer, "#version %u\n", shader_glsl_get_version(gl_info)); 407 } 408 409 static void shader_glsl_append_imm_vec4(struct wined3d_string_buffer *buffer, const float *values) 410 { 411 char str[4][17]; 412 413 wined3d_ftoa(values[0], str[0]); 414 wined3d_ftoa(values[1], str[1]); 415 wined3d_ftoa(values[2], str[2]); 416 wined3d_ftoa(values[3], str[3]); 417 shader_addline(buffer, "vec4(%s, %s, %s, %s)", str[0], str[1], str[2], str[3]); 418 } 419 420 static void shader_glsl_append_imm_ivec(struct wined3d_string_buffer *buffer, 421 const int *values, unsigned int size) 422 { 423 int i; 424 425 if (!size || size > 4) 426 { 427 ERR("Invalid vector size %u.\n", size); 428 return; 429 } 430 431 if (size > 1) 432 shader_addline(buffer, "ivec%u(", size); 433 434 for (i = 0; i < size; ++i) 435 shader_addline(buffer, i ? ", %#x" : "%#x", values[i]); 436 437 if (size > 1) 438 shader_addline(buffer, ")"); 439 } 440 441 static const char *get_info_log_line(const char **ptr) 442 { 443 const char *p, *q; 444 445 p = *ptr; 446 if (!(q = strstr(p, "\n"))) 447 { 448 if (!*p) return NULL; 449 *ptr += strlen(p); 450 return p; 451 } 452 *ptr = q + 1; 453 454 return p; 455 } 456 457 /* Context activation is done by the caller. */ 458 void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program) 459 { 460 int length = 0; 461 char *log; 462 463 if (!WARN_ON(d3d_shader) && !FIXME_ON(d3d_shader)) 464 return; 465 466 if (program) 467 GL_EXTCALL(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length)); 468 else 469 GL_EXTCALL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length)); 470 471 /* A size of 1 is just a null-terminated string, so the log should be bigger than 472 * that if there are errors. */ 473 if (length > 1) 474 { 475 const char *ptr, *line; 476 477 log = heap_alloc(length); 478 /* The info log is supposed to be zero-terminated, but at least some 479 * versions of fglrx don't terminate the string properly. The reported 480 * length does include the terminator, so explicitly set it to zero 481 * here. */ 482 log[length - 1] = 0; 483 if (program) 484 GL_EXTCALL(glGetProgramInfoLog(id, length, NULL, log)); 485 else 486 GL_EXTCALL(glGetShaderInfoLog(id, length, NULL, log)); 487 488 ptr = log; 489 if (gl_info->quirks & WINED3D_QUIRK_INFO_LOG_SPAM) 490 { 491 WARN("Info log received from GLSL shader #%u:\n", id); 492 while ((line = get_info_log_line(&ptr))) WARN(" %.*s", (int)(ptr - line), line); 493 } 494 else 495 { 496 FIXME("Info log received from GLSL shader #%u:\n", id); 497 while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line); 498 } 499 heap_free(log); 500 } 501 } 502 503 /* Context activation is done by the caller. */ 504 static void shader_glsl_compile(const struct wined3d_gl_info *gl_info, GLuint shader, const char *src) 505 { 506 const char *ptr, *line; 507 508 TRACE("Compiling shader object %u.\n", shader); 509 510 if (TRACE_ON(d3d_shader)) 511 { 512 ptr = src; 513 while ((line = get_info_log_line(&ptr))) TRACE_(d3d_shader)(" %.*s", (int)(ptr - line), line); 514 } 515 516 GL_EXTCALL(glShaderSource(shader, 1, &src, NULL)); 517 checkGLcall("glShaderSource"); 518 GL_EXTCALL(glCompileShader(shader)); 519 checkGLcall("glCompileShader"); 520 print_glsl_info_log(gl_info, shader, FALSE); 521 } 522 523 /* Context activation is done by the caller. */ 524 static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLuint program) 525 { 526 GLint i, shader_count, source_size = -1; 527 GLuint *shaders; 528 char *source = NULL; 529 530 GL_EXTCALL(glGetProgramiv(program, GL_ATTACHED_SHADERS, &shader_count)); 531 if (!(shaders = heap_calloc(shader_count, sizeof(*shaders)))) 532 { 533 ERR("Failed to allocate shader array memory.\n"); 534 return; 535 } 536 537 GL_EXTCALL(glGetAttachedShaders(program, shader_count, NULL, shaders)); 538 for (i = 0; i < shader_count; ++i) 539 { 540 const char *ptr, *line; 541 GLint tmp; 542 543 GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &tmp)); 544 545 if (source_size < tmp) 546 { 547 heap_free(source); 548 549 if (!(source = heap_alloc_zero(tmp))) 550 { 551 ERR("Failed to allocate %d bytes for shader source.\n", tmp); 552 heap_free(shaders); 553 return; 554 } 555 source_size = tmp; 556 } 557 558 FIXME("Shader %u:\n", shaders[i]); 559 GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_TYPE, &tmp)); 560 FIXME(" GL_SHADER_TYPE: %s.\n", debug_gl_shader_type(tmp)); 561 GL_EXTCALL(glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &tmp)); 562 FIXME(" GL_COMPILE_STATUS: %d.\n", tmp); 563 FIXME("\n"); 564 565 ptr = source; 566 GL_EXTCALL(glGetShaderSource(shaders[i], source_size, NULL, source)); 567 while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line); 568 FIXME("\n"); 569 } 570 571 heap_free(source); 572 heap_free(shaders); 573 } 574 575 /* Context activation is done by the caller. */ 576 void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program) 577 { 578 GLint tmp; 579 580 if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) 581 return; 582 583 GL_EXTCALL(glGetProgramiv(program, GL_LINK_STATUS, &tmp)); 584 if (!tmp) 585 { 586 FIXME("Program %u link status invalid.\n", program); 587 shader_glsl_dump_program_source(gl_info, program); 588 } 589 590 print_glsl_info_log(gl_info, program, TRUE); 591 } 592 593 static BOOL shader_glsl_use_layout_qualifier(const struct wined3d_gl_info *gl_info) 594 { 595 /* Layout qualifiers were introduced in GLSL 1.40. The Nvidia Legacy GPU 596 * driver (series 340.xx) doesn't parse layout qualifiers in older GLSL 597 * versions. */ 598 return shader_glsl_get_version(gl_info) >= 140; 599 } 600 601 static BOOL shader_glsl_use_layout_binding_qualifier(const struct wined3d_gl_info *gl_info) 602 { 603 return gl_info->supported[ARB_SHADING_LANGUAGE_420PACK] && shader_glsl_use_layout_qualifier(gl_info); 604 } 605 606 static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info, 607 struct shader_glsl_priv *priv, GLuint program_id, 608 const struct wined3d_shader_reg_maps *reg_maps) 609 { 610 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 611 struct wined3d_string_buffer *name; 612 unsigned int i, base, count; 613 GLuint block_idx; 614 615 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 616 return; 617 618 name = string_buffer_get(&priv->string_buffers); 619 wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, reg_maps->shader_version.type, &base, &count); 620 for (i = 0; i < count; ++i) 621 { 622 if (!reg_maps->cb_sizes[i]) 623 continue; 624 625 string_buffer_sprintf(name, "block_%s_cb%u", prefix, i); 626 block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name->buffer)); 627 GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i)); 628 } 629 checkGLcall("glUniformBlockBinding"); 630 string_buffer_release(&priv->string_buffers, name); 631 } 632 633 /* Context activation is done by the caller. */ 634 static void shader_glsl_load_samplers_range(const struct wined3d_gl_info *gl_info, 635 struct shader_glsl_priv *priv, GLuint program_id, const char *prefix, 636 unsigned int base, unsigned int count, const DWORD *tex_unit_map) 637 { 638 struct wined3d_string_buffer *sampler_name = string_buffer_get(&priv->string_buffers); 639 unsigned int i, mapped_unit; 640 GLint name_loc; 641 642 for (i = 0; i < count; ++i) 643 { 644 string_buffer_sprintf(sampler_name, "%s_sampler%u", prefix, i); 645 name_loc = GL_EXTCALL(glGetUniformLocation(program_id, sampler_name->buffer)); 646 if (name_loc == -1) 647 continue; 648 649 mapped_unit = tex_unit_map ? tex_unit_map[base + i] : base + i; 650 if (mapped_unit == WINED3D_UNMAPPED_STAGE || mapped_unit >= gl_info->limits.combined_samplers) 651 { 652 ERR("Trying to load sampler %s on unsupported unit %u.\n", sampler_name->buffer, mapped_unit); 653 continue; 654 } 655 656 TRACE("Loading sampler %s on unit %u.\n", sampler_name->buffer, mapped_unit); 657 GL_EXTCALL(glUniform1i(name_loc, mapped_unit)); 658 } 659 checkGLcall("Load sampler bindings"); 660 string_buffer_release(&priv->string_buffers, sampler_name); 661 } 662 663 static unsigned int shader_glsl_map_tex_unit(const struct wined3d_context *context, 664 const struct wined3d_shader_version *shader_version, unsigned int sampler_idx) 665 { 666 const DWORD *tex_unit_map; 667 unsigned int base, count; 668 669 tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count); 670 if (sampler_idx >= count) 671 return WINED3D_UNMAPPED_STAGE; 672 if (!tex_unit_map) 673 return base + sampler_idx; 674 return tex_unit_map[base + sampler_idx]; 675 } 676 677 static void shader_glsl_append_sampler_binding_qualifier(struct wined3d_string_buffer *buffer, 678 const struct wined3d_context *context, const struct wined3d_shader_version *shader_version, 679 unsigned int sampler_idx) 680 { 681 unsigned int mapped_unit = shader_glsl_map_tex_unit(context, shader_version, sampler_idx); 682 if (mapped_unit != WINED3D_UNMAPPED_STAGE) 683 shader_addline(buffer, "layout(binding = %u)\n", mapped_unit); 684 else 685 ERR("Unmapped sampler %u.\n", sampler_idx); 686 } 687 688 /* Context activation is done by the caller. */ 689 static void shader_glsl_load_samplers(const struct wined3d_context *context, 690 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) 691 { 692 const struct wined3d_gl_info *gl_info = context->gl_info; 693 const struct wined3d_shader_version *shader_version; 694 const DWORD *tex_unit_map; 695 unsigned int base, count; 696 const char *prefix; 697 698 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 699 return; 700 701 shader_version = reg_maps ? ®_maps->shader_version : NULL; 702 prefix = shader_glsl_get_prefix(shader_version ? shader_version->type : WINED3D_SHADER_TYPE_PIXEL); 703 tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count); 704 shader_glsl_load_samplers_range(gl_info, priv, program_id, prefix, base, count, tex_unit_map); 705 } 706 707 static void shader_glsl_load_icb(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, 708 GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) 709 { 710 const struct wined3d_shader_immediate_constant_buffer *icb = reg_maps->icb; 711 712 if (icb) 713 { 714 struct wined3d_string_buffer *icb_name = string_buffer_get(&priv->string_buffers); 715 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 716 GLint icb_location; 717 718 string_buffer_sprintf(icb_name, "%s_icb", prefix); 719 icb_location = GL_EXTCALL(glGetUniformLocation(program_id, icb_name->buffer)); 720 GL_EXTCALL(glUniform4fv(icb_location, icb->vec4_count, (const GLfloat *)icb->data)); 721 checkGLcall("Load immediate constant buffer"); 722 723 string_buffer_release(&priv->string_buffers, icb_name); 724 } 725 } 726 727 /* Context activation is done by the caller. */ 728 static void shader_glsl_load_images(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, 729 GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) 730 { 731 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 732 struct wined3d_string_buffer *name; 733 GLint location; 734 unsigned int i; 735 736 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 737 return; 738 739 name = string_buffer_get(&priv->string_buffers); 740 for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i) 741 { 742 if (!reg_maps->uav_resource_info[i].type) 743 continue; 744 745 string_buffer_sprintf(name, "%s_image%u", prefix, i); 746 location = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 747 if (location == -1) 748 continue; 749 750 TRACE("Loading image %s on unit %u.\n", name->buffer, i); 751 GL_EXTCALL(glUniform1i(location, i)); 752 } 753 checkGLcall("Load image bindings"); 754 string_buffer_release(&priv->string_buffers, name); 755 } 756 757 /* Context activation is done by the caller. */ 758 static void shader_glsl_load_program_resources(const struct wined3d_context *context, 759 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader) 760 { 761 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 762 763 shader_glsl_init_uniform_block_bindings(context->gl_info, priv, program_id, reg_maps); 764 shader_glsl_load_icb(context->gl_info, priv, program_id, reg_maps); 765 /* Texture unit mapping is set up to be the same each time the shader 766 * program is used so we can hardcode the sampler uniform values. */ 767 shader_glsl_load_samplers(context, priv, program_id, reg_maps); 768 } 769 770 static void append_transform_feedback_varying(const char **varyings, unsigned int *varying_count, 771 char **strings, unsigned int *strings_length, struct wined3d_string_buffer *buffer) 772 { 773 if (varyings && *strings) 774 { 775 char *ptr = *strings; 776 777 varyings[*varying_count] = ptr; 778 779 memcpy(ptr, buffer->buffer, buffer->content_size + 1); 780 ptr += buffer->content_size + 1; 781 782 *strings = ptr; 783 } 784 785 *strings_length += buffer->content_size + 1; 786 ++(*varying_count); 787 } 788 789 static void append_transform_feedback_skip_components(const char **varyings, 790 unsigned int *varying_count, char **strings, unsigned int *strings_length, 791 struct wined3d_string_buffer *buffer, unsigned int component_count) 792 { 793 unsigned int j; 794 795 for (j = 0; j < component_count / 4; ++j) 796 { 797 string_buffer_sprintf(buffer, "gl_SkipComponents4"); 798 append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer); 799 } 800 if (component_count % 4) 801 { 802 string_buffer_sprintf(buffer, "gl_SkipComponents%u", component_count % 4); 803 append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer); 804 } 805 } 806 807 static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc, 808 struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count, 809 char *strings, unsigned int *strings_length, GLenum buffer_mode) 810 { 811 unsigned int i, buffer_idx, count, length, highest_output_slot, stride; 812 BOOL have_varyings_to_record = FALSE; 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 have_varyings_to_record = TRUE; 864 } 865 866 if (buffer_idx < so_desc->buffer_stride_count 867 && stride < so_desc->buffer_strides[buffer_idx] / 4) 868 { 869 unsigned int component_count = so_desc->buffer_strides[buffer_idx] / 4 - stride; 870 append_transform_feedback_skip_components(varyings, &count, 871 &strings, &length, buffer, component_count); 872 } 873 874 if (highest_output_slot <= buffer_idx) 875 break; 876 877 if (buffer_mode == GL_INTERLEAVED_ATTRIBS) 878 { 879 string_buffer_sprintf(buffer, "gl_NextBuffer"); 880 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer); 881 } 882 } 883 884 if (varying_count) 885 *varying_count = count; 886 if (strings_length) 887 *strings_length = length; 888 889 return have_varyings_to_record; 890 } 891 892 static void shader_glsl_init_transform_feedback(const struct wined3d_context *context, 893 struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader) 894 { 895 const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc; 896 const struct wined3d_gl_info *gl_info = context->gl_info; 897 struct wined3d_string_buffer *buffer; 898 unsigned int i, count, length; 899 const char **varyings; 900 char *strings; 901 GLenum mode; 902 903 if (!so_desc->element_count) 904 return; 905 906 if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3]) 907 { 908 mode = GL_INTERLEAVED_ATTRIBS; 909 } 910 else 911 { 912 unsigned int element_count[WINED3D_MAX_STREAM_OUTPUT_BUFFERS] = {0}; 913 914 for (i = 0; i < so_desc->element_count; ++i) 915 { 916 if (so_desc->elements[i].register_idx == WINED3D_STREAM_OUTPUT_GAP) 917 { 918 FIXME("ARB_transform_feedback3 is needed for stream output gaps.\n"); 919 return; 920 } 921 ++element_count[so_desc->elements[i].output_slot]; 922 } 923 924 if (element_count[0] == so_desc->element_count) 925 { 926 mode = GL_INTERLEAVED_ATTRIBS; 927 } 928 else 929 { 930 mode = GL_SEPARATE_ATTRIBS; 931 for (i = 0; i < ARRAY_SIZE(element_count); ++i) 932 { 933 if (element_count[i] != 1) 934 break; 935 } 936 for (; i < ARRAY_SIZE(element_count); ++i) 937 { 938 if (element_count[i]) 939 { 940 FIXME("Only single element per buffer is allowed in separate mode.\n"); 941 return; 942 } 943 } 944 } 945 } 946 947 buffer = string_buffer_get(&priv->string_buffers); 948 949 if (!shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode)) 950 { 951 FIXME("No varyings to record, disabling transform feedback.\n"); 952 shader->u.gs.so_desc.element_count = 0; 953 string_buffer_release(&priv->string_buffers, buffer); 954 return; 955 } 956 957 if (!(varyings = heap_calloc(count, sizeof(*varyings)))) 958 { 959 ERR("Out of memory.\n"); 960 string_buffer_release(&priv->string_buffers, buffer); 961 return; 962 } 963 if (!(strings = heap_calloc(length, sizeof(*strings)))) 964 { 965 ERR("Out of memory.\n"); 966 heap_free(varyings); 967 string_buffer_release(&priv->string_buffers, buffer); 968 return; 969 } 970 971 shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL, mode); 972 GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, mode)); 973 checkGLcall("glTransformFeedbackVaryings"); 974 975 heap_free(varyings); 976 heap_free(strings); 977 string_buffer_release(&priv->string_buffers, buffer); 978 } 979 980 /* Context activation is done by the caller. */ 981 static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants, 982 const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) 983 { 984 unsigned int start = ~0U, end = 0; 985 int stack_idx = 0; 986 unsigned int heap_idx = 1; 987 unsigned int idx; 988 989 if (heap->entries[heap_idx].version <= version) return; 990 991 idx = heap->entries[heap_idx].idx; 992 if (constant_locations[idx] != -1) 993 start = end = idx; 994 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 995 996 while (stack_idx >= 0) 997 { 998 /* Note that we fall through to the next case statement. */ 999 switch(stack[stack_idx]) 1000 { 1001 case HEAP_NODE_TRAVERSE_LEFT: 1002 { 1003 unsigned int left_idx = heap_idx << 1; 1004 if (left_idx < heap->size && heap->entries[left_idx].version > version) 1005 { 1006 heap_idx = left_idx; 1007 idx = heap->entries[heap_idx].idx; 1008 if (constant_locations[idx] != -1) 1009 { 1010 if (start > idx) 1011 start = idx; 1012 if (end < idx) 1013 end = idx; 1014 } 1015 1016 stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; 1017 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1018 break; 1019 } 1020 } 1021 1022 case HEAP_NODE_TRAVERSE_RIGHT: 1023 { 1024 unsigned int right_idx = (heap_idx << 1) + 1; 1025 if (right_idx < heap->size && heap->entries[right_idx].version > version) 1026 { 1027 heap_idx = right_idx; 1028 idx = heap->entries[heap_idx].idx; 1029 if (constant_locations[idx] != -1) 1030 { 1031 if (start > idx) 1032 start = idx; 1033 if (end < idx) 1034 end = idx; 1035 } 1036 1037 stack[stack_idx++] = HEAP_NODE_POP; 1038 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1039 break; 1040 } 1041 } 1042 1043 case HEAP_NODE_POP: 1044 heap_idx >>= 1; 1045 --stack_idx; 1046 break; 1047 } 1048 } 1049 if (start <= end) 1050 GL_EXTCALL(glUniform4fv(constant_locations[start], end - start + 1, &constants[start].x)); 1051 checkGLcall("walk_constant_heap()"); 1052 } 1053 1054 /* Context activation is done by the caller. */ 1055 static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info, 1056 GLint location, const struct wined3d_vec4 *data) 1057 { 1058 GLfloat clamped_constant[4]; 1059 1060 if (location == -1) return; 1061 1062 clamped_constant[0] = data->x < -1.0f ? -1.0f : data->x > 1.0f ? 1.0f : data->x; 1063 clamped_constant[1] = data->y < -1.0f ? -1.0f : data->y > 1.0f ? 1.0f : data->y; 1064 clamped_constant[2] = data->z < -1.0f ? -1.0f : data->z > 1.0f ? 1.0f : data->z; 1065 clamped_constant[3] = data->w < -1.0f ? -1.0f : data->w > 1.0f ? 1.0f : data->w; 1066 1067 GL_EXTCALL(glUniform4fv(location, 1, clamped_constant)); 1068 } 1069 1070 /* Context activation is done by the caller. */ 1071 static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info, 1072 const struct wined3d_vec4 *constants, const GLint *constant_locations, 1073 const struct constant_heap *heap, unsigned char *stack, DWORD version) 1074 { 1075 int stack_idx = 0; 1076 unsigned int heap_idx = 1; 1077 unsigned int idx; 1078 1079 if (heap->entries[heap_idx].version <= version) return; 1080 1081 idx = heap->entries[heap_idx].idx; 1082 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]); 1083 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1084 1085 while (stack_idx >= 0) 1086 { 1087 /* Note that we fall through to the next case statement. */ 1088 switch(stack[stack_idx]) 1089 { 1090 case HEAP_NODE_TRAVERSE_LEFT: 1091 { 1092 unsigned int left_idx = heap_idx << 1; 1093 if (left_idx < heap->size && heap->entries[left_idx].version > version) 1094 { 1095 heap_idx = left_idx; 1096 idx = heap->entries[heap_idx].idx; 1097 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]); 1098 1099 stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; 1100 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1101 break; 1102 } 1103 } 1104 1105 case HEAP_NODE_TRAVERSE_RIGHT: 1106 { 1107 unsigned int right_idx = (heap_idx << 1) + 1; 1108 if (right_idx < heap->size && heap->entries[right_idx].version > version) 1109 { 1110 heap_idx = right_idx; 1111 idx = heap->entries[heap_idx].idx; 1112 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]); 1113 1114 stack[stack_idx++] = HEAP_NODE_POP; 1115 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1116 break; 1117 } 1118 } 1119 1120 case HEAP_NODE_POP: 1121 heap_idx >>= 1; 1122 --stack_idx; 1123 break; 1124 } 1125 } 1126 checkGLcall("walk_constant_heap_clamped()"); 1127 } 1128 1129 /* Context activation is done by the caller. */ 1130 static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, 1131 const struct wined3d_vec4 *constants, const GLint *constant_locations, const struct constant_heap *heap, 1132 unsigned char *stack, unsigned int version) 1133 { 1134 const struct wined3d_shader_lconst *lconst; 1135 1136 /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ 1137 if (shader->reg_maps.shader_version.major == 1 1138 && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL) 1139 walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version); 1140 else 1141 walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version); 1142 1143 if (!shader->load_local_constsF) 1144 { 1145 TRACE("No need to load local float constants for this shader.\n"); 1146 return; 1147 } 1148 1149 /* Immediate constants are clamped to [-1;1] at shader creation time if needed */ 1150 LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry) 1151 { 1152 GL_EXTCALL(glUniform4fv(constant_locations[lconst->idx], 1, (const GLfloat *)lconst->value)); 1153 } 1154 checkGLcall("glUniform4fv()"); 1155 } 1156 1157 /* Context activation is done by the caller. */ 1158 static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, 1159 const struct wined3d_ivec4 *constants, const GLint locations[WINED3D_MAX_CONSTS_I], WORD constants_set) 1160 { 1161 unsigned int i; 1162 struct list* ptr; 1163 1164 for (i = 0; constants_set; constants_set >>= 1, ++i) 1165 { 1166 if (!(constants_set & 1)) continue; 1167 1168 /* We found this uniform name in the program - go ahead and send the data */ 1169 GL_EXTCALL(glUniform4iv(locations[i], 1, &constants[i].x)); 1170 } 1171 1172 /* Load immediate constants */ 1173 ptr = list_head(&shader->constantsI); 1174 while (ptr) 1175 { 1176 const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry); 1177 unsigned int idx = lconst->idx; 1178 const GLint *values = (const GLint *)lconst->value; 1179 1180 /* We found this uniform name in the program - go ahead and send the data */ 1181 GL_EXTCALL(glUniform4iv(locations[idx], 1, values)); 1182 ptr = list_next(&shader->constantsI, ptr); 1183 } 1184 checkGLcall("glUniform4iv()"); 1185 } 1186 1187 /* Context activation is done by the caller. */ 1188 static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, 1189 const GLint locations[WINED3D_MAX_CONSTS_B], const BOOL *constants, WORD constants_set) 1190 { 1191 unsigned int i; 1192 struct list* ptr; 1193 1194 for (i = 0; constants_set; constants_set >>= 1, ++i) 1195 { 1196 if (!(constants_set & 1)) continue; 1197 1198 GL_EXTCALL(glUniform1iv(locations[i], 1, &constants[i])); 1199 } 1200 1201 /* Load immediate constants */ 1202 ptr = list_head(&shader->constantsB); 1203 while (ptr) 1204 { 1205 const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry); 1206 unsigned int idx = lconst->idx; 1207 const GLint *values = (const GLint *)lconst->value; 1208 1209 GL_EXTCALL(glUniform1iv(locations[idx], 1, values)); 1210 ptr = list_next(&shader->constantsB, ptr); 1211 } 1212 checkGLcall("glUniform1iv()"); 1213 } 1214 1215 static void reset_program_constant_version(struct wine_rb_entry *entry, void *context) 1216 { 1217 WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0; 1218 } 1219 1220 /* Context activation is done by the caller (state handler). */ 1221 static void shader_glsl_load_np2fixup_constants(const struct glsl_ps_program *ps, 1222 const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) 1223 { 1224 struct 1225 { 1226 float sx, sy; 1227 } 1228 np2fixup_constants[MAX_FRAGMENT_SAMPLERS]; 1229 UINT fixup = ps->np2_fixup_info->active; 1230 UINT i; 1231 1232 for (i = 0; fixup; fixup >>= 1, ++i) 1233 { 1234 const struct wined3d_texture *tex = state->textures[i]; 1235 unsigned char idx = ps->np2_fixup_info->idx[i]; 1236 1237 if (!tex) 1238 { 1239 ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n"); 1240 continue; 1241 } 1242 1243 np2fixup_constants[idx].sx = tex->pow2_matrix[0]; 1244 np2fixup_constants[idx].sy = tex->pow2_matrix[5]; 1245 } 1246 1247 GL_EXTCALL(glUniform4fv(ps->np2_fixup_location, ps->np2_fixup_info->num_consts, &np2fixup_constants[0].sx)); 1248 } 1249 1250 static void shader_glsl_ffp_vertex_texmatrix_uniform(const struct wined3d_context *context, 1251 const struct wined3d_state *state, unsigned int tex, struct glsl_shader_prog_link *prog) 1252 { 1253 const struct wined3d_gl_info *gl_info = context->gl_info; 1254 struct wined3d_matrix mat; 1255 1256 if (tex >= MAX_TEXTURES) 1257 return; 1258 if (prog->vs.texture_matrix_location[tex] == -1) 1259 return; 1260 1261 get_texture_matrix(context, state, tex, &mat); 1262 GL_EXTCALL(glUniformMatrix4fv(prog->vs.texture_matrix_location[tex], 1, FALSE, &mat._11)); 1263 checkGLcall("glUniformMatrix4fv"); 1264 } 1265 1266 static void shader_glsl_ffp_vertex_material_uniform(const struct wined3d_context *context, 1267 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1268 { 1269 const struct wined3d_gl_info *gl_info = context->gl_info; 1270 1271 if (state->render_states[WINED3D_RS_SPECULARENABLE]) 1272 { 1273 GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, &state->material.specular.r)); 1274 GL_EXTCALL(glUniform1f(prog->vs.material_shininess_location, state->material.power)); 1275 } 1276 else 1277 { 1278 static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; 1279 1280 GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, black)); 1281 } 1282 GL_EXTCALL(glUniform4fv(prog->vs.material_ambient_location, 1, &state->material.ambient.r)); 1283 GL_EXTCALL(glUniform4fv(prog->vs.material_diffuse_location, 1, &state->material.diffuse.r)); 1284 GL_EXTCALL(glUniform4fv(prog->vs.material_emissive_location, 1, &state->material.emissive.r)); 1285 checkGLcall("setting FFP material uniforms"); 1286 } 1287 1288 static void shader_glsl_ffp_vertex_lightambient_uniform(const struct wined3d_context *context, 1289 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1290 { 1291 const struct wined3d_gl_info *gl_info = context->gl_info; 1292 struct wined3d_color color; 1293 1294 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_AMBIENT]); 1295 GL_EXTCALL(glUniform3fv(prog->vs.light_ambient_location, 1, &color.r)); 1296 checkGLcall("glUniform3fv"); 1297 } 1298 1299 static void multiply_vector_matrix(struct wined3d_vec4 *dest, const struct wined3d_vec4 *src1, 1300 const struct wined3d_matrix *src2) 1301 { 1302 struct wined3d_vec4 temp; 1303 1304 temp.x = (src1->x * src2->_11) + (src1->y * src2->_21) + (src1->z * src2->_31) + (src1->w * src2->_41); 1305 temp.y = (src1->x * src2->_12) + (src1->y * src2->_22) + (src1->z * src2->_32) + (src1->w * src2->_42); 1306 temp.z = (src1->x * src2->_13) + (src1->y * src2->_23) + (src1->z * src2->_33) + (src1->w * src2->_43); 1307 temp.w = (src1->x * src2->_14) + (src1->y * src2->_24) + (src1->z * src2->_34) + (src1->w * src2->_44); 1308 1309 *dest = temp; 1310 } 1311 1312 static void shader_glsl_ffp_vertex_light_uniform(const struct wined3d_context *context, 1313 const struct wined3d_state *state, unsigned int light, const struct wined3d_light_info *light_info, 1314 struct glsl_shader_prog_link *prog) 1315 { 1316 const struct wined3d_matrix *view = &state->transforms[WINED3D_TS_VIEW]; 1317 const struct wined3d_gl_info *gl_info = context->gl_info; 1318 struct wined3d_vec4 vec4; 1319 1320 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].diffuse, 1, &light_info->OriginalParms.diffuse.r)); 1321 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].specular, 1, &light_info->OriginalParms.specular.r)); 1322 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].ambient, 1, &light_info->OriginalParms.ambient.r)); 1323 1324 switch (light_info->OriginalParms.type) 1325 { 1326 case WINED3D_LIGHT_POINT: 1327 multiply_vector_matrix(&vec4, &light_info->position, view); 1328 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x)); 1329 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range)); 1330 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0)); 1331 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1)); 1332 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2)); 1333 break; 1334 1335 case WINED3D_LIGHT_SPOT: 1336 multiply_vector_matrix(&vec4, &light_info->position, view); 1337 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x)); 1338 1339 multiply_vector_matrix(&vec4, &light_info->direction, view); 1340 GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x)); 1341 1342 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range)); 1343 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].falloff, light_info->OriginalParms.falloff)); 1344 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0)); 1345 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1)); 1346 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2)); 1347 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_htheta, cosf(light_info->OriginalParms.theta / 2.0f))); 1348 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_hphi, cosf(light_info->OriginalParms.phi / 2.0f))); 1349 break; 1350 1351 case WINED3D_LIGHT_DIRECTIONAL: 1352 multiply_vector_matrix(&vec4, &light_info->direction, view); 1353 GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x)); 1354 break; 1355 1356 case WINED3D_LIGHT_PARALLELPOINT: 1357 multiply_vector_matrix(&vec4, &light_info->position, view); 1358 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x)); 1359 break; 1360 1361 default: 1362 FIXME("Unrecognized light type %#x.\n", light_info->OriginalParms.type); 1363 } 1364 checkGLcall("setting FFP lights uniforms"); 1365 } 1366 1367 static void shader_glsl_pointsize_uniform(const struct wined3d_context *context, 1368 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1369 { 1370 const struct wined3d_gl_info *gl_info = context->gl_info; 1371 float min, max; 1372 float size, att[3]; 1373 1374 get_pointsize_minmax(context, state, &min, &max); 1375 1376 GL_EXTCALL(glUniform1f(prog->vs.pointsize_min_location, min)); 1377 checkGLcall("glUniform1f"); 1378 GL_EXTCALL(glUniform1f(prog->vs.pointsize_max_location, max)); 1379 checkGLcall("glUniform1f"); 1380 1381 get_pointsize(context, state, &size, att); 1382 1383 GL_EXTCALL(glUniform1f(prog->vs.pointsize_location, size)); 1384 checkGLcall("glUniform1f"); 1385 GL_EXTCALL(glUniform1f(prog->vs.pointsize_c_att_location, att[0])); 1386 checkGLcall("glUniform1f"); 1387 GL_EXTCALL(glUniform1f(prog->vs.pointsize_l_att_location, att[1])); 1388 checkGLcall("glUniform1f"); 1389 GL_EXTCALL(glUniform1f(prog->vs.pointsize_q_att_location, att[2])); 1390 checkGLcall("glUniform1f"); 1391 } 1392 1393 static void shader_glsl_load_fog_uniform(const struct wined3d_context *context, 1394 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1395 { 1396 const struct wined3d_gl_info *gl_info = context->gl_info; 1397 struct wined3d_color color; 1398 float start, end, scale; 1399 union 1400 { 1401 DWORD d; 1402 float f; 1403 } tmpvalue; 1404 1405 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_FOGCOLOR]); 1406 GL_EXTCALL(glUniform4fv(prog->ps.fog_color_location, 1, &color.r)); 1407 tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY]; 1408 GL_EXTCALL(glUniform1f(prog->ps.fog_density_location, tmpvalue.f)); 1409 get_fog_start_end(context, state, &start, &end); 1410 scale = 1.0f / (end - start); 1411 GL_EXTCALL(glUniform1f(prog->ps.fog_end_location, end)); 1412 GL_EXTCALL(glUniform1f(prog->ps.fog_scale_location, scale)); 1413 checkGLcall("fog emulation uniforms"); 1414 } 1415 1416 static void shader_glsl_clip_plane_uniform(const struct wined3d_context *context, 1417 const struct wined3d_state *state, unsigned int index, struct glsl_shader_prog_link *prog) 1418 { 1419 const struct wined3d_gl_info *gl_info = context->gl_info; 1420 struct wined3d_matrix matrix; 1421 struct wined3d_vec4 plane; 1422 1423 plane = state->clip_planes[index]; 1424 1425 /* Clip planes are affected by the view transform in d3d for FFP draws. */ 1426 if (!use_vs(state)) 1427 { 1428 invert_matrix(&matrix, &state->transforms[WINED3D_TS_VIEW]); 1429 transpose_matrix(&matrix, &matrix); 1430 multiply_vector_matrix(&plane, &plane, &matrix); 1431 } 1432 1433 GL_EXTCALL(glUniform4fv(prog->vs.clip_planes_location + index, 1, &plane.x)); 1434 } 1435 1436 /* Context activation is done by the caller (state handler). */ 1437 static void shader_glsl_load_color_key_constant(const struct glsl_ps_program *ps, 1438 const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) 1439 { 1440 struct wined3d_color float_key[2]; 1441 const struct wined3d_texture *texture = state->textures[0]; 1442 1443 wined3d_format_get_float_color_key(texture->resource.format, &texture->async.src_blt_color_key, float_key); 1444 GL_EXTCALL(glUniform4fv(ps->color_key_location, 2, &float_key[0].r)); 1445 } 1446 1447 /* Context activation is done by the caller. */ 1448 static void get_normal_matrix(struct wined3d_context *context, struct wined3d_matrix *mat, float *normal) 1449 { 1450 int i, j; 1451 1452 if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING) 1453 invert_matrix_3d(mat, mat); 1454 else 1455 invert_matrix(mat, mat); 1456 /* Tests show that singular modelview matrices are used unchanged as normal 1457 * matrices on D3D3 and older. There seems to be no clearly consistent 1458 * behavior on newer D3D versions so always follow older ddraw behavior. */ 1459 for (i = 0; i < 3; ++i) 1460 for (j = 0; j < 3; ++j) 1461 normal[i * 3 + j] = (&mat->_11)[j * 4 + i]; 1462 } 1463 1464 /* Context activation is done by the caller (state handler). */ 1465 static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context, 1466 const struct wined3d_state *state) 1467 { 1468 const struct glsl_context_data *ctx_data = context->shader_backend_data; 1469 const struct wined3d_shader *vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 1470 const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; 1471 const struct wined3d_gl_info *gl_info = context->gl_info; 1472 struct shader_glsl_priv *priv = shader_priv; 1473 float position_fixup[4 * WINED3D_MAX_VIEWPORTS]; 1474 float normal[3 * 3]; 1475 DWORD update_mask; 1476 1477 struct glsl_shader_prog_link *prog = ctx_data->glsl_program; 1478 UINT constant_version; 1479 int i; 1480 1481 if (!prog) { 1482 /* No GLSL program set - nothing to do. */ 1483 return; 1484 } 1485 constant_version = prog->constant_version; 1486 update_mask = context->constant_update_mask & prog->constant_update_mask; 1487 1488 if (update_mask & WINED3D_SHADER_CONST_VS_F) 1489 shader_glsl_load_constants_f(vshader, gl_info, state->vs_consts_f, 1490 prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version); 1491 1492 if (update_mask & WINED3D_SHADER_CONST_VS_I) 1493 shader_glsl_load_constants_i(vshader, gl_info, state->vs_consts_i, 1494 prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants); 1495 1496 if (update_mask & WINED3D_SHADER_CONST_VS_B) 1497 shader_glsl_load_constantsB(vshader, gl_info, prog->vs.uniform_b_locations, state->vs_consts_b, 1498 vshader->reg_maps.boolean_constants); 1499 1500 if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES) 1501 { 1502 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 1503 shader_glsl_clip_plane_uniform(context, state, i, prog); 1504 } 1505 1506 if (update_mask & WINED3D_SHADER_CONST_VS_POINTSIZE) 1507 shader_glsl_pointsize_uniform(context, state, prog); 1508 1509 if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP) 1510 { 1511 unsigned int fixup_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ? 1512 max(state->viewport_count, 1) : 1; 1513 shader_get_position_fixup(context, state, fixup_count, position_fixup); 1514 if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) 1515 GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, fixup_count, position_fixup)); 1516 else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) 1517 GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup)); 1518 else 1519 GL_EXTCALL(glUniform4fv(prog->vs.pos_fixup_location, 1, position_fixup)); 1520 checkGLcall("glUniform4fv"); 1521 } 1522 1523 if (update_mask & WINED3D_SHADER_CONST_FFP_MODELVIEW) 1524 { 1525 struct wined3d_matrix mat; 1526 1527 get_modelview_matrix(context, state, 0, &mat); 1528 GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[0], 1, FALSE, &mat._11)); 1529 checkGLcall("glUniformMatrix4fv"); 1530 1531 get_normal_matrix(context, &mat, normal); 1532 GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[0], 1, FALSE, normal)); 1533 checkGLcall("glUniformMatrix3fv"); 1534 } 1535 1536 if (update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND) 1537 { 1538 struct wined3d_matrix mat; 1539 1540 for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i) 1541 { 1542 if (prog->vs.modelview_matrix_location[i] == -1) 1543 break; 1544 if (!(update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i))) 1545 continue; 1546 1547 get_modelview_matrix(context, state, i, &mat); 1548 GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11)); 1549 checkGLcall("glUniformMatrix4fv"); 1550 1551 get_normal_matrix(context, &mat, normal); 1552 GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[i], 1, FALSE, normal)); 1553 checkGLcall("glUniformMatrix3fv"); 1554 } 1555 } 1556 1557 if (update_mask & WINED3D_SHADER_CONST_FFP_PROJ) 1558 { 1559 struct wined3d_matrix projection; 1560 1561 get_projection_matrix(context, state, &projection); 1562 GL_EXTCALL(glUniformMatrix4fv(prog->vs.projection_matrix_location, 1, FALSE, &projection._11)); 1563 checkGLcall("glUniformMatrix4fv"); 1564 } 1565 1566 if (update_mask & WINED3D_SHADER_CONST_FFP_TEXMATRIX) 1567 { 1568 for (i = 0; i < MAX_TEXTURES; ++i) 1569 shader_glsl_ffp_vertex_texmatrix_uniform(context, state, i, prog); 1570 } 1571 1572 if (update_mask & WINED3D_SHADER_CONST_FFP_MATERIAL) 1573 shader_glsl_ffp_vertex_material_uniform(context, state, prog); 1574 1575 if (update_mask & WINED3D_SHADER_CONST_FFP_LIGHTS) 1576 { 1577 unsigned int point_idx, spot_idx, directional_idx, parallel_point_idx; 1578 DWORD point_count = 0; 1579 DWORD spot_count = 0; 1580 DWORD directional_count = 0; 1581 DWORD parallel_point_count = 0; 1582 1583 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) 1584 { 1585 if (!state->lights[i]) 1586 continue; 1587 1588 switch (state->lights[i]->OriginalParms.type) 1589 { 1590 case WINED3D_LIGHT_POINT: 1591 ++point_count; 1592 break; 1593 case WINED3D_LIGHT_SPOT: 1594 ++spot_count; 1595 break; 1596 case WINED3D_LIGHT_DIRECTIONAL: 1597 ++directional_count; 1598 break; 1599 case WINED3D_LIGHT_PARALLELPOINT: 1600 ++parallel_point_count; 1601 break; 1602 default: 1603 FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type); 1604 break; 1605 } 1606 } 1607 point_idx = 0; 1608 spot_idx = point_idx + point_count; 1609 directional_idx = spot_idx + spot_count; 1610 parallel_point_idx = directional_idx + directional_count; 1611 1612 shader_glsl_ffp_vertex_lightambient_uniform(context, state, prog); 1613 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) 1614 { 1615 const struct wined3d_light_info *light_info = state->lights[i]; 1616 unsigned int idx; 1617 1618 if (!light_info) 1619 continue; 1620 1621 switch (light_info->OriginalParms.type) 1622 { 1623 case WINED3D_LIGHT_POINT: 1624 idx = point_idx++; 1625 break; 1626 case WINED3D_LIGHT_SPOT: 1627 idx = spot_idx++; 1628 break; 1629 case WINED3D_LIGHT_DIRECTIONAL: 1630 idx = directional_idx++; 1631 break; 1632 case WINED3D_LIGHT_PARALLELPOINT: 1633 idx = parallel_point_idx++; 1634 break; 1635 default: 1636 FIXME("Unhandled light type %#x.\n", light_info->OriginalParms.type); 1637 continue; 1638 } 1639 shader_glsl_ffp_vertex_light_uniform(context, state, idx, light_info, prog); 1640 } 1641 } 1642 1643 if (update_mask & WINED3D_SHADER_CONST_PS_F) 1644 shader_glsl_load_constants_f(pshader, gl_info, state->ps_consts_f, 1645 prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version); 1646 1647 if (update_mask & WINED3D_SHADER_CONST_PS_I) 1648 shader_glsl_load_constants_i(pshader, gl_info, state->ps_consts_i, 1649 prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants); 1650 1651 if (update_mask & WINED3D_SHADER_CONST_PS_B) 1652 shader_glsl_load_constantsB(pshader, gl_info, prog->ps.uniform_b_locations, state->ps_consts_b, 1653 pshader->reg_maps.boolean_constants); 1654 1655 if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV) 1656 { 1657 for (i = 0; i < MAX_TEXTURES; ++i) 1658 { 1659 if (prog->ps.bumpenv_mat_location[i] == -1) 1660 continue; 1661 1662 GL_EXTCALL(glUniformMatrix2fv(prog->ps.bumpenv_mat_location[i], 1, 0, 1663 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00])); 1664 1665 if (prog->ps.bumpenv_lum_scale_location[i] != -1) 1666 { 1667 GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_scale_location[i], 1, 1668 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE])); 1669 GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_offset_location[i], 1, 1670 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET])); 1671 } 1672 } 1673 1674 checkGLcall("bump env uniforms"); 1675 } 1676 1677 if (update_mask & WINED3D_SHADER_CONST_PS_Y_CORR) 1678 { 1679 const struct wined3d_vec4 correction_params = 1680 { 1681 /* Position is relative to the framebuffer, not the viewport. */ 1682 context->render_offscreen ? 0.0f : (float)state->fb->render_targets[0]->height, 1683 context->render_offscreen ? 1.0f : -1.0f, 1684 0.0f, 1685 0.0f, 1686 }; 1687 1688 GL_EXTCALL(glUniform4fv(prog->ps.ycorrection_location, 1, &correction_params.x)); 1689 } 1690 1691 if (update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP) 1692 shader_glsl_load_np2fixup_constants(&prog->ps, gl_info, state); 1693 if (update_mask & WINED3D_SHADER_CONST_FFP_COLOR_KEY) 1694 shader_glsl_load_color_key_constant(&prog->ps, gl_info, state); 1695 1696 if (update_mask & WINED3D_SHADER_CONST_FFP_PS) 1697 { 1698 struct wined3d_color color; 1699 1700 if (prog->ps.tex_factor_location != -1) 1701 { 1702 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_TEXTUREFACTOR]); 1703 GL_EXTCALL(glUniform4fv(prog->ps.tex_factor_location, 1, &color.r)); 1704 } 1705 1706 if (state->render_states[WINED3D_RS_SPECULARENABLE]) 1707 GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 1.0f, 1.0f, 1.0f, 0.0f)); 1708 else 1709 GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 0.0f, 0.0f, 0.0f, 0.0f)); 1710 1711 for (i = 0; i < MAX_TEXTURES; ++i) 1712 { 1713 if (prog->ps.tss_constant_location[i] == -1) 1714 continue; 1715 1716 wined3d_color_from_d3dcolor(&color, state->texture_states[i][WINED3D_TSS_CONSTANT]); 1717 GL_EXTCALL(glUniform4fv(prog->ps.tss_constant_location[i], 1, &color.r)); 1718 } 1719 1720 checkGLcall("fixed function uniforms"); 1721 } 1722 1723 if (update_mask & WINED3D_SHADER_CONST_PS_FOG) 1724 shader_glsl_load_fog_uniform(context, state, prog); 1725 1726 if (update_mask & WINED3D_SHADER_CONST_PS_ALPHA_TEST) 1727 { 1728 float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f; 1729 1730 GL_EXTCALL(glUniform1f(prog->ps.alpha_test_ref_location, ref)); 1731 checkGLcall("alpha test emulation uniform"); 1732 } 1733 1734 if (priv->next_constant_version == UINT_MAX) 1735 { 1736 TRACE("Max constant version reached, resetting to 0.\n"); 1737 wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL); 1738 priv->next_constant_version = 1; 1739 } 1740 else 1741 { 1742 prog->constant_version = priv->next_constant_version++; 1743 } 1744 } 1745 1746 static void update_heap_entry(struct constant_heap *heap, unsigned int idx, DWORD new_version) 1747 { 1748 struct constant_entry *entries = heap->entries; 1749 unsigned int *positions = heap->positions; 1750 unsigned int heap_idx, parent_idx; 1751 1752 if (!heap->contained[idx]) 1753 { 1754 heap_idx = heap->size++; 1755 heap->contained[idx] = TRUE; 1756 } 1757 else 1758 { 1759 heap_idx = positions[idx]; 1760 } 1761 1762 while (heap_idx > 1) 1763 { 1764 parent_idx = heap_idx >> 1; 1765 1766 if (new_version <= entries[parent_idx].version) break; 1767 1768 entries[heap_idx] = entries[parent_idx]; 1769 positions[entries[parent_idx].idx] = heap_idx; 1770 heap_idx = parent_idx; 1771 } 1772 1773 entries[heap_idx].version = new_version; 1774 entries[heap_idx].idx = idx; 1775 positions[idx] = heap_idx; 1776 } 1777 1778 static void shader_glsl_update_float_vertex_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->vconst_heap; 1782 UINT i; 1783 1784 for (i = start; i < count + start; ++i) 1785 { 1786 update_heap_entry(heap, i, priv->next_constant_version); 1787 } 1788 } 1789 1790 static void shader_glsl_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count) 1791 { 1792 struct shader_glsl_priv *priv = device->shader_priv; 1793 struct constant_heap *heap = &priv->pconst_heap; 1794 UINT i; 1795 1796 for (i = start; i < count + start; ++i) 1797 { 1798 update_heap_entry(heap, i, priv->next_constant_version); 1799 } 1800 } 1801 1802 static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info) 1803 { 1804 unsigned int ret = gl_info->limits.glsl_varyings / 4; 1805 /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */ 1806 if(shader_major > 3) return ret; 1807 1808 /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */ 1809 if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1; 1810 return ret; 1811 } 1812 1813 static BOOL needs_legacy_glsl_syntax(const struct wined3d_gl_info *gl_info) 1814 { 1815 return gl_info->glsl_version < MAKEDWORD_VERSION(1, 30); 1816 } 1817 1818 static BOOL shader_glsl_use_explicit_attrib_location(const struct wined3d_gl_info *gl_info) 1819 { 1820 return gl_info->supported[ARB_EXPLICIT_ATTRIB_LOCATION] 1821 && shader_glsl_use_layout_qualifier(gl_info) && !needs_legacy_glsl_syntax(gl_info); 1822 } 1823 1824 static BOOL shader_glsl_use_interface_blocks(const struct wined3d_gl_info *gl_info) 1825 { 1826 return shader_glsl_get_version(gl_info) >= 150; 1827 } 1828 1829 static const char *get_attribute_keyword(const struct wined3d_gl_info *gl_info) 1830 { 1831 return needs_legacy_glsl_syntax(gl_info) ? "attribute" : "in"; 1832 } 1833 1834 static void PRINTF_ATTR(4, 5) declare_in_varying(const struct wined3d_gl_info *gl_info, 1835 struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...) 1836 { 1837 va_list args; 1838 int ret; 1839 1840 shader_addline(buffer, "%s%s ", flat ? "flat " : "", 1841 needs_legacy_glsl_syntax(gl_info) ? "varying" : "in"); 1842 for (;;) 1843 { 1844 va_start(args, format); 1845 ret = shader_vaddline(buffer, format, args); 1846 va_end(args); 1847 if (!ret) 1848 return; 1849 if (!string_buffer_resize(buffer, ret)) 1850 return; 1851 } 1852 } 1853 1854 static void PRINTF_ATTR(4, 5) declare_out_varying(const struct wined3d_gl_info *gl_info, 1855 struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...) 1856 { 1857 va_list args; 1858 int ret; 1859 1860 shader_addline(buffer, "%s%s ", flat ? "flat " : "", 1861 needs_legacy_glsl_syntax(gl_info) ? "varying" : "out"); 1862 for (;;) 1863 { 1864 va_start(args, format); 1865 ret = shader_vaddline(buffer, format, args); 1866 va_end(args); 1867 if (!ret) 1868 return; 1869 if (!string_buffer_resize(buffer, ret)) 1870 return; 1871 } 1872 } 1873 1874 static const char *shader_glsl_shader_input_name(const struct wined3d_gl_info *gl_info) 1875 { 1876 return shader_glsl_use_interface_blocks(gl_info) ? "shader_in.reg" : "ps_link"; 1877 } 1878 1879 static const char *shader_glsl_shader_output_name(const struct wined3d_gl_info *gl_info) 1880 { 1881 return shader_glsl_use_interface_blocks(gl_info) ? "shader_out.reg" : "ps_link"; 1882 } 1883 1884 static const char *shader_glsl_interpolation_qualifiers(enum wined3d_shader_interpolation_mode mode) 1885 { 1886 switch (mode) 1887 { 1888 case WINED3DSIM_CONSTANT: 1889 return "flat"; 1890 case WINED3DSIM_LINEAR_NOPERSPECTIVE: 1891 return "noperspective"; 1892 default: 1893 FIXME("Unhandled interpolation mode %#x.\n", mode); 1894 case WINED3DSIM_NONE: 1895 case WINED3DSIM_LINEAR: 1896 return ""; 1897 } 1898 } 1899 1900 static enum wined3d_shader_interpolation_mode wined3d_extract_interpolation_mode( 1901 const DWORD *packed_interpolation_mode, unsigned int register_idx) 1902 { 1903 return wined3d_extract_bits(packed_interpolation_mode, 1904 register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT); 1905 } 1906 1907 static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_info, 1908 struct wined3d_string_buffer *buffer, unsigned int element_count, 1909 const DWORD *interpolation_mode, BOOL unroll) 1910 { 1911 enum wined3d_shader_interpolation_mode mode; 1912 unsigned int i; 1913 1914 if (shader_glsl_use_interface_blocks(gl_info)) 1915 { 1916 if (unroll) 1917 { 1918 shader_addline(buffer, "in shader_in_out {\n"); 1919 for (i = 0; i < element_count; ++i) 1920 { 1921 mode = wined3d_extract_interpolation_mode(interpolation_mode, i); 1922 shader_addline(buffer, "%s vec4 reg%u;\n", shader_glsl_interpolation_qualifiers(mode), i); 1923 } 1924 shader_addline(buffer, "} shader_in;\n"); 1925 } 1926 else 1927 { 1928 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in;\n", element_count); 1929 } 1930 } 1931 else 1932 { 1933 declare_in_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count); 1934 } 1935 } 1936 1937 static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_info, 1938 struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup, 1939 const DWORD *interpolation_mode) 1940 { 1941 enum wined3d_shader_interpolation_mode mode; 1942 unsigned int i; 1943 1944 if (shader_glsl_use_interface_blocks(gl_info)) 1945 { 1946 if (rasterizer_setup) 1947 { 1948 shader_addline(buffer, "out shader_in_out {\n"); 1949 for (i = 0; i < element_count; ++i) 1950 { 1951 const char *interpolation_qualifiers = ""; 1952 if (needs_interpolation_qualifiers_for_shader_outputs(gl_info)) 1953 { 1954 mode = wined3d_extract_interpolation_mode(interpolation_mode, i); 1955 interpolation_qualifiers = shader_glsl_interpolation_qualifiers(mode); 1956 } 1957 shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i); 1958 } 1959 shader_addline(buffer, "} shader_out;\n"); 1960 } 1961 else 1962 { 1963 shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out;\n", element_count); 1964 } 1965 } 1966 else 1967 { 1968 declare_out_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count); 1969 } 1970 } 1971 1972 static const char *get_fragment_output(const struct wined3d_gl_info *gl_info) 1973 { 1974 return needs_legacy_glsl_syntax(gl_info) ? "gl_FragData" : "ps_out"; 1975 } 1976 1977 static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) 1978 { 1979 switch (primitive_type) 1980 { 1981 case WINED3D_PT_POINTLIST: 1982 return "points"; 1983 1984 case WINED3D_PT_LINELIST: 1985 return "lines"; 1986 1987 case WINED3D_PT_LINESTRIP: 1988 return "line_strip"; 1989 1990 case WINED3D_PT_TRIANGLELIST: 1991 return "triangles"; 1992 1993 case WINED3D_PT_TRIANGLESTRIP: 1994 return "triangle_strip"; 1995 1996 case WINED3D_PT_LINELIST_ADJ: 1997 return "lines_adjacency"; 1998 1999 case WINED3D_PT_TRIANGLELIST_ADJ: 2000 return "triangles_adjacency"; 2001 2002 default: 2003 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); 2004 return ""; 2005 } 2006 } 2007 2008 static BOOL glsl_is_color_reg_read(const struct wined3d_shader *shader, unsigned int idx) 2009 { 2010 const struct wined3d_shader_signature *input_signature = &shader->input_signature; 2011 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 2012 DWORD input_reg_used = shader->u.ps.input_reg_used; 2013 unsigned int i; 2014 2015 if (reg_maps->shader_version.major < 3) 2016 return input_reg_used & (1u << idx); 2017 2018 for (i = 0; i < input_signature->element_count; ++i) 2019 { 2020 const struct wined3d_shader_signature_element *input = &input_signature->elements[i]; 2021 2022 if (!(reg_maps->input_registers & (1u << input->register_idx))) 2023 continue; 2024 2025 if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_COLOR) 2026 && input->semantic_idx == idx) 2027 return input_reg_used & (1u << input->register_idx); 2028 } 2029 return FALSE; 2030 } 2031 2032 static BOOL glsl_is_shadow_sampler(const struct wined3d_shader *shader, 2033 const struct ps_compile_args *ps_args, unsigned int resource_idx, unsigned int sampler_idx) 2034 { 2035 const struct wined3d_shader_version *version = &shader->reg_maps.shader_version; 2036 2037 if (version->major >= 4) 2038 return shader->reg_maps.sampler_comparison_mode & (1u << sampler_idx); 2039 else 2040 return version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1u << resource_idx)); 2041 } 2042 2043 static void shader_glsl_declare_typed_vertex_attribute(struct wined3d_string_buffer *buffer, 2044 const struct wined3d_gl_info *gl_info, const char *vector_type, const char *scalar_type, 2045 unsigned int index) 2046 { 2047 shader_addline(buffer, "%s %s4 vs_in_%s%u;\n", 2048 get_attribute_keyword(gl_info), vector_type, scalar_type, index); 2049 shader_addline(buffer, "vec4 vs_in%u = %sBitsToFloat(vs_in_%s%u);\n", 2050 index, scalar_type, scalar_type, index); 2051 } 2052 2053 static void shader_glsl_declare_generic_vertex_attribute(struct wined3d_string_buffer *buffer, 2054 const struct wined3d_gl_info *gl_info, const struct wined3d_shader_signature_element *e) 2055 { 2056 unsigned int index = e->register_idx; 2057 2058 if (e->sysval_semantic == WINED3D_SV_VERTEX_ID) 2059 { 2060 shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_VertexID), 0.0, 0.0, 0.0);\n", 2061 index); 2062 return; 2063 } 2064 if (e->sysval_semantic == WINED3D_SV_INSTANCE_ID) 2065 { 2066 shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_InstanceID), 0.0, 0.0, 0.0);\n", 2067 index); 2068 return; 2069 } 2070 if (e->sysval_semantic && e->sysval_semantic != WINED3D_SV_POSITION) 2071 FIXME("Unhandled sysval semantic %#x.\n", e->sysval_semantic); 2072 2073 if (shader_glsl_use_explicit_attrib_location(gl_info)) 2074 shader_addline(buffer, "layout(location = %u) ", index); 2075 2076 switch (e->component_type) 2077 { 2078 case WINED3D_TYPE_UINT: 2079 shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "uvec", "uint", index); 2080 break; 2081 case WINED3D_TYPE_INT: 2082 shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "ivec", "int", index); 2083 break; 2084 2085 default: 2086 FIXME("Unhandled type %#x.\n", e->component_type); 2087 /* Fall through. */ 2088 case WINED3D_TYPE_UNKNOWN: 2089 case WINED3D_TYPE_FLOAT: 2090 shader_addline(buffer, "%s vec4 vs_in%u;\n", get_attribute_keyword(gl_info), index); 2091 break; 2092 } 2093 } 2094 2095 /** Generate the variable & register declarations for the GLSL output target */ 2096 static void shader_generate_glsl_declarations(const struct wined3d_context *context, 2097 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 2098 const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv) 2099 { 2100 const struct wined3d_shader_version *version = ®_maps->shader_version; 2101 const struct vs_compile_args *vs_args = ctx_priv->cur_vs_args; 2102 const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; 2103 const struct wined3d_gl_info *gl_info = context->gl_info; 2104 const struct wined3d_shader_indexable_temp *idx_temp_reg; 2105 unsigned int uniform_block_base, uniform_block_count; 2106 const struct wined3d_shader_lconst *lconst; 2107 const char *prefix; 2108 unsigned int i; 2109 DWORD map; 2110 2111 prefix = shader_glsl_get_prefix(version->type); 2112 2113 /* Prototype the subroutines */ 2114 for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i) 2115 { 2116 if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i); 2117 } 2118 2119 /* Declare the constants (aka uniforms) */ 2120 if (shader->limits->constant_float > 0) 2121 { 2122 unsigned max_constantsF; 2123 2124 /* Unless the shader uses indirect addressing, always declare the 2125 * maximum array size and ignore that we need some uniforms privately. 2126 * E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup 2127 * and immediate values, still declare VC[256]. If the shader needs 2128 * more uniforms than we have it won't work in any case. If it uses 2129 * less, the compiler will figure out which uniforms are really used 2130 * and strip them out. This allows a shader to use c255 on a dx9 card, 2131 * as long as it doesn't also use all the other constants. 2132 * 2133 * If the shader uses indirect addressing the compiler must assume 2134 * that all declared uniforms are used. In this case, declare only the 2135 * amount that we're assured to have. 2136 * 2137 * Thus we run into problems in these two cases: 2138 * 1) The shader really uses more uniforms than supported. 2139 * 2) The shader uses indirect addressing, less constants than 2140 * supported, but uses a constant index > #supported consts. */ 2141 if (version->type == WINED3D_SHADER_TYPE_PIXEL) 2142 { 2143 /* No indirect addressing here. */ 2144 max_constantsF = gl_info->limits.glsl_ps_float_constants; 2145 } 2146 else 2147 { 2148 if (reg_maps->usesrelconstF) 2149 { 2150 /* Subtract the other potential uniforms from the max 2151 * available (bools, ints, and 1 row of projection matrix). 2152 * Subtract another uniform for immediate values, which have 2153 * to be loaded via uniform by the driver as well. The shader 2154 * code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex 2155 * shader code, so one vec4 should be enough. (Unfortunately 2156 * the Nvidia driver doesn't store 128 and -128 in one float). 2157 * 2158 * Writing gl_ClipVertex requires one uniform for each 2159 * clipplane as well. */ 2160 max_constantsF = gl_info->limits.glsl_vs_float_constants - 3; 2161 if (vs_args->clip_enabled) 2162 max_constantsF -= gl_info->limits.user_clip_distances; 2163 max_constantsF -= wined3d_popcount(reg_maps->integer_constants); 2164 /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly, 2165 * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but 2166 * for now take this into account when calculating the number of available constants 2167 */ 2168 max_constantsF -= wined3d_popcount(reg_maps->boolean_constants); 2169 /* Set by driver quirks in directx.c */ 2170 max_constantsF -= gl_info->reserved_glsl_constants; 2171 2172 if (max_constantsF < shader->limits->constant_float) 2173 { 2174 static unsigned int once; 2175 2176 if (!once++) 2177 ERR_(winediag)("The hardware does not support enough uniform components to run this shader," 2178 " it may not render correctly.\n"); 2179 else 2180 WARN("The hardware does not support enough uniform components to run this shader.\n"); 2181 } 2182 } 2183 else 2184 { 2185 max_constantsF = gl_info->limits.glsl_vs_float_constants; 2186 } 2187 } 2188 max_constantsF = min(shader->limits->constant_float, max_constantsF); 2189 shader_addline(buffer, "uniform vec4 %s_c[%u];\n", prefix, max_constantsF); 2190 } 2191 2192 /* Always declare the full set of constants, the compiler can remove the 2193 * unused ones because d3d doesn't (yet) support indirect int and bool 2194 * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */ 2195 if (shader->limits->constant_int > 0 && reg_maps->integer_constants) 2196 shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits->constant_int); 2197 2198 if (shader->limits->constant_bool > 0 && reg_maps->boolean_constants) 2199 shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits->constant_bool); 2200 2201 /* Declare immediate constant buffer */ 2202 if (reg_maps->icb) 2203 shader_addline(buffer, "uniform vec4 %s_icb[%u];\n", prefix, reg_maps->icb->vec4_count); 2204 2205 /* Declare constant buffers */ 2206 wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, version->type, 2207 &uniform_block_base, &uniform_block_count); 2208 for (i = 0; i < min(uniform_block_count, WINED3D_MAX_CBS); ++i) 2209 { 2210 if (reg_maps->cb_sizes[i]) 2211 { 2212 shader_addline(buffer, "layout(std140"); 2213 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 2214 shader_addline(buffer, ", binding = %u", uniform_block_base + i); 2215 shader_addline(buffer, ") uniform block_%s_cb%u { vec4 %s_cb%u[%u]; };\n", 2216 prefix, i, prefix, i, reg_maps->cb_sizes[i]); 2217 } 2218 } 2219 2220 /* Declare texture samplers */ 2221 for (i = 0; i < reg_maps->sampler_map.count; ++i) 2222 { 2223 struct wined3d_shader_sampler_map_entry *entry; 2224 const char *sampler_type_prefix, *sampler_type; 2225 BOOL shadow_sampler, tex_rect; 2226 2227 entry = ®_maps->sampler_map.entries[i]; 2228 2229 if (entry->resource_idx >= ARRAY_SIZE(reg_maps->resource_info)) 2230 { 2231 ERR("Invalid resource index %u.\n", entry->resource_idx); 2232 continue; 2233 } 2234 2235 switch (reg_maps->resource_info[entry->resource_idx].data_type) 2236 { 2237 case WINED3D_DATA_FLOAT: 2238 case WINED3D_DATA_UNORM: 2239 case WINED3D_DATA_SNORM: 2240 sampler_type_prefix = ""; 2241 break; 2242 2243 case WINED3D_DATA_INT: 2244 sampler_type_prefix = "i"; 2245 break; 2246 2247 case WINED3D_DATA_UINT: 2248 sampler_type_prefix = "u"; 2249 break; 2250 2251 default: 2252 sampler_type_prefix = ""; 2253 ERR("Unhandled resource data type %#x.\n", reg_maps->resource_info[i].data_type); 2254 break; 2255 } 2256 2257 shadow_sampler = glsl_is_shadow_sampler(shader, ps_args, entry->resource_idx, entry->sampler_idx); 2258 switch (reg_maps->resource_info[entry->resource_idx].type) 2259 { 2260 case WINED3D_SHADER_RESOURCE_BUFFER: 2261 sampler_type = "samplerBuffer"; 2262 break; 2263 2264 case WINED3D_SHADER_RESOURCE_TEXTURE_1D: 2265 if (shadow_sampler) 2266 sampler_type = "sampler1DShadow"; 2267 else 2268 sampler_type = "sampler1D"; 2269 break; 2270 2271 case WINED3D_SHADER_RESOURCE_TEXTURE_2D: 2272 tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL 2273 && (ps_args->np2_fixup & (1u << entry->resource_idx)) 2274 && gl_info->supported[ARB_TEXTURE_RECTANGLE]; 2275 if (shadow_sampler) 2276 { 2277 if (tex_rect) 2278 sampler_type = "sampler2DRectShadow"; 2279 else 2280 sampler_type = "sampler2DShadow"; 2281 } 2282 else 2283 { 2284 if (tex_rect) 2285 sampler_type = "sampler2DRect"; 2286 else 2287 sampler_type = "sampler2D"; 2288 } 2289 break; 2290 2291 case WINED3D_SHADER_RESOURCE_TEXTURE_3D: 2292 if (shadow_sampler) 2293 FIXME("Unsupported 3D shadow sampler.\n"); 2294 sampler_type = "sampler3D"; 2295 break; 2296 2297 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: 2298 if (shadow_sampler) 2299 sampler_type = "samplerCubeShadow"; 2300 else 2301 sampler_type = "samplerCube"; 2302 break; 2303 2304 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY: 2305 if (shadow_sampler) 2306 sampler_type = "sampler1DArrayShadow"; 2307 else 2308 sampler_type = "sampler1DArray"; 2309 break; 2310 2311 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: 2312 if (shadow_sampler) 2313 sampler_type = "sampler2DArrayShadow"; 2314 else 2315 sampler_type = "sampler2DArray"; 2316 break; 2317 2318 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY: 2319 if (shadow_sampler) 2320 sampler_type = "samplerCubeArrayShadow"; 2321 else 2322 sampler_type = "samplerCubeArray"; 2323 break; 2324 2325 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS: 2326 sampler_type = "sampler2DMS"; 2327 break; 2328 2329 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY: 2330 sampler_type = "sampler2DMSArray"; 2331 break; 2332 2333 default: 2334 sampler_type = "unsupported_sampler"; 2335 FIXME("Unhandled resource type %#x.\n", reg_maps->resource_info[entry->resource_idx].type); 2336 break; 2337 } 2338 2339 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 2340 shader_glsl_append_sampler_binding_qualifier(buffer, context, version, entry->bind_idx); 2341 shader_addline(buffer, "uniform %s%s %s_sampler%u;\n", 2342 sampler_type_prefix, sampler_type, prefix, entry->bind_idx); 2343 } 2344 2345 /* Declare images */ 2346 for (i = 0; i < ARRAY_SIZE(reg_maps->uav_resource_info); ++i) 2347 { 2348 const char *image_type_prefix, *image_type, *read_format; 2349 2350 if (!reg_maps->uav_resource_info[i].type) 2351 continue; 2352 2353 switch (reg_maps->uav_resource_info[i].data_type) 2354 { 2355 case WINED3D_DATA_FLOAT: 2356 case WINED3D_DATA_UNORM: 2357 case WINED3D_DATA_SNORM: 2358 image_type_prefix = ""; 2359 read_format = "r32f"; 2360 break; 2361 2362 case WINED3D_DATA_INT: 2363 image_type_prefix = "i"; 2364 read_format = "r32i"; 2365 break; 2366 2367 case WINED3D_DATA_UINT: 2368 image_type_prefix = "u"; 2369 read_format = "r32ui"; 2370 break; 2371 2372 default: 2373 image_type_prefix = ""; 2374 read_format = ""; 2375 ERR("Unhandled resource data type %#x.\n", reg_maps->uav_resource_info[i].data_type); 2376 break; 2377 } 2378 2379 switch (reg_maps->uav_resource_info[i].type) 2380 { 2381 case WINED3D_SHADER_RESOURCE_BUFFER: 2382 image_type = "imageBuffer"; 2383 break; 2384 2385 case WINED3D_SHADER_RESOURCE_TEXTURE_2D: 2386 image_type = "image2D"; 2387 break; 2388 2389 case WINED3D_SHADER_RESOURCE_TEXTURE_3D: 2390 image_type = "image3D"; 2391 break; 2392 2393 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: 2394 image_type = "image2DArray"; 2395 break; 2396 2397 default: 2398 image_type = "unsupported_image"; 2399 FIXME("Unhandled resource type %#x.\n", reg_maps->uav_resource_info[i].type); 2400 break; 2401 } 2402 2403 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 2404 shader_addline(buffer, "layout(binding = %u)\n", i); 2405 if (reg_maps->uav_read_mask & (1u << i)) 2406 shader_addline(buffer, "layout(%s) uniform %s%s %s_image%u;\n", 2407 read_format, image_type_prefix, image_type, prefix, i); 2408 else 2409 shader_addline(buffer, "writeonly uniform %s%s %s_image%u;\n", 2410 image_type_prefix, image_type, prefix, i); 2411 2412 if (reg_maps->uav_counter_mask & (1u << i)) 2413 shader_addline(buffer, "layout(binding = %u) uniform atomic_uint %s_counter%u;\n", 2414 i, prefix, i); 2415 } 2416 2417 /* Declare address variables */ 2418 for (i = 0, map = reg_maps->address; map; map >>= 1, ++i) 2419 { 2420 if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i); 2421 } 2422 2423 /* Declare output register temporaries */ 2424 if (shader->limits->packed_output) 2425 shader_addline(buffer, "vec4 %s_out[%u];\n", prefix, shader->limits->packed_output); 2426 2427 /* Declare temporary variables */ 2428 if (reg_maps->temporary_count) 2429 { 2430 for (i = 0; i < reg_maps->temporary_count; ++i) 2431 shader_addline(buffer, "vec4 R%u;\n", i); 2432 } 2433 else if (version->major < 4) 2434 { 2435 for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i) 2436 { 2437 if (map & 1) 2438 shader_addline(buffer, "vec4 R%u;\n", i); 2439 } 2440 } 2441 2442 /* Declare indexable temporary variables */ 2443 LIST_FOR_EACH_ENTRY(idx_temp_reg, ®_maps->indexable_temps, struct wined3d_shader_indexable_temp, entry) 2444 { 2445 if (idx_temp_reg->component_count != 4) 2446 FIXME("Ignoring component count %u.\n", idx_temp_reg->component_count); 2447 shader_addline(buffer, "vec4 X%u[%u];\n", idx_temp_reg->register_idx, idx_temp_reg->register_size); 2448 } 2449 2450 /* Declare loop registers aLx */ 2451 if (version->major < 4) 2452 { 2453 for (i = 0; i < reg_maps->loop_depth; ++i) 2454 { 2455 shader_addline(buffer, "int aL%u;\n", i); 2456 shader_addline(buffer, "int tmpInt%u;\n", i); 2457 } 2458 } 2459 2460 /* Temporary variables for matrix operations */ 2461 shader_addline(buffer, "vec4 tmp0;\n"); 2462 shader_addline(buffer, "vec4 tmp1;\n"); 2463 2464 if (!shader->load_local_constsF) 2465 { 2466 LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry) 2467 { 2468 shader_addline(buffer, "const vec4 %s_lc%u = ", prefix, lconst->idx); 2469 shader_glsl_append_imm_vec4(buffer, (const float *)lconst->value); 2470 shader_addline(buffer, ";\n"); 2471 } 2472 } 2473 } 2474 2475 /* Prototypes */ 2476 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, 2477 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src); 2478 2479 /** Used for opcode modifiers - They multiply the result by the specified amount */ 2480 static const char * const shift_glsl_tab[] = { 2481 "", /* 0 (none) */ 2482 "2.0 * ", /* 1 (x2) */ 2483 "4.0 * ", /* 2 (x4) */ 2484 "8.0 * ", /* 3 (x8) */ 2485 "16.0 * ", /* 4 (x16) */ 2486 "32.0 * ", /* 5 (x32) */ 2487 "", /* 6 (x64) */ 2488 "", /* 7 (x128) */ 2489 "", /* 8 (d256) */ 2490 "", /* 9 (d128) */ 2491 "", /* 10 (d64) */ 2492 "", /* 11 (d32) */ 2493 "0.0625 * ", /* 12 (d16) */ 2494 "0.125 * ", /* 13 (d8) */ 2495 "0.25 * ", /* 14 (d4) */ 2496 "0.5 * " /* 15 (d2) */ 2497 }; 2498 2499 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */ 2500 static void shader_glsl_gen_modifier(enum wined3d_shader_src_modifier src_modifier, 2501 const char *in_reg, const char *in_regswizzle, char *out_str) 2502 { 2503 switch (src_modifier) 2504 { 2505 case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */ 2506 case WINED3DSPSM_DW: 2507 case WINED3DSPSM_NONE: 2508 sprintf(out_str, "%s%s", in_reg, in_regswizzle); 2509 break; 2510 case WINED3DSPSM_NEG: 2511 sprintf(out_str, "-%s%s", in_reg, in_regswizzle); 2512 break; 2513 case WINED3DSPSM_NOT: 2514 sprintf(out_str, "!%s%s", in_reg, in_regswizzle); 2515 break; 2516 case WINED3DSPSM_BIAS: 2517 sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); 2518 break; 2519 case WINED3DSPSM_BIASNEG: 2520 sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); 2521 break; 2522 case WINED3DSPSM_SIGN: 2523 sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle); 2524 break; 2525 case WINED3DSPSM_SIGNNEG: 2526 sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle); 2527 break; 2528 case WINED3DSPSM_COMP: 2529 sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle); 2530 break; 2531 case WINED3DSPSM_X2: 2532 sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle); 2533 break; 2534 case WINED3DSPSM_X2NEG: 2535 sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle); 2536 break; 2537 case WINED3DSPSM_ABS: 2538 sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle); 2539 break; 2540 case WINED3DSPSM_ABSNEG: 2541 sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle); 2542 break; 2543 default: 2544 FIXME("Unhandled modifier %u\n", src_modifier); 2545 sprintf(out_str, "%s%s", in_reg, in_regswizzle); 2546 } 2547 } 2548 2549 static void shader_glsl_fixup_scalar_register_variable(char *register_name, 2550 const char *glsl_variable, const struct wined3d_gl_info *gl_info) 2551 { 2552 /* The ARB_shading_language_420pack extension allows swizzle operations on 2553 * scalars. */ 2554 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) 2555 sprintf(register_name, "%s", glsl_variable); 2556 else 2557 sprintf(register_name, "ivec2(%s, 0)", glsl_variable); 2558 } 2559 2560 /** Writes the GLSL variable name that corresponds to the register that the 2561 * DX opcode parameter is trying to access */ 2562 static void shader_glsl_get_register_name(const struct wined3d_shader_register *reg, 2563 enum wined3d_data_type data_type, char *register_name, BOOL *is_color, 2564 const struct wined3d_shader_instruction *ins) 2565 { 2566 /* oPos, oFog and oPts in D3D */ 2567 static const char * const hwrastout_reg_names[] = {"vs_out[10]", "vs_out[11].x", "vs_out[11].y"}; 2568 2569 const struct wined3d_shader *shader = ins->ctx->shader; 2570 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 2571 const struct wined3d_shader_version *version = ®_maps->shader_version; 2572 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 2573 const char *prefix = shader_glsl_get_prefix(version->type); 2574 struct glsl_src_param rel_param0, rel_param1; 2575 char imm_str[4][17]; 2576 2577 if (reg->idx[0].offset != ~0U && reg->idx[0].rel_addr) 2578 shader_glsl_add_src_param(ins, reg->idx[0].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param0); 2579 if (reg->idx[1].offset != ~0U && reg->idx[1].rel_addr) 2580 shader_glsl_add_src_param(ins, reg->idx[1].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param1); 2581 *is_color = FALSE; 2582 2583 switch (reg->type) 2584 { 2585 case WINED3DSPR_TEMP: 2586 sprintf(register_name, "R%u", reg->idx[0].offset); 2587 break; 2588 2589 case WINED3DSPR_INPUT: 2590 case WINED3DSPR_INCONTROLPOINT: 2591 if (version->type == WINED3D_SHADER_TYPE_VERTEX) 2592 { 2593 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 2594 2595 if (reg->idx[0].rel_addr) 2596 FIXME("VS3 input registers relative addressing.\n"); 2597 if (priv->cur_vs_args->swizzle_map & (1u << reg->idx[0].offset)) 2598 *is_color = TRUE; 2599 if (reg->idx[0].rel_addr) 2600 { 2601 sprintf(register_name, "%s_in[%s + %u]", 2602 prefix, rel_param0.param_str, reg->idx[0].offset); 2603 } 2604 else 2605 { 2606 sprintf(register_name, "%s_in%u", prefix, reg->idx[0].offset); 2607 } 2608 break; 2609 } 2610 2611 if (version->type == WINED3D_SHADER_TYPE_HULL 2612 || version->type == WINED3D_SHADER_TYPE_DOMAIN 2613 || version->type == WINED3D_SHADER_TYPE_GEOMETRY) 2614 { 2615 if (reg->idx[0].rel_addr) 2616 { 2617 if (reg->idx[1].rel_addr) 2618 sprintf(register_name, "shader_in[%s + %u].reg[%s + %u]", 2619 rel_param0.param_str, reg->idx[0].offset, 2620 rel_param1.param_str, reg->idx[1].offset); 2621 else 2622 sprintf(register_name, "shader_in[%s + %u].reg[%u]", 2623 rel_param0.param_str, reg->idx[0].offset, 2624 reg->idx[1].offset); 2625 } 2626 else if (reg->idx[1].rel_addr) 2627 sprintf(register_name, "shader_in[%u].reg[%s + %u]", reg->idx[0].offset, 2628 rel_param1.param_str, reg->idx[1].offset); 2629 else 2630 sprintf(register_name, "shader_in[%u].reg[%u]", 2631 reg->idx[0].offset, reg->idx[1].offset); 2632 break; 2633 } 2634 2635 /* pixel shaders >= 3.0 */ 2636 if (version->major >= 3) 2637 { 2638 DWORD idx = shader->u.ps.input_reg_map[reg->idx[0].offset]; 2639 unsigned int in_count = vec4_varyings(version->major, gl_info); 2640 2641 if (reg->idx[0].rel_addr) 2642 { 2643 /* Removing a + 0 would be an obvious optimization, but 2644 * OS X doesn't see the NOP operation there. */ 2645 if (idx) 2646 { 2647 if (needs_legacy_glsl_syntax(gl_info) 2648 && shader->u.ps.declared_in_count > in_count) 2649 { 2650 sprintf(register_name, 2651 "((%s + %u) > %u ? (%s + %u) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s + %u])", 2652 rel_param0.param_str, idx, in_count - 1, rel_param0.param_str, idx, in_count, 2653 prefix, rel_param0.param_str, idx); 2654 } 2655 else 2656 { 2657 sprintf(register_name, "%s_in[%s + %u]", prefix, rel_param0.param_str, idx); 2658 } 2659 } 2660 else 2661 { 2662 if (needs_legacy_glsl_syntax(gl_info) 2663 && shader->u.ps.declared_in_count > in_count) 2664 { 2665 sprintf(register_name, "((%s) > %u ? (%s) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s])", 2666 rel_param0.param_str, in_count - 1, rel_param0.param_str, in_count, 2667 prefix, rel_param0.param_str); 2668 } 2669 else 2670 { 2671 sprintf(register_name, "%s_in[%s]", prefix, rel_param0.param_str); 2672 } 2673 } 2674 } 2675 else 2676 { 2677 if (idx == in_count) sprintf(register_name, "gl_Color"); 2678 else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor"); 2679 else sprintf(register_name, "%s_in[%u]", prefix, idx); 2680 } 2681 } 2682 else 2683 { 2684 if (!reg->idx[0].offset) 2685 strcpy(register_name, "ffp_varying_diffuse"); 2686 else 2687 strcpy(register_name, "ffp_varying_specular"); 2688 break; 2689 } 2690 break; 2691 2692 case WINED3DSPR_CONST: 2693 { 2694 /* Relative addressing */ 2695 if (reg->idx[0].rel_addr) 2696 { 2697 if (wined3d_settings.check_float_constants) 2698 sprintf(register_name, "(%s + %u >= 0 && %s + %u < %u ? %s_c[%s + %u] : vec4(0.0))", 2699 rel_param0.param_str, reg->idx[0].offset, 2700 rel_param0.param_str, reg->idx[0].offset, shader->limits->constant_float, 2701 prefix, rel_param0.param_str, reg->idx[0].offset); 2702 else if (reg->idx[0].offset) 2703 sprintf(register_name, "%s_c[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset); 2704 else 2705 sprintf(register_name, "%s_c[%s]", prefix, rel_param0.param_str); 2706 } 2707 else 2708 { 2709 if (shader_constant_is_local(shader, reg->idx[0].offset)) 2710 sprintf(register_name, "%s_lc%u", prefix, reg->idx[0].offset); 2711 else 2712 sprintf(register_name, "%s_c[%u]", prefix, reg->idx[0].offset); 2713 } 2714 } 2715 break; 2716 2717 case WINED3DSPR_CONSTINT: 2718 sprintf(register_name, "%s_i[%u]", prefix, reg->idx[0].offset); 2719 break; 2720 2721 case WINED3DSPR_CONSTBOOL: 2722 sprintf(register_name, "%s_b[%u]", prefix, reg->idx[0].offset); 2723 break; 2724 2725 case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */ 2726 if (version->type == WINED3D_SHADER_TYPE_PIXEL) 2727 sprintf(register_name, "T%u", reg->idx[0].offset); 2728 else 2729 sprintf(register_name, "A%u", reg->idx[0].offset); 2730 break; 2731 2732 case WINED3DSPR_LOOP: 2733 sprintf(register_name, "aL%u", ins->ctx->state->current_loop_reg - 1); 2734 break; 2735 2736 case WINED3DSPR_SAMPLER: 2737 sprintf(register_name, "%s_sampler%u", prefix, reg->idx[0].offset); 2738 break; 2739 2740 case WINED3DSPR_COLOROUT: 2741 /* FIXME: should check dual_buffers when dual blending is enabled */ 2742 if (reg->idx[0].offset >= gl_info->limits.buffers) 2743 WARN("Write to render target %u, only %d supported.\n", 2744 reg->idx[0].offset, gl_info->limits.buffers); 2745 2746 sprintf(register_name, needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[%u]" : "ps_out%u", 2747 reg->idx[0].offset); 2748 break; 2749 2750 case WINED3DSPR_RASTOUT: 2751 sprintf(register_name, "%s", hwrastout_reg_names[reg->idx[0].offset]); 2752 break; 2753 2754 case WINED3DSPR_DEPTHOUT: 2755 case WINED3DSPR_DEPTHOUTGE: 2756 case WINED3DSPR_DEPTHOUTLE: 2757 sprintf(register_name, "gl_FragDepth"); 2758 break; 2759 2760 case WINED3DSPR_ATTROUT: 2761 if (!reg->idx[0].offset) 2762 sprintf(register_name, "%s_out[8]", prefix); 2763 else 2764 sprintf(register_name, "%s_out[9]", prefix); 2765 break; 2766 2767 case WINED3DSPR_TEXCRDOUT: 2768 /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */ 2769 if (reg->idx[0].rel_addr) 2770 sprintf(register_name, "%s_out[%s + %u]", 2771 prefix, rel_param0.param_str, reg->idx[0].offset); 2772 else 2773 sprintf(register_name, "%s_out[%u]", prefix, reg->idx[0].offset); 2774 break; 2775 2776 case WINED3DSPR_MISCTYPE: 2777 if (!reg->idx[0].offset) 2778 { 2779 /* vPos */ 2780 sprintf(register_name, "vpos"); 2781 } 2782 else if (reg->idx[0].offset == 1) 2783 { 2784 /* Note that gl_FrontFacing is a bool, while vFace is 2785 * a float for which the sign determines front/back */ 2786 sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)"); 2787 } 2788 else 2789 { 2790 FIXME("Unhandled misctype register %u.\n", reg->idx[0].offset); 2791 sprintf(register_name, "unrecognized_register"); 2792 } 2793 break; 2794 2795 case WINED3DSPR_IMMCONST: 2796 switch (reg->immconst_type) 2797 { 2798 case WINED3D_IMMCONST_SCALAR: 2799 switch (data_type) 2800 { 2801 case WINED3D_DATA_FLOAT: 2802 if (gl_info->supported[ARB_SHADER_BIT_ENCODING]) 2803 sprintf(register_name, "uintBitsToFloat(%#xu)", reg->u.immconst_data[0]); 2804 else 2805 wined3d_ftoa(*(const float *)reg->u.immconst_data, register_name); 2806 break; 2807 case WINED3D_DATA_INT: 2808 sprintf(register_name, "%#x", reg->u.immconst_data[0]); 2809 break; 2810 case WINED3D_DATA_RESOURCE: 2811 case WINED3D_DATA_SAMPLER: 2812 case WINED3D_DATA_UINT: 2813 sprintf(register_name, "%#xu", reg->u.immconst_data[0]); 2814 break; 2815 default: 2816 sprintf(register_name, "<unhandled data type %#x>", data_type); 2817 break; 2818 } 2819 break; 2820 2821 case WINED3D_IMMCONST_VEC4: 2822 switch (data_type) 2823 { 2824 case WINED3D_DATA_FLOAT: 2825 if (gl_info->supported[ARB_SHADER_BIT_ENCODING]) 2826 { 2827 sprintf(register_name, "uintBitsToFloat(uvec4(%#xu, %#xu, %#xu, %#xu))", 2828 reg->u.immconst_data[0], reg->u.immconst_data[1], 2829 reg->u.immconst_data[2], reg->u.immconst_data[3]); 2830 } 2831 else 2832 { 2833 wined3d_ftoa(*(const float *)®->u.immconst_data[0], imm_str[0]); 2834 wined3d_ftoa(*(const float *)®->u.immconst_data[1], imm_str[1]); 2835 wined3d_ftoa(*(const float *)®->u.immconst_data[2], imm_str[2]); 2836 wined3d_ftoa(*(const float *)®->u.immconst_data[3], imm_str[3]); 2837 sprintf(register_name, "vec4(%s, %s, %s, %s)", 2838 imm_str[0], imm_str[1], imm_str[2], imm_str[3]); 2839 } 2840 break; 2841 case WINED3D_DATA_INT: 2842 sprintf(register_name, "ivec4(%#x, %#x, %#x, %#x)", 2843 reg->u.immconst_data[0], reg->u.immconst_data[1], 2844 reg->u.immconst_data[2], reg->u.immconst_data[3]); 2845 break; 2846 case WINED3D_DATA_RESOURCE: 2847 case WINED3D_DATA_SAMPLER: 2848 case WINED3D_DATA_UINT: 2849 sprintf(register_name, "uvec4(%#xu, %#xu, %#xu, %#xu)", 2850 reg->u.immconst_data[0], reg->u.immconst_data[1], 2851 reg->u.immconst_data[2], reg->u.immconst_data[3]); 2852 break; 2853 default: 2854 sprintf(register_name, "<unhandled data type %#x>", data_type); 2855 break; 2856 } 2857 break; 2858 2859 default: 2860 FIXME("Unhandled immconst type %#x\n", reg->immconst_type); 2861 sprintf(register_name, "<unhandled_immconst_type %#x>", reg->immconst_type); 2862 } 2863 break; 2864 2865 case WINED3DSPR_CONSTBUFFER: 2866 if (reg->idx[1].rel_addr) 2867 sprintf(register_name, "%s_cb%u[%s + %u]", 2868 prefix, reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset); 2869 else 2870 sprintf(register_name, "%s_cb%u[%u]", prefix, reg->idx[0].offset, reg->idx[1].offset); 2871 break; 2872 2873 case WINED3DSPR_IMMCONSTBUFFER: 2874 if (reg->idx[0].rel_addr) 2875 sprintf(register_name, "%s_icb[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset); 2876 else 2877 sprintf(register_name, "%s_icb[%u]", prefix, reg->idx[0].offset); 2878 break; 2879 2880 case WINED3DSPR_PRIMID: 2881 if (version->type == WINED3D_SHADER_TYPE_GEOMETRY) 2882 sprintf(register_name, "gl_PrimitiveIDIn"); 2883 else 2884 sprintf(register_name, "gl_PrimitiveID"); 2885 break; 2886 2887 case WINED3DSPR_IDXTEMP: 2888 if (reg->idx[1].rel_addr) 2889 sprintf(register_name, "X%u[%s + %u]", reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset); 2890 else 2891 sprintf(register_name, "X%u[%u]", reg->idx[0].offset, reg->idx[1].offset); 2892 break; 2893 2894 case WINED3DSPR_LOCALTHREADINDEX: 2895 shader_glsl_fixup_scalar_register_variable(register_name, 2896 "int(gl_LocalInvocationIndex)", gl_info); 2897 break; 2898 2899 case WINED3DSPR_GSINSTID: 2900 case WINED3DSPR_OUTPOINTID: 2901 shader_glsl_fixup_scalar_register_variable(register_name, 2902 "gl_InvocationID", gl_info); 2903 break; 2904 2905 case WINED3DSPR_THREADID: 2906 sprintf(register_name, "ivec3(gl_GlobalInvocationID)"); 2907 break; 2908 2909 case WINED3DSPR_THREADGROUPID: 2910 sprintf(register_name, "ivec3(gl_WorkGroupID)"); 2911 break; 2912 2913 case WINED3DSPR_LOCALTHREADID: 2914 sprintf(register_name, "ivec3(gl_LocalInvocationID)"); 2915 break; 2916 2917 case WINED3DSPR_FORKINSTID: 2918 case WINED3DSPR_JOININSTID: 2919 shader_glsl_fixup_scalar_register_variable(register_name, 2920 "phase_instance_id", gl_info); 2921 break; 2922 2923 case WINED3DSPR_TESSCOORD: 2924 sprintf(register_name, "gl_TessCoord"); 2925 break; 2926 2927 case WINED3DSPR_OUTCONTROLPOINT: 2928 if (reg->idx[0].rel_addr) 2929 { 2930 if (reg->idx[1].rel_addr) 2931 sprintf(register_name, "shader_out[%s + %u].reg[%s + %u]", 2932 rel_param0.param_str, reg->idx[0].offset, 2933 rel_param1.param_str, reg->idx[1].offset); 2934 else 2935 sprintf(register_name, "shader_out[%s + %u].reg[%u]", 2936 rel_param0.param_str, reg->idx[0].offset, 2937 reg->idx[1].offset); 2938 } 2939 else if (reg->idx[1].rel_addr) 2940 { 2941 sprintf(register_name, "shader_out[%u].reg[%s + %u]", 2942 reg->idx[0].offset, rel_param1.param_str, 2943 reg->idx[1].offset); 2944 } 2945 else 2946 { 2947 sprintf(register_name, "shader_out[%u].reg[%u]", 2948 reg->idx[0].offset, reg->idx[1].offset); 2949 } 2950 break; 2951 2952 case WINED3DSPR_PATCHCONST: 2953 if (version->type == WINED3D_SHADER_TYPE_HULL) 2954 sprintf(register_name, "hs_out[%u]", reg->idx[0].offset); 2955 else 2956 sprintf(register_name, "vpc[%u]", reg->idx[0].offset); 2957 break; 2958 2959 case WINED3DSPR_SAMPLEMASK: 2960 sprintf(register_name, "sample_mask"); 2961 break; 2962 2963 default: 2964 FIXME("Unhandled register type %#x.\n", reg->type); 2965 sprintf(register_name, "unrecognized_register"); 2966 break; 2967 } 2968 } 2969 2970 static void shader_glsl_write_mask_to_str(DWORD write_mask, char *str) 2971 { 2972 *str++ = '.'; 2973 if (write_mask & WINED3DSP_WRITEMASK_0) *str++ = 'x'; 2974 if (write_mask & WINED3DSP_WRITEMASK_1) *str++ = 'y'; 2975 if (write_mask & WINED3DSP_WRITEMASK_2) *str++ = 'z'; 2976 if (write_mask & WINED3DSP_WRITEMASK_3) *str++ = 'w'; 2977 *str = '\0'; 2978 } 2979 2980 /* Get the GLSL write mask for the destination register */ 2981 static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *param, char *write_mask) 2982 { 2983 DWORD mask = param->write_mask; 2984 2985 if (shader_is_scalar(¶m->reg)) 2986 { 2987 mask = WINED3DSP_WRITEMASK_0; 2988 *write_mask = '\0'; 2989 } 2990 else 2991 { 2992 shader_glsl_write_mask_to_str(mask, write_mask); 2993 } 2994 2995 return mask; 2996 } 2997 2998 static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask) 2999 { 3000 unsigned int size = 0; 3001 3002 if (write_mask & WINED3DSP_WRITEMASK_0) ++size; 3003 if (write_mask & WINED3DSP_WRITEMASK_1) ++size; 3004 if (write_mask & WINED3DSP_WRITEMASK_2) ++size; 3005 if (write_mask & WINED3DSP_WRITEMASK_3) ++size; 3006 3007 return size; 3008 } 3009 3010 static unsigned int shader_glsl_swizzle_get_component(DWORD swizzle, 3011 unsigned int component_idx) 3012 { 3013 /* swizzle bits fields: wwzzyyxx */ 3014 return (swizzle >> (2 * component_idx)) & 0x3; 3015 } 3016 3017 static void shader_glsl_swizzle_to_str(DWORD swizzle, BOOL fixup, DWORD mask, char *str) 3018 { 3019 /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra", 3020 * but addressed as "rgba". To fix this we need to swap the register's x 3021 * and z components. */ 3022 const char *swizzle_chars = fixup ? "zyxw" : "xyzw"; 3023 unsigned int i; 3024 3025 *str++ = '.'; 3026 for (i = 0; i < 4; ++i) 3027 { 3028 if (mask & (WINED3DSP_WRITEMASK_0 << i)) 3029 *str++ = swizzle_chars[shader_glsl_swizzle_get_component(swizzle, i)]; 3030 } 3031 *str = '\0'; 3032 } 3033 3034 static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param, 3035 BOOL fixup, DWORD mask, char *swizzle_str) 3036 { 3037 if (shader_is_scalar(¶m->reg)) 3038 *swizzle_str = '\0'; 3039 else 3040 shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str); 3041 } 3042 3043 static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, const char *src_param, 3044 enum wined3d_data_type dst_data_type, enum wined3d_data_type src_data_type) 3045 { 3046 if (dst_data_type == src_data_type) 3047 { 3048 string_buffer_sprintf(dst_param, "%s", src_param); 3049 return; 3050 } 3051 3052 if (src_data_type == WINED3D_DATA_FLOAT) 3053 { 3054 switch (dst_data_type) 3055 { 3056 case WINED3D_DATA_INT: 3057 string_buffer_sprintf(dst_param, "floatBitsToInt(%s)", src_param); 3058 return; 3059 case WINED3D_DATA_RESOURCE: 3060 case WINED3D_DATA_SAMPLER: 3061 case WINED3D_DATA_UINT: 3062 string_buffer_sprintf(dst_param, "floatBitsToUint(%s)", src_param); 3063 return; 3064 default: 3065 break; 3066 } 3067 } 3068 3069 if (src_data_type == WINED3D_DATA_UINT && dst_data_type == WINED3D_DATA_FLOAT) 3070 { 3071 string_buffer_sprintf(dst_param, "uintBitsToFloat(%s)", src_param); 3072 return; 3073 } 3074 3075 if (src_data_type == WINED3D_DATA_INT && dst_data_type == WINED3D_DATA_FLOAT) 3076 { 3077 string_buffer_sprintf(dst_param, "intBitsToFloat(%s)", src_param); 3078 return; 3079 } 3080 3081 FIXME("Unhandled cast from %#x to %#x.\n", src_data_type, dst_data_type); 3082 string_buffer_sprintf(dst_param, "%s", src_param); 3083 } 3084 3085 /* From a given parameter token, generate the corresponding GLSL string. 3086 * Also, return the actual register name and swizzle in case the 3087 * caller needs this information as well. */ 3088 static void shader_glsl_add_src_param_ext(const struct wined3d_shader_instruction *ins, 3089 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src, 3090 enum wined3d_data_type data_type) 3091 { 3092 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 3093 struct wined3d_string_buffer *reg_name = string_buffer_get(priv->string_buffers); 3094 enum wined3d_data_type param_data_type; 3095 BOOL is_color = FALSE; 3096 char swizzle_str[6]; 3097 3098 glsl_src->reg_name[0] = '\0'; 3099 glsl_src->param_str[0] = '\0'; 3100 swizzle_str[0] = '\0'; 3101 3102 shader_glsl_get_register_name(&wined3d_src->reg, data_type, glsl_src->reg_name, &is_color, ins); 3103 shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str); 3104 3105 switch (wined3d_src->reg.type) 3106 { 3107 case WINED3DSPR_IMMCONST: 3108 param_data_type = data_type; 3109 break; 3110 case WINED3DSPR_FORKINSTID: 3111 case WINED3DSPR_GSINSTID: 3112 case WINED3DSPR_JOININSTID: 3113 case WINED3DSPR_LOCALTHREADID: 3114 case WINED3DSPR_LOCALTHREADINDEX: 3115 case WINED3DSPR_OUTPOINTID: 3116 case WINED3DSPR_PRIMID: 3117 case WINED3DSPR_THREADGROUPID: 3118 case WINED3DSPR_THREADID: 3119 param_data_type = WINED3D_DATA_INT; 3120 break; 3121 default: 3122 param_data_type = WINED3D_DATA_FLOAT; 3123 break; 3124 } 3125 3126 shader_glsl_sprintf_cast(reg_name, glsl_src->reg_name, data_type, param_data_type); 3127 shader_glsl_gen_modifier(wined3d_src->modifiers, reg_name->buffer, swizzle_str, glsl_src->param_str); 3128 3129 string_buffer_release(priv->string_buffers, reg_name); 3130 } 3131 3132 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, 3133 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src) 3134 { 3135 shader_glsl_add_src_param_ext(ins, wined3d_src, mask, glsl_src, wined3d_src->reg.data_type); 3136 } 3137 3138 /* From a given parameter token, generate the corresponding GLSL string. 3139 * Also, return the actual register name and swizzle in case the 3140 * caller needs this information as well. */ 3141 static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction *ins, 3142 const struct wined3d_shader_dst_param *wined3d_dst, struct glsl_dst_param *glsl_dst) 3143 { 3144 BOOL is_color = FALSE; 3145 3146 glsl_dst->mask_str[0] = '\0'; 3147 glsl_dst->reg_name[0] = '\0'; 3148 3149 shader_glsl_get_register_name(&wined3d_dst->reg, wined3d_dst->reg.data_type, 3150 glsl_dst->reg_name, &is_color, ins); 3151 return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str); 3152 } 3153 3154 /* Append the destination part of the instruction to the buffer, return the effective write mask */ 3155 static DWORD shader_glsl_append_dst_ext(struct wined3d_string_buffer *buffer, 3156 const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst, 3157 enum wined3d_data_type data_type) 3158 { 3159 struct glsl_dst_param glsl_dst; 3160 DWORD mask; 3161 3162 if ((mask = shader_glsl_add_dst_param(ins, dst, &glsl_dst))) 3163 { 3164 switch (data_type) 3165 { 3166 case WINED3D_DATA_FLOAT: 3167 shader_addline(buffer, "%s%s = %s(", 3168 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3169 break; 3170 case WINED3D_DATA_INT: 3171 shader_addline(buffer, "%s%s = %sintBitsToFloat(", 3172 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3173 break; 3174 case WINED3D_DATA_RESOURCE: 3175 case WINED3D_DATA_SAMPLER: 3176 case WINED3D_DATA_UINT: 3177 shader_addline(buffer, "%s%s = %suintBitsToFloat(", 3178 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3179 break; 3180 default: 3181 FIXME("Unhandled data type %#x.\n", data_type); 3182 shader_addline(buffer, "%s%s = %s(", 3183 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3184 break; 3185 } 3186 } 3187 3188 return mask; 3189 } 3190 3191 /* Append the destination part of the instruction to the buffer, return the effective write mask */ 3192 static DWORD shader_glsl_append_dst(struct wined3d_string_buffer *buffer, const struct wined3d_shader_instruction *ins) 3193 { 3194 return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 3195 } 3196 3197 /** Process GLSL instruction modifiers */ 3198 static void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) 3199 { 3200 struct glsl_dst_param dst_param; 3201 DWORD modifiers; 3202 3203 if (!ins->dst_count) return; 3204 3205 modifiers = ins->dst[0].modifiers; 3206 if (!modifiers) return; 3207 3208 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 3209 3210 if (modifiers & WINED3DSPDM_SATURATE) 3211 { 3212 /* _SAT means to clamp the value of the register to between 0 and 1 */ 3213 shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name, 3214 dst_param.mask_str, dst_param.reg_name, dst_param.mask_str); 3215 } 3216 3217 if (modifiers & WINED3DSPDM_MSAMPCENTROID) 3218 { 3219 FIXME("_centroid modifier not handled\n"); 3220 } 3221 3222 if (modifiers & WINED3DSPDM_PARTIALPRECISION) 3223 { 3224 /* MSDN says this modifier can be safely ignored, so that's what we'll do. */ 3225 } 3226 } 3227 3228 static const char *shader_glsl_get_rel_op(enum wined3d_shader_rel_op op) 3229 { 3230 switch (op) 3231 { 3232 case WINED3D_SHADER_REL_OP_GT: return ">"; 3233 case WINED3D_SHADER_REL_OP_EQ: return "=="; 3234 case WINED3D_SHADER_REL_OP_GE: return ">="; 3235 case WINED3D_SHADER_REL_OP_LT: return "<"; 3236 case WINED3D_SHADER_REL_OP_NE: return "!="; 3237 case WINED3D_SHADER_REL_OP_LE: return "<="; 3238 default: 3239 FIXME("Unrecognized operator %#x.\n", op); 3240 return "(\?\?)"; 3241 } 3242 } 3243 3244 static BOOL shader_glsl_has_core_grad(const struct wined3d_gl_info *gl_info) 3245 { 3246 return shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4]; 3247 } 3248 3249 static void shader_glsl_get_coord_size(enum wined3d_shader_resource_type resource_type, 3250 unsigned int *coord_size, unsigned int *deriv_size) 3251 { 3252 const BOOL is_array = resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY 3253 || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY; 3254 3255 *coord_size = resource_type_info[resource_type].coord_size; 3256 *deriv_size = *coord_size; 3257 if (is_array) 3258 --(*deriv_size); 3259 } 3260 3261 static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx, 3262 DWORD resource_idx, DWORD sampler_idx, DWORD flags, struct glsl_sample_function *sample_function) 3263 { 3264 enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type; 3265 struct shader_glsl_ctx_priv *priv = ctx->backend_data; 3266 const struct wined3d_gl_info *gl_info = ctx->gl_info; 3267 BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx); 3268 BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED; 3269 BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL 3270 && priv->cur_ps_args->np2_fixup & (1u << resource_idx) 3271 && gl_info->supported[ARB_TEXTURE_RECTANGLE]; 3272 BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD; 3273 BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD; 3274 BOOL offset = flags & WINED3D_GLSL_SAMPLE_OFFSET; 3275 const char *base = "texture", *type_part = "", *suffix = ""; 3276 unsigned int coord_size, deriv_size; 3277 3278 sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type; 3279 3280 if (resource_type >= ARRAY_SIZE(resource_type_info)) 3281 { 3282 ERR("Unexpected resource type %#x.\n", resource_type); 3283 resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; 3284 } 3285 3286 /* Note that there's no such thing as a projected cube texture. */ 3287 if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) 3288 projected = FALSE; 3289 3290 if (needs_legacy_glsl_syntax(gl_info)) 3291 { 3292 if (shadow) 3293 base = "shadow"; 3294 3295 type_part = resource_type_info[resource_type].type_part; 3296 if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect) 3297 type_part = "2DRect"; 3298 if (!type_part[0] && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY) 3299 FIXME("Unhandled resource type %#x.\n", resource_type); 3300 3301 if (!lod && grad && !shader_glsl_has_core_grad(gl_info)) 3302 { 3303 if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 3304 suffix = "ARB"; 3305 else 3306 FIXME("Unsupported grad function.\n"); 3307 } 3308 } 3309 3310 if (flags & WINED3D_GLSL_SAMPLE_LOAD) 3311 { 3312 static const DWORD texel_fetch_flags = WINED3D_GLSL_SAMPLE_LOAD | WINED3D_GLSL_SAMPLE_OFFSET; 3313 if (flags & ~texel_fetch_flags) 3314 ERR("Unexpected flags %#x for texelFetch.\n", flags & ~texel_fetch_flags); 3315 3316 base = "texelFetch"; 3317 type_part = ""; 3318 } 3319 3320 sample_function->name = string_buffer_get(priv->string_buffers); 3321 string_buffer_sprintf(sample_function->name, "%s%s%s%s%s%s", base, type_part, projected ? "Proj" : "", 3322 lod ? "Lod" : grad ? "Grad" : "", offset ? "Offset" : "", suffix); 3323 3324 shader_glsl_get_coord_size(resource_type, &coord_size, &deriv_size); 3325 if (shadow) 3326 ++coord_size; 3327 sample_function->offset_size = offset ? deriv_size : 0; 3328 sample_function->coord_mask = (1u << coord_size) - 1; 3329 sample_function->deriv_mask = (1u << deriv_size) - 1; 3330 sample_function->output_single_component = shadow && !needs_legacy_glsl_syntax(gl_info); 3331 } 3332 3333 static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx, 3334 struct glsl_sample_function *sample_function) 3335 { 3336 const struct shader_glsl_ctx_priv *priv = ctx->backend_data; 3337 3338 string_buffer_release(priv->string_buffers, sample_function->name); 3339 } 3340 3341 static void shader_glsl_append_fixup_arg(char *arguments, const char *reg_name, 3342 BOOL sign_fixup, enum fixup_channel_source channel_source) 3343 { 3344 switch(channel_source) 3345 { 3346 case CHANNEL_SOURCE_ZERO: 3347 strcat(arguments, "0.0"); 3348 break; 3349 3350 case CHANNEL_SOURCE_ONE: 3351 strcat(arguments, "1.0"); 3352 break; 3353 3354 case CHANNEL_SOURCE_X: 3355 strcat(arguments, reg_name); 3356 strcat(arguments, ".x"); 3357 break; 3358 3359 case CHANNEL_SOURCE_Y: 3360 strcat(arguments, reg_name); 3361 strcat(arguments, ".y"); 3362 break; 3363 3364 case CHANNEL_SOURCE_Z: 3365 strcat(arguments, reg_name); 3366 strcat(arguments, ".z"); 3367 break; 3368 3369 case CHANNEL_SOURCE_W: 3370 strcat(arguments, reg_name); 3371 strcat(arguments, ".w"); 3372 break; 3373 3374 default: 3375 FIXME("Unhandled channel source %#x\n", channel_source); 3376 strcat(arguments, "undefined"); 3377 break; 3378 } 3379 3380 if (sign_fixup) strcat(arguments, " * 2.0 - 1.0"); 3381 } 3382 3383 static void shader_glsl_color_correction_ext(struct wined3d_string_buffer *buffer, 3384 const char *reg_name, DWORD mask, struct color_fixup_desc fixup) 3385 { 3386 unsigned int mask_size, remaining; 3387 DWORD fixup_mask = 0; 3388 char arguments[256]; 3389 char mask_str[6]; 3390 3391 if (fixup.x_sign_fixup || fixup.x_source != CHANNEL_SOURCE_X) fixup_mask |= WINED3DSP_WRITEMASK_0; 3392 if (fixup.y_sign_fixup || fixup.y_source != CHANNEL_SOURCE_Y) fixup_mask |= WINED3DSP_WRITEMASK_1; 3393 if (fixup.z_sign_fixup || fixup.z_source != CHANNEL_SOURCE_Z) fixup_mask |= WINED3DSP_WRITEMASK_2; 3394 if (fixup.w_sign_fixup || fixup.w_source != CHANNEL_SOURCE_W) fixup_mask |= WINED3DSP_WRITEMASK_3; 3395 if (!(mask &= fixup_mask)) 3396 return; 3397 3398 if (is_complex_fixup(fixup)) 3399 { 3400 enum complex_fixup complex_fixup = get_complex_fixup(fixup); 3401 FIXME("Complex fixup (%#x) not supported\n",complex_fixup); 3402 return; 3403 } 3404 3405 shader_glsl_write_mask_to_str(mask, mask_str); 3406 mask_size = shader_glsl_get_write_mask_size(mask); 3407 3408 arguments[0] = '\0'; 3409 remaining = mask_size; 3410 if (mask & WINED3DSP_WRITEMASK_0) 3411 { 3412 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.x_sign_fixup, fixup.x_source); 3413 if (--remaining) strcat(arguments, ", "); 3414 } 3415 if (mask & WINED3DSP_WRITEMASK_1) 3416 { 3417 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.y_sign_fixup, fixup.y_source); 3418 if (--remaining) strcat(arguments, ", "); 3419 } 3420 if (mask & WINED3DSP_WRITEMASK_2) 3421 { 3422 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.z_sign_fixup, fixup.z_source); 3423 if (--remaining) strcat(arguments, ", "); 3424 } 3425 if (mask & WINED3DSP_WRITEMASK_3) 3426 { 3427 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.w_sign_fixup, fixup.w_source); 3428 if (--remaining) strcat(arguments, ", "); 3429 } 3430 3431 if (mask_size > 1) 3432 shader_addline(buffer, "%s%s = vec%u(%s);\n", reg_name, mask_str, mask_size, arguments); 3433 else 3434 shader_addline(buffer, "%s%s = %s;\n", reg_name, mask_str, arguments); 3435 } 3436 3437 static void shader_glsl_color_correction(const struct wined3d_shader_instruction *ins, struct color_fixup_desc fixup) 3438 { 3439 char reg_name[256]; 3440 BOOL is_color; 3441 3442 shader_glsl_get_register_name(&ins->dst[0].reg, ins->dst[0].reg.data_type, reg_name, &is_color, ins); 3443 shader_glsl_color_correction_ext(ins->ctx->buffer, reg_name, ins->dst[0].write_mask, fixup); 3444 } 3445 3446 static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins, 3447 unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, DWORD swizzle, 3448 const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset, 3449 const char *coord_reg_fmt, ...) 3450 { 3451 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; 3452 char dst_swizzle[6]; 3453 struct color_fixup_desc fixup; 3454 BOOL np2_fixup = FALSE; 3455 va_list args; 3456 int ret; 3457 3458 shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); 3459 3460 /* If ARB_texture_swizzle is supported we don't need to do anything here. 3461 * We actually rely on it for vertex shaders and SM4+. */ 3462 if (version->type == WINED3D_SHADER_TYPE_PIXEL && version->major < 4) 3463 { 3464 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 3465 fixup = priv->cur_ps_args->color_fixup[sampler_bind_idx]; 3466 3467 if (priv->cur_ps_args->np2_fixup & (1u << sampler_bind_idx)) 3468 np2_fixup = TRUE; 3469 } 3470 else 3471 { 3472 fixup = COLOR_FIXUP_IDENTITY; 3473 } 3474 3475 shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], sample_function->data_type); 3476 3477 if (sample_function->output_single_component) 3478 shader_addline(ins->ctx->buffer, "vec4("); 3479 3480 shader_addline(ins->ctx->buffer, "%s(%s_sampler%u, ", 3481 sample_function->name->buffer, shader_glsl_get_prefix(version->type), sampler_bind_idx); 3482 3483 for (;;) 3484 { 3485 va_start(args, coord_reg_fmt); 3486 ret = shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args); 3487 va_end(args); 3488 if (!ret) 3489 break; 3490 if (!string_buffer_resize(ins->ctx->buffer, ret)) 3491 break; 3492 } 3493 3494 if (np2_fixup) 3495 { 3496 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 3497 const unsigned char idx = priv->cur_np2fixup_info->idx[sampler_bind_idx]; 3498 3499 switch (shader_glsl_get_write_mask_size(sample_function->coord_mask)) 3500 { 3501 case 1: 3502 shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s", 3503 idx >> 1, (idx % 2) ? "z" : "x"); 3504 break; 3505 case 2: 3506 shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s", 3507 idx >> 1, (idx % 2) ? "zw" : "xy"); 3508 break; 3509 case 3: 3510 shader_addline(ins->ctx->buffer, " * vec3(ps_samplerNP2Fixup[%u].%s, 1.0)", 3511 idx >> 1, (idx % 2) ? "zw" : "xy"); 3512 break; 3513 case 4: 3514 shader_addline(ins->ctx->buffer, " * vec4(ps_samplerNP2Fixup[%u].%s, 1.0, 1.0)", 3515 idx >> 1, (idx % 2) ? "zw" : "xy"); 3516 break; 3517 } 3518 } 3519 if (dx && dy) 3520 shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy); 3521 else if (bias) 3522 shader_addline(ins->ctx->buffer, ", %s", bias); 3523 if (sample_function->offset_size) 3524 { 3525 int offset_immdata[4] = {offset->u, offset->v, offset->w}; 3526 shader_addline(ins->ctx->buffer, ", "); 3527 shader_glsl_append_imm_ivec(ins->ctx->buffer, offset_immdata, sample_function->offset_size); 3528 } 3529 shader_addline(ins->ctx->buffer, ")"); 3530 3531 if (sample_function->output_single_component) 3532 shader_addline(ins->ctx->buffer, ")"); 3533 3534 shader_addline(ins->ctx->buffer, "%s);\n", dst_swizzle); 3535 3536 if (!is_identity_fixup(fixup)) 3537 shader_glsl_color_correction(ins, fixup); 3538 } 3539 3540 static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer, BOOL use_viewport_index) 3541 { 3542 /* Write the final position. 3543 * 3544 * OpenGL coordinates specify the center of the pixel while D3D coords 3545 * specify the corner. The offsets are stored in z and w in 3546 * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering 3547 * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow 3548 * a MAD. */ 3549 if (use_viewport_index) 3550 { 3551 shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup[gl_ViewportIndex].y;\n"); 3552 shader_addline(buffer, "gl_Position.xy += pos_fixup[gl_ViewportIndex].zw * gl_Position.ww;\n"); 3553 } 3554 else 3555 { 3556 shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n"); 3557 shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n"); 3558 } 3559 3560 /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix() 3561 * in utils.c 3562 * 3563 * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, 3564 * shaders are run before the homogeneous divide, so we have to take the w 3565 * into account: z = ((z / w) * 2 - 1) * w, which is the same as 3566 * z = z * 2 - w. */ 3567 shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); 3568 } 3569 3570 /***************************************************************************** 3571 * Begin processing individual instruction opcodes 3572 ****************************************************************************/ 3573 3574 static void shader_glsl_binop(const struct wined3d_shader_instruction *ins) 3575 { 3576 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3577 struct glsl_src_param src0_param; 3578 struct glsl_src_param src1_param; 3579 DWORD write_mask; 3580 const char *op; 3581 3582 /* Determine the GLSL operator to use based on the opcode */ 3583 switch (ins->handler_idx) 3584 { 3585 case WINED3DSIH_ADD: op = "+"; break; 3586 case WINED3DSIH_AND: op = "&"; break; 3587 case WINED3DSIH_DIV: op = "/"; break; 3588 case WINED3DSIH_IADD: op = "+"; break; 3589 case WINED3DSIH_ISHL: op = "<<"; break; 3590 case WINED3DSIH_ISHR: op = ">>"; break; 3591 case WINED3DSIH_MUL: op = "*"; break; 3592 case WINED3DSIH_OR: op = "|"; break; 3593 case WINED3DSIH_SUB: op = "-"; break; 3594 case WINED3DSIH_USHR: op = ">>"; break; 3595 case WINED3DSIH_XOR: op = "^"; break; 3596 default: 3597 op = "<unhandled operator>"; 3598 FIXME("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 3599 break; 3600 } 3601 3602 write_mask = shader_glsl_append_dst(buffer, ins); 3603 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3604 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3605 shader_addline(buffer, "%s %s %s);\n", src0_param.param_str, op, src1_param.param_str); 3606 } 3607 3608 static void shader_glsl_relop(const struct wined3d_shader_instruction *ins) 3609 { 3610 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3611 struct glsl_src_param src0_param; 3612 struct glsl_src_param src1_param; 3613 unsigned int mask_size; 3614 DWORD write_mask; 3615 const char *op; 3616 3617 write_mask = shader_glsl_append_dst(buffer, ins); 3618 mask_size = shader_glsl_get_write_mask_size(write_mask); 3619 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3620 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3621 3622 if (mask_size > 1) 3623 { 3624 switch (ins->handler_idx) 3625 { 3626 case WINED3DSIH_EQ: op = "equal"; break; 3627 case WINED3DSIH_IEQ: op = "equal"; break; 3628 case WINED3DSIH_GE: op = "greaterThanEqual"; break; 3629 case WINED3DSIH_IGE: op = "greaterThanEqual"; break; 3630 case WINED3DSIH_UGE: op = "greaterThanEqual"; break; 3631 case WINED3DSIH_LT: op = "lessThan"; break; 3632 case WINED3DSIH_ILT: op = "lessThan"; break; 3633 case WINED3DSIH_ULT: op = "lessThan"; break; 3634 case WINED3DSIH_NE: op = "notEqual"; break; 3635 case WINED3DSIH_INE: op = "notEqual"; break; 3636 default: 3637 op = "<unhandled operator>"; 3638 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 3639 break; 3640 } 3641 3642 shader_addline(buffer, "uvec%u(%s(%s, %s)) * 0xffffffffu);\n", 3643 mask_size, op, src0_param.param_str, src1_param.param_str); 3644 } 3645 else 3646 { 3647 switch (ins->handler_idx) 3648 { 3649 case WINED3DSIH_EQ: op = "=="; break; 3650 case WINED3DSIH_IEQ: op = "=="; break; 3651 case WINED3DSIH_GE: op = ">="; break; 3652 case WINED3DSIH_IGE: op = ">="; break; 3653 case WINED3DSIH_UGE: op = ">="; break; 3654 case WINED3DSIH_LT: op = "<"; break; 3655 case WINED3DSIH_ILT: op = "<"; break; 3656 case WINED3DSIH_ULT: op = "<"; break; 3657 case WINED3DSIH_NE: op = "!="; break; 3658 case WINED3DSIH_INE: op = "!="; break; 3659 default: 3660 op = "<unhandled operator>"; 3661 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 3662 break; 3663 } 3664 3665 shader_addline(buffer, "%s %s %s ? 0xffffffffu : 0u);\n", 3666 src0_param.param_str, op, src1_param.param_str); 3667 } 3668 } 3669 3670 static void shader_glsl_unary_op(const struct wined3d_shader_instruction *ins) 3671 { 3672 struct glsl_src_param src_param; 3673 DWORD write_mask; 3674 const char *op; 3675 3676 switch (ins->handler_idx) 3677 { 3678 case WINED3DSIH_INEG: op = "-"; break; 3679 case WINED3DSIH_NOT: op = "~"; break; 3680 default: 3681 op = "<unhandled operator>"; 3682 ERR("Unhandled opcode %s.\n", 3683 debug_d3dshaderinstructionhandler(ins->handler_idx)); 3684 break; 3685 } 3686 3687 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 3688 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 3689 shader_addline(ins->ctx->buffer, "%s%s);\n", op, src_param.param_str); 3690 } 3691 3692 static void shader_glsl_mul_extended(const struct wined3d_shader_instruction *ins) 3693 { 3694 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3695 struct glsl_src_param src0_param; 3696 struct glsl_src_param src1_param; 3697 DWORD write_mask; 3698 3699 /* If we have ARB_gpu_shader5, we can use imulExtended() / umulExtended(). 3700 * If not, we can emulate it. */ 3701 if (ins->dst[0].reg.type != WINED3DSPR_NULL) 3702 FIXME("64-bit integer multiplies not implemented.\n"); 3703 3704 if (ins->dst[1].reg.type != WINED3DSPR_NULL) 3705 { 3706 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 3707 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3708 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3709 3710 shader_addline(ins->ctx->buffer, "%s * %s);\n", 3711 src0_param.param_str, src1_param.param_str); 3712 } 3713 } 3714 3715 static void shader_glsl_udiv(const struct wined3d_shader_instruction *ins) 3716 { 3717 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3718 struct glsl_src_param src0_param, src1_param; 3719 DWORD write_mask; 3720 3721 if (ins->dst[0].reg.type != WINED3DSPR_NULL) 3722 { 3723 if (ins->dst[1].reg.type != WINED3DSPR_NULL) 3724 { 3725 char dst_mask[6]; 3726 3727 write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 3728 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3729 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3730 shader_addline(buffer, "tmp0%s = uintBitsToFloat(%s / %s);\n", 3731 dst_mask, src0_param.param_str, src1_param.param_str); 3732 3733 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 3734 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3735 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3736 shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str); 3737 3738 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT); 3739 shader_addline(buffer, "tmp0%s);\n", dst_mask); 3740 } 3741 else 3742 { 3743 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 3744 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3745 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3746 shader_addline(buffer, "%s / %s);\n", src0_param.param_str, src1_param.param_str); 3747 } 3748 } 3749 else if (ins->dst[1].reg.type != WINED3DSPR_NULL) 3750 { 3751 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 3752 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3753 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3754 shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str); 3755 } 3756 } 3757 3758 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ 3759 static void shader_glsl_mov(const struct wined3d_shader_instruction *ins) 3760 { 3761 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 3762 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3763 struct glsl_src_param src0_param; 3764 DWORD write_mask; 3765 3766 write_mask = shader_glsl_append_dst(buffer, ins); 3767 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3768 3769 /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later 3770 * shader versions WINED3DSIO_MOVA is used for this. */ 3771 if (ins->ctx->reg_maps->shader_version.major == 1 3772 && ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX 3773 && ins->dst[0].reg.type == WINED3DSPR_ADDR) 3774 { 3775 /* This is a simple floor() */ 3776 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); 3777 if (mask_size > 1) { 3778 shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str); 3779 } else { 3780 shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str); 3781 } 3782 } 3783 else if (ins->handler_idx == WINED3DSIH_MOVA) 3784 { 3785 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); 3786 3787 if (shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4]) 3788 { 3789 if (mask_size > 1) 3790 shader_addline(buffer, "ivec%d(round(%s)));\n", mask_size, src0_param.param_str); 3791 else 3792 shader_addline(buffer, "int(round(%s)));\n", src0_param.param_str); 3793 } 3794 else 3795 { 3796 if (mask_size > 1) 3797 shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n", 3798 mask_size, src0_param.param_str, mask_size, src0_param.param_str); 3799 else 3800 shader_addline(buffer, "int(floor(abs(%s) + 0.5) * sign(%s)));\n", 3801 src0_param.param_str, src0_param.param_str); 3802 } 3803 } 3804 else 3805 { 3806 shader_addline(buffer, "%s);\n", src0_param.param_str); 3807 } 3808 } 3809 3810 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */ 3811 static void shader_glsl_dot(const struct wined3d_shader_instruction *ins) 3812 { 3813 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3814 struct glsl_src_param src0_param; 3815 struct glsl_src_param src1_param; 3816 DWORD dst_write_mask, src_write_mask; 3817 unsigned int dst_size; 3818 3819 dst_write_mask = shader_glsl_append_dst(buffer, ins); 3820 dst_size = shader_glsl_get_write_mask_size(dst_write_mask); 3821 3822 /* dp4 works on vec4, dp3 on vec3, etc. */ 3823 if (ins->handler_idx == WINED3DSIH_DP4) 3824 src_write_mask = WINED3DSP_WRITEMASK_ALL; 3825 else if (ins->handler_idx == WINED3DSIH_DP3) 3826 src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 3827 else 3828 src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; 3829 3830 shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param); 3831 shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param); 3832 3833 if (dst_size > 1) { 3834 shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str); 3835 } else { 3836 shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str); 3837 } 3838 } 3839 3840 /* Note that this instruction has some restrictions. The destination write mask 3841 * can't contain the w component, and the source swizzles have to be .xyzw */ 3842 static void shader_glsl_cross(const struct wined3d_shader_instruction *ins) 3843 { 3844 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 3845 struct glsl_src_param src0_param; 3846 struct glsl_src_param src1_param; 3847 char dst_mask[6]; 3848 3849 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 3850 shader_glsl_append_dst(ins->ctx->buffer, ins); 3851 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 3852 shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param); 3853 shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask); 3854 } 3855 3856 static void shader_glsl_cut(const struct wined3d_shader_instruction *ins) 3857 { 3858 unsigned int stream = ins->handler_idx == WINED3DSIH_CUT ? 0 : ins->src[0].reg.idx[0].offset; 3859 3860 if (!stream) 3861 shader_addline(ins->ctx->buffer, "EndPrimitive();\n"); 3862 else 3863 FIXME("Unhandled primitive stream %u.\n", stream); 3864 } 3865 3866 /* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1) 3867 * Src0 and src1 are scalars. Note that D3D uses the absolute of src0, while 3868 * GLSL uses the value as-is. */ 3869 static void shader_glsl_pow(const struct wined3d_shader_instruction *ins) 3870 { 3871 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3872 struct glsl_src_param src0_param; 3873 struct glsl_src_param src1_param; 3874 DWORD dst_write_mask; 3875 unsigned int dst_size; 3876 3877 dst_write_mask = shader_glsl_append_dst(buffer, ins); 3878 dst_size = shader_glsl_get_write_mask_size(dst_write_mask); 3879 3880 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 3881 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 3882 3883 if (dst_size > 1) 3884 { 3885 shader_addline(buffer, "vec%u(%s == 0.0 ? 1.0 : pow(abs(%s), %s)));\n", 3886 dst_size, src1_param.param_str, src0_param.param_str, src1_param.param_str); 3887 } 3888 else 3889 { 3890 shader_addline(buffer, "%s == 0.0 ? 1.0 : pow(abs(%s), %s));\n", 3891 src1_param.param_str, src0_param.param_str, src1_param.param_str); 3892 } 3893 } 3894 3895 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */ 3896 static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins) 3897 { 3898 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3899 struct glsl_src_param src_param; 3900 const char *instruction; 3901 DWORD write_mask; 3902 unsigned i; 3903 3904 /* Determine the GLSL function to use based on the opcode */ 3905 /* TODO: Possibly make this a table for faster lookups */ 3906 switch (ins->handler_idx) 3907 { 3908 case WINED3DSIH_ABS: instruction = "abs"; break; 3909 case WINED3DSIH_BFREV: instruction = "bitfieldReverse"; break; 3910 case WINED3DSIH_COUNTBITS: instruction = "bitCount"; break; 3911 case WINED3DSIH_DSX: instruction = "dFdx"; break; 3912 case WINED3DSIH_DSX_COARSE: instruction = "dFdxCoarse"; break; 3913 case WINED3DSIH_DSX_FINE: instruction = "dFdxFine"; break; 3914 case WINED3DSIH_DSY: instruction = "ycorrection.y * dFdy"; break; 3915 case WINED3DSIH_DSY_COARSE: instruction = "ycorrection.y * dFdyCoarse"; break; 3916 case WINED3DSIH_DSY_FINE: instruction = "ycorrection.y * dFdyFine"; break; 3917 case WINED3DSIH_FIRSTBIT_HI: instruction = "findMSB"; break; 3918 case WINED3DSIH_FIRSTBIT_LO: instruction = "findLSB"; break; 3919 case WINED3DSIH_FIRSTBIT_SHI: instruction = "findMSB"; break; 3920 case WINED3DSIH_FRC: instruction = "fract"; break; 3921 case WINED3DSIH_IMAX: instruction = "max"; break; 3922 case WINED3DSIH_IMIN: instruction = "min"; break; 3923 case WINED3DSIH_MAX: instruction = "max"; break; 3924 case WINED3DSIH_MIN: instruction = "min"; break; 3925 case WINED3DSIH_ROUND_NE: instruction = "roundEven"; break; 3926 case WINED3DSIH_ROUND_NI: instruction = "floor"; break; 3927 case WINED3DSIH_ROUND_PI: instruction = "ceil"; break; 3928 case WINED3DSIH_ROUND_Z: instruction = "trunc"; break; 3929 case WINED3DSIH_SQRT: instruction = "sqrt"; break; 3930 case WINED3DSIH_UMAX: instruction = "max"; break; 3931 case WINED3DSIH_UMIN: instruction = "min"; break; 3932 default: instruction = ""; 3933 ERR("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 3934 break; 3935 } 3936 3937 write_mask = shader_glsl_append_dst(buffer, ins); 3938 3939 /* In D3D bits are numbered from the most significant bit. */ 3940 if (ins->handler_idx == WINED3DSIH_FIRSTBIT_HI || ins->handler_idx == WINED3DSIH_FIRSTBIT_SHI) 3941 shader_addline(buffer, "31 - "); 3942 shader_addline(buffer, "%s(", instruction); 3943 3944 if (ins->src_count) 3945 { 3946 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 3947 shader_addline(buffer, "%s", src_param.param_str); 3948 for (i = 1; i < ins->src_count; ++i) 3949 { 3950 shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param); 3951 shader_addline(buffer, ", %s", src_param.param_str); 3952 } 3953 } 3954 3955 shader_addline(buffer, "));\n"); 3956 } 3957 3958 static void shader_glsl_float16(const struct wined3d_shader_instruction *ins) 3959 { 3960 struct wined3d_shader_dst_param dst; 3961 struct glsl_src_param src; 3962 DWORD write_mask; 3963 const char *fmt; 3964 unsigned int i; 3965 3966 fmt = ins->handler_idx == WINED3DSIH_F16TOF32 3967 ? "unpackHalf2x16(%s).x);\n" : "packHalf2x16(vec2(%s, 0.0)));\n"; 3968 3969 dst = ins->dst[0]; 3970 for (i = 0; i < 4; ++i) 3971 { 3972 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i); 3973 if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, 3974 &dst, dst.reg.data_type))) 3975 continue; 3976 3977 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src); 3978 shader_addline(ins->ctx->buffer, fmt, src.param_str); 3979 } 3980 } 3981 3982 static void shader_glsl_bitwise_op(const struct wined3d_shader_instruction *ins) 3983 { 3984 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3985 struct wined3d_shader_dst_param dst; 3986 struct glsl_src_param src[4]; 3987 const char *instruction; 3988 BOOL tmp_dst = FALSE; 3989 char mask_char[6]; 3990 unsigned int i, j; 3991 DWORD write_mask; 3992 3993 switch (ins->handler_idx) 3994 { 3995 case WINED3DSIH_BFI: instruction = "bitfieldInsert"; break; 3996 case WINED3DSIH_IBFE: instruction = "bitfieldExtract"; break; 3997 case WINED3DSIH_UBFE: instruction = "bitfieldExtract"; break; 3998 default: 3999 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 4000 return; 4001 } 4002 4003 for (i = 0; i < ins->src_count; ++i) 4004 { 4005 if (ins->dst[0].reg.idx[0].offset == ins->src[i].reg.idx[0].offset 4006 && ins->dst[0].reg.type == ins->src[i].reg.type) 4007 tmp_dst = TRUE; 4008 } 4009 4010 dst = ins->dst[0]; 4011 for (i = 0; i < 4; ++i) 4012 { 4013 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i); 4014 if (tmp_dst && (write_mask = shader_glsl_get_write_mask(&dst, mask_char))) 4015 shader_addline(buffer, "tmp0%s = %sBitsToFloat(", mask_char, 4016 dst.reg.data_type == WINED3D_DATA_INT ? "int" : "uint"); 4017 else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst, dst.reg.data_type))) 4018 continue; 4019 4020 for (j = 0; j < ins->src_count; ++j) 4021 shader_glsl_add_src_param(ins, &ins->src[j], write_mask, &src[j]); 4022 shader_addline(buffer, "%s(", instruction); 4023 for (j = 0; j < ins->src_count - 2; ++j) 4024 shader_addline(buffer, "%s, ", src[ins->src_count - j - 1].param_str); 4025 shader_addline(buffer, "%s & 0x1f, %s & 0x1f));\n", src[1].param_str, src[0].param_str); 4026 } 4027 4028 if (tmp_dst) 4029 { 4030 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT); 4031 shader_glsl_get_write_mask(&ins->dst[0], mask_char); 4032 shader_addline(buffer, "tmp0%s);\n", mask_char); 4033 } 4034 } 4035 4036 static void shader_glsl_nop(const struct wined3d_shader_instruction *ins) {} 4037 4038 static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins) 4039 { 4040 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4041 struct glsl_src_param src_param; 4042 unsigned int mask_size; 4043 DWORD write_mask; 4044 char dst_mask[6]; 4045 4046 write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask); 4047 mask_size = shader_glsl_get_write_mask_size(write_mask); 4048 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 4049 4050 shader_addline(buffer, "tmp0.x = dot(%s, %s);\n", 4051 src_param.param_str, src_param.param_str); 4052 shader_glsl_append_dst(buffer, ins); 4053 4054 if (mask_size > 1) 4055 { 4056 shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s * inversesqrt(tmp0.x)));\n", 4057 mask_size, src_param.param_str); 4058 } 4059 else 4060 { 4061 shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s * inversesqrt(tmp0.x)));\n", 4062 src_param.param_str); 4063 } 4064 } 4065 4066 static void shader_glsl_scalar_op(const struct wined3d_shader_instruction *ins) 4067 { 4068 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, 4069 ins->ctx->reg_maps->shader_version.minor); 4070 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4071 struct glsl_src_param src0_param; 4072 const char *prefix, *suffix; 4073 unsigned int dst_size; 4074 DWORD dst_write_mask; 4075 4076 dst_write_mask = shader_glsl_append_dst(buffer, ins); 4077 dst_size = shader_glsl_get_write_mask_size(dst_write_mask); 4078 4079 if (shader_version < WINED3D_SHADER_VERSION(4, 0)) 4080 dst_write_mask = WINED3DSP_WRITEMASK_3; 4081 4082 shader_glsl_add_src_param(ins, &ins->src[0], dst_write_mask, &src0_param); 4083 4084 switch (ins->handler_idx) 4085 { 4086 case WINED3DSIH_EXP: 4087 case WINED3DSIH_EXPP: 4088 prefix = "exp2("; 4089 suffix = ")"; 4090 break; 4091 4092 case WINED3DSIH_LOG: 4093 case WINED3DSIH_LOGP: 4094 prefix = "log2(abs("; 4095 suffix = "))"; 4096 break; 4097 4098 case WINED3DSIH_RCP: 4099 prefix = "1.0 / "; 4100 suffix = ""; 4101 break; 4102 4103 case WINED3DSIH_RSQ: 4104 prefix = "inversesqrt(abs("; 4105 suffix = "))"; 4106 break; 4107 4108 default: 4109 prefix = ""; 4110 suffix = ""; 4111 FIXME("Unhandled instruction %#x.\n", ins->handler_idx); 4112 break; 4113 } 4114 4115 if (dst_size > 1 && shader_version < WINED3D_SHADER_VERSION(4, 0)) 4116 shader_addline(buffer, "vec%u(%s%s%s));\n", dst_size, prefix, src0_param.param_str, suffix); 4117 else 4118 shader_addline(buffer, "%s%s%s);\n", prefix, src0_param.param_str, suffix); 4119 } 4120 4121 /** Process the WINED3DSIO_EXPP instruction in GLSL: 4122 * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable): 4123 * dst.x = 2^(floor(src)) 4124 * dst.y = src - floor(src) 4125 * dst.z = 2^src (partial precision is allowed, but optional) 4126 * dst.w = 1.0; 4127 * For 2.0 shaders, just do this (honoring writemask and swizzle): 4128 * dst = 2^src; (partial precision is allowed, but optional) 4129 */ 4130 static void shader_glsl_expp(const struct wined3d_shader_instruction *ins) 4131 { 4132 if (ins->ctx->reg_maps->shader_version.major < 2) 4133 { 4134 struct glsl_src_param src_param; 4135 char dst_mask[6]; 4136 4137 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param); 4138 4139 shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str); 4140 shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str); 4141 shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str); 4142 shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n"); 4143 4144 shader_glsl_append_dst(ins->ctx->buffer, ins); 4145 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4146 shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask); 4147 return; 4148 } 4149 4150 shader_glsl_scalar_op(ins); 4151 } 4152 4153 static void shader_glsl_cast(const struct wined3d_shader_instruction *ins, 4154 const char *vector_constructor, const char *scalar_constructor) 4155 { 4156 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4157 struct glsl_src_param src_param; 4158 unsigned int mask_size; 4159 DWORD write_mask; 4160 4161 write_mask = shader_glsl_append_dst(buffer, ins); 4162 mask_size = shader_glsl_get_write_mask_size(write_mask); 4163 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 4164 4165 if (mask_size > 1) 4166 shader_addline(buffer, "%s%u(%s));\n", vector_constructor, mask_size, src_param.param_str); 4167 else 4168 shader_addline(buffer, "%s(%s));\n", scalar_constructor, src_param.param_str); 4169 } 4170 4171 static void shader_glsl_to_int(const struct wined3d_shader_instruction *ins) 4172 { 4173 shader_glsl_cast(ins, "ivec", "int"); 4174 } 4175 4176 static void shader_glsl_to_uint(const struct wined3d_shader_instruction *ins) 4177 { 4178 shader_glsl_cast(ins, "uvec", "uint"); 4179 } 4180 4181 static void shader_glsl_to_float(const struct wined3d_shader_instruction *ins) 4182 { 4183 shader_glsl_cast(ins, "vec", "float"); 4184 } 4185 4186 /** Process signed comparison opcodes in GLSL. */ 4187 static void shader_glsl_compare(const struct wined3d_shader_instruction *ins) 4188 { 4189 struct glsl_src_param src0_param; 4190 struct glsl_src_param src1_param; 4191 DWORD write_mask; 4192 unsigned int mask_size; 4193 4194 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4195 mask_size = shader_glsl_get_write_mask_size(write_mask); 4196 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4197 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4198 4199 if (mask_size > 1) { 4200 const char *compare; 4201 4202 switch(ins->handler_idx) 4203 { 4204 case WINED3DSIH_SLT: compare = "lessThan"; break; 4205 case WINED3DSIH_SGE: compare = "greaterThanEqual"; break; 4206 default: compare = ""; 4207 FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 4208 } 4209 4210 shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare, 4211 src0_param.param_str, src1_param.param_str); 4212 } else { 4213 switch(ins->handler_idx) 4214 { 4215 case WINED3DSIH_SLT: 4216 /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed, 4217 * to return 0.0 but step returns 1.0 because step is not < x 4218 * An alternative is a bvec compare padded with an unused second component. 4219 * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same 4220 * issue. Playing with not() is not possible either because not() does not accept 4221 * a scalar. 4222 */ 4223 shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n", 4224 src0_param.param_str, src1_param.param_str); 4225 break; 4226 case WINED3DSIH_SGE: 4227 /* Here we can use the step() function and safe a conditional */ 4228 shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str); 4229 break; 4230 default: 4231 FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 4232 } 4233 4234 } 4235 } 4236 4237 static void shader_glsl_swapc(const struct wined3d_shader_instruction *ins) 4238 { 4239 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4240 struct wined3d_shader_dst_param dst[2]; 4241 struct glsl_src_param src[3]; 4242 unsigned int i, j, k; 4243 char mask_char[6]; 4244 DWORD write_mask; 4245 BOOL tmp_dst[2]; 4246 4247 for (i = 0; i < ins->dst_count; ++i) 4248 { 4249 tmp_dst[i] = FALSE; 4250 for (j = 0; j < ins->src_count; ++j) 4251 { 4252 if (ins->dst[i].reg.idx[0].offset == ins->src[j].reg.idx[0].offset 4253 && ins->dst[i].reg.type == ins->src[j].reg.type) 4254 tmp_dst[i] = TRUE; 4255 } 4256 } 4257 4258 dst[0] = ins->dst[0]; 4259 dst[1] = ins->dst[1]; 4260 for (i = 0; i < 4; ++i) 4261 { 4262 for (j = 0; j < ARRAY_SIZE(dst); ++j) 4263 { 4264 dst[j].write_mask = ins->dst[j].write_mask & (WINED3DSP_WRITEMASK_0 << i); 4265 if (tmp_dst[j] && (write_mask = shader_glsl_get_write_mask(&dst[j], mask_char))) 4266 shader_addline(buffer, "tmp%u%s = (", j, mask_char); 4267 else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst[j], dst[j].reg.data_type))) 4268 continue; 4269 4270 for (k = 0; k < ARRAY_SIZE(src); ++k) 4271 shader_glsl_add_src_param(ins, &ins->src[k], write_mask, &src[k]); 4272 4273 shader_addline(buffer, "%sbool(%s) ? %s : %s);\n", !j ? "!" : "", 4274 src[0].param_str, src[1].param_str, src[2].param_str); 4275 } 4276 } 4277 4278 for (i = 0; i < ARRAY_SIZE(tmp_dst); ++i) 4279 { 4280 if (tmp_dst[i]) 4281 { 4282 shader_glsl_get_write_mask(&ins->dst[i], mask_char); 4283 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[i], ins->dst[i].reg.data_type); 4284 shader_addline(buffer, "tmp%u%s);\n", i, mask_char); 4285 } 4286 } 4287 } 4288 4289 static void shader_glsl_conditional_move(const struct wined3d_shader_instruction *ins) 4290 { 4291 const char *condition_prefix, *condition_suffix; 4292 struct wined3d_shader_dst_param dst; 4293 struct glsl_src_param src0_param; 4294 struct glsl_src_param src1_param; 4295 struct glsl_src_param src2_param; 4296 BOOL temp_destination = FALSE; 4297 DWORD cmp_channel = 0; 4298 unsigned int i, j; 4299 char mask_char[6]; 4300 DWORD write_mask; 4301 4302 switch (ins->handler_idx) 4303 { 4304 case WINED3DSIH_CMP: 4305 condition_prefix = ""; 4306 condition_suffix = " >= 0.0"; 4307 break; 4308 4309 case WINED3DSIH_CND: 4310 condition_prefix = ""; 4311 condition_suffix = " > 0.5"; 4312 break; 4313 4314 case WINED3DSIH_MOVC: 4315 condition_prefix = "bool("; 4316 condition_suffix = ")"; 4317 break; 4318 4319 default: 4320 FIXME("Unhandled instruction %#x.\n", ins->handler_idx); 4321 condition_prefix = "<unhandled prefix>"; 4322 condition_suffix = "<unhandled suffix>"; 4323 break; 4324 } 4325 4326 if (shader_is_scalar(&ins->dst[0].reg) || shader_is_scalar(&ins->src[0].reg)) 4327 { 4328 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4329 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4330 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4331 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4332 4333 shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n", 4334 condition_prefix, src0_param.param_str, condition_suffix, 4335 src1_param.param_str, src2_param.param_str); 4336 return; 4337 } 4338 4339 dst = ins->dst[0]; 4340 4341 /* Splitting the instruction up in multiple lines imposes a problem: 4342 * The first lines may overwrite source parameters of the following lines. 4343 * Deal with that by using a temporary destination register if needed. */ 4344 if ((ins->src[0].reg.idx[0].offset == dst.reg.idx[0].offset 4345 && ins->src[0].reg.type == dst.reg.type) 4346 || (ins->src[1].reg.idx[0].offset == dst.reg.idx[0].offset 4347 && ins->src[1].reg.type == dst.reg.type) 4348 || (ins->src[2].reg.idx[0].offset == dst.reg.idx[0].offset 4349 && ins->src[2].reg.type == dst.reg.type)) 4350 temp_destination = TRUE; 4351 4352 /* Cycle through all source0 channels. */ 4353 for (i = 0; i < 4; ++i) 4354 { 4355 write_mask = 0; 4356 /* Find the destination channels which use the current source0 channel. */ 4357 for (j = 0; j < 4; ++j) 4358 { 4359 if (shader_glsl_swizzle_get_component(ins->src[0].swizzle, j) == i) 4360 { 4361 write_mask |= WINED3DSP_WRITEMASK_0 << j; 4362 cmp_channel = WINED3DSP_WRITEMASK_0 << j; 4363 } 4364 } 4365 dst.write_mask = ins->dst[0].write_mask & write_mask; 4366 4367 if (temp_destination) 4368 { 4369 if (!(write_mask = shader_glsl_get_write_mask(&dst, mask_char))) 4370 continue; 4371 shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char); 4372 } 4373 else if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type))) 4374 continue; 4375 4376 shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param); 4377 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4378 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4379 4380 shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n", 4381 condition_prefix, src0_param.param_str, condition_suffix, 4382 src1_param.param_str, src2_param.param_str); 4383 } 4384 4385 if (temp_destination) 4386 { 4387 shader_glsl_get_write_mask(&ins->dst[0], mask_char); 4388 shader_glsl_append_dst(ins->ctx->buffer, ins); 4389 shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char); 4390 } 4391 } 4392 4393 /** Process the CND opcode in GLSL (dst = (src0 > 0.5) ? src1 : src2) */ 4394 /* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4 4395 * the compare is done per component of src0. */ 4396 static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins) 4397 { 4398 struct glsl_src_param src0_param; 4399 struct glsl_src_param src1_param; 4400 struct glsl_src_param src2_param; 4401 DWORD write_mask; 4402 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, 4403 ins->ctx->reg_maps->shader_version.minor); 4404 4405 if (shader_version < WINED3D_SHADER_VERSION(1, 4)) 4406 { 4407 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4408 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4409 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4410 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4411 4412 if (ins->coissue && ins->dst->write_mask != WINED3DSP_WRITEMASK_3) 4413 shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str); 4414 else 4415 shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n", 4416 src0_param.param_str, src1_param.param_str, src2_param.param_str); 4417 return; 4418 } 4419 4420 shader_glsl_conditional_move(ins); 4421 } 4422 4423 /** GLSL code generation for WINED3DSIO_MAD: Multiply the first 2 opcodes, then add the last */ 4424 static void shader_glsl_mad(const struct wined3d_shader_instruction *ins) 4425 { 4426 struct glsl_src_param src0_param; 4427 struct glsl_src_param src1_param; 4428 struct glsl_src_param src2_param; 4429 DWORD write_mask; 4430 4431 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4432 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4433 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4434 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4435 shader_addline(ins->ctx->buffer, "(%s * %s) + %s);\n", 4436 src0_param.param_str, src1_param.param_str, src2_param.param_str); 4437 } 4438 4439 /* Handles transforming all WINED3DSIO_M?x? opcodes for 4440 Vertex shaders to GLSL codes */ 4441 static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins) 4442 { 4443 int i; 4444 int nComponents = 0; 4445 struct wined3d_shader_dst_param tmp_dst = {{0}}; 4446 struct wined3d_shader_src_param tmp_src[2] = {{{0}}}; 4447 struct wined3d_shader_instruction tmp_ins; 4448 4449 memset(&tmp_ins, 0, sizeof(tmp_ins)); 4450 4451 /* Set constants for the temporary argument */ 4452 tmp_ins.ctx = ins->ctx; 4453 tmp_ins.dst_count = 1; 4454 tmp_ins.dst = &tmp_dst; 4455 tmp_ins.src_count = 2; 4456 tmp_ins.src = tmp_src; 4457 4458 switch(ins->handler_idx) 4459 { 4460 case WINED3DSIH_M4x4: 4461 nComponents = 4; 4462 tmp_ins.handler_idx = WINED3DSIH_DP4; 4463 break; 4464 case WINED3DSIH_M4x3: 4465 nComponents = 3; 4466 tmp_ins.handler_idx = WINED3DSIH_DP4; 4467 break; 4468 case WINED3DSIH_M3x4: 4469 nComponents = 4; 4470 tmp_ins.handler_idx = WINED3DSIH_DP3; 4471 break; 4472 case WINED3DSIH_M3x3: 4473 nComponents = 3; 4474 tmp_ins.handler_idx = WINED3DSIH_DP3; 4475 break; 4476 case WINED3DSIH_M3x2: 4477 nComponents = 2; 4478 tmp_ins.handler_idx = WINED3DSIH_DP3; 4479 break; 4480 default: 4481 break; 4482 } 4483 4484 tmp_dst = ins->dst[0]; 4485 tmp_src[0] = ins->src[0]; 4486 tmp_src[1] = ins->src[1]; 4487 for (i = 0; i < nComponents; ++i) 4488 { 4489 tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i; 4490 shader_glsl_dot(&tmp_ins); 4491 ++tmp_src[1].reg.idx[0].offset; 4492 } 4493 } 4494 4495 /** 4496 The LRP instruction performs a component-wise linear interpolation 4497 between the second and third operands using the first operand as the 4498 blend factor. Equation: (dst = src2 + src0 * (src1 - src2)) 4499 This is equivalent to mix(src2, src1, src0); 4500 */ 4501 static void shader_glsl_lrp(const struct wined3d_shader_instruction *ins) 4502 { 4503 struct glsl_src_param src0_param; 4504 struct glsl_src_param src1_param; 4505 struct glsl_src_param src2_param; 4506 DWORD write_mask; 4507 4508 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4509 4510 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4511 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4512 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4513 4514 shader_addline(ins->ctx->buffer, "mix(%s, %s, %s));\n", 4515 src2_param.param_str, src1_param.param_str, src0_param.param_str); 4516 } 4517 4518 /** Process the WINED3DSIO_LIT instruction in GLSL: 4519 * dst.x = dst.w = 1.0 4520 * dst.y = (src0.x > 0) ? src0.x 4521 * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0 4522 * where src.w is clamped at +- 128 4523 */ 4524 static void shader_glsl_lit(const struct wined3d_shader_instruction *ins) 4525 { 4526 struct glsl_src_param src0_param; 4527 struct glsl_src_param src1_param; 4528 struct glsl_src_param src3_param; 4529 char dst_mask[6]; 4530 4531 shader_glsl_append_dst(ins->ctx->buffer, ins); 4532 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4533 4534 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4535 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src1_param); 4536 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src3_param); 4537 4538 /* The sdk specifies the instruction like this 4539 * dst.x = 1.0; 4540 * if(src.x > 0.0) dst.y = src.x 4541 * else dst.y = 0.0. 4542 * if(src.x > 0.0 && src.y > 0.0) dst.z = pow(src.y, power); 4543 * else dst.z = 0.0; 4544 * dst.w = 1.0; 4545 * (where power = src.w clamped between -128 and 128) 4546 * 4547 * Obviously that has quite a few conditionals in it which we don't like. So the first step is this: 4548 * dst.x = 1.0 ... No further explanation needed 4549 * dst.y = max(src.y, 0.0); ... If x < 0.0, use 0.0, otherwise x. Same as the conditional 4550 * dst.z = x > 0.0 ? pow(max(y, 0.0), p) : 0; ... 0 ^ power is 0, and otherwise we use y anyway 4551 * dst.w = 1.0. ... Nothing fancy. 4552 * 4553 * So we still have one conditional in there. So do this: 4554 * dst.z = pow(max(0.0, src.y) * step(0.0, src.x), power); 4555 * 4556 * 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), 4557 * 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. 4558 * if both x and y are > 0, we get pow(y * 1.0, power), as it is supposed to. 4559 * 4560 * Unfortunately pow(0.0 ^ 0.0) returns NaN on most GPUs, but lit with src.y = 0 and src.w = 0 returns 4561 * a non-NaN value in dst.z. What we return doesn't matter, as long as it is not NaN. Return 0, which is 4562 * what all Windows HW drivers and GL_ARB_vertex_program's LIT do. 4563 */ 4564 shader_addline(ins->ctx->buffer, 4565 "vec4(1.0, max(%s, 0.0), %s == 0.0 ? 0.0 : " 4566 "pow(max(0.0, %s) * step(0.0, %s), clamp(%s, -128.0, 128.0)), 1.0)%s);\n", 4567 src0_param.param_str, src3_param.param_str, src1_param.param_str, 4568 src0_param.param_str, src3_param.param_str, dst_mask); 4569 } 4570 4571 /** Process the WINED3DSIO_DST instruction in GLSL: 4572 * dst.x = 1.0 4573 * dst.y = src0.x * src0.y 4574 * dst.z = src0.z 4575 * dst.w = src1.w 4576 */ 4577 static void shader_glsl_dst(const struct wined3d_shader_instruction *ins) 4578 { 4579 struct glsl_src_param src0y_param; 4580 struct glsl_src_param src0z_param; 4581 struct glsl_src_param src1y_param; 4582 struct glsl_src_param src1w_param; 4583 char dst_mask[6]; 4584 4585 shader_glsl_append_dst(ins->ctx->buffer, ins); 4586 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4587 4588 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src0y_param); 4589 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &src0z_param); 4590 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_1, &src1y_param); 4591 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_3, &src1w_param); 4592 4593 shader_addline(ins->ctx->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n", 4594 src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask); 4595 } 4596 4597 /** Process the WINED3DSIO_SINCOS instruction in GLSL: 4598 * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware 4599 * can handle it. But, these functions are built-in for GLSL, so we can just ignore the last 2 params. 4600 * 4601 * dst.x = cos(src0.?) 4602 * dst.y = sin(src0.?) 4603 * dst.z = dst.z 4604 * dst.w = dst.w 4605 */ 4606 static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins) 4607 { 4608 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4609 struct glsl_src_param src0_param; 4610 DWORD write_mask; 4611 4612 if (ins->ctx->reg_maps->shader_version.major < 4) 4613 { 4614 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4615 4616 write_mask = shader_glsl_append_dst(buffer, ins); 4617 switch (write_mask) 4618 { 4619 case WINED3DSP_WRITEMASK_0: 4620 shader_addline(buffer, "cos(%s));\n", src0_param.param_str); 4621 break; 4622 4623 case WINED3DSP_WRITEMASK_1: 4624 shader_addline(buffer, "sin(%s));\n", src0_param.param_str); 4625 break; 4626 4627 case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1): 4628 shader_addline(buffer, "vec2(cos(%s), sin(%s)));\n", 4629 src0_param.param_str, src0_param.param_str); 4630 break; 4631 4632 default: 4633 ERR("Write mask should be .x, .y or .xy\n"); 4634 break; 4635 } 4636 4637 return; 4638 } 4639 4640 if (ins->dst[0].reg.type != WINED3DSPR_NULL) 4641 { 4642 4643 if (ins->dst[1].reg.type != WINED3DSPR_NULL) 4644 { 4645 char dst_mask[6]; 4646 4647 write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4648 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4649 shader_addline(buffer, "tmp0%s = sin(%s);\n", dst_mask, src0_param.param_str); 4650 4651 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 4652 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4653 shader_addline(buffer, "cos(%s));\n", src0_param.param_str); 4654 4655 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 4656 shader_addline(buffer, "tmp0%s);\n", dst_mask); 4657 } 4658 else 4659 { 4660 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 4661 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4662 shader_addline(buffer, "sin(%s));\n", src0_param.param_str); 4663 } 4664 } 4665 else if (ins->dst[1].reg.type != WINED3DSPR_NULL) 4666 { 4667 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 4668 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4669 shader_addline(buffer, "cos(%s));\n", src0_param.param_str); 4670 } 4671 } 4672 4673 /* sgn in vs_2_0 has 2 extra parameters(registers for temporary storage) which we don't use 4674 * here. But those extra parameters require a dedicated function for sgn, since map2gl would 4675 * generate invalid code 4676 */ 4677 static void shader_glsl_sgn(const struct wined3d_shader_instruction *ins) 4678 { 4679 struct glsl_src_param src0_param; 4680 DWORD write_mask; 4681 4682 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4683 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4684 4685 shader_addline(ins->ctx->buffer, "sign(%s));\n", src0_param.param_str); 4686 } 4687 4688 /** Process the WINED3DSIO_LOOP instruction in GLSL: 4689 * Start a for() loop where src1.y is the initial value of aL, 4690 * increment aL by src1.z for a total of src1.x iterations. 4691 * Need to use a temporary variable for this operation. 4692 */ 4693 /* FIXME: I don't think nested loops will work correctly this way. */ 4694 static void shader_glsl_loop(const struct wined3d_shader_instruction *ins) 4695 { 4696 struct wined3d_shader_parser_state *state = ins->ctx->state; 4697 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4698 const struct wined3d_shader *shader = ins->ctx->shader; 4699 const struct wined3d_shader_lconst *constant; 4700 struct glsl_src_param src1_param; 4701 const DWORD *control_values = NULL; 4702 4703 if (ins->ctx->reg_maps->shader_version.major < 4) 4704 { 4705 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &src1_param); 4706 4707 /* Try to hardcode the loop control parameters if possible. Direct3D 9 4708 * class hardware doesn't support real varying indexing, but Microsoft 4709 * designed this feature for Shader model 2.x+. If the loop control is 4710 * known at compile time, the GLSL compiler can unroll the loop, and 4711 * replace indirect addressing with direct addressing. */ 4712 if (ins->src[1].reg.type == WINED3DSPR_CONSTINT) 4713 { 4714 LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry) 4715 { 4716 if (constant->idx == ins->src[1].reg.idx[0].offset) 4717 { 4718 control_values = constant->value; 4719 break; 4720 } 4721 } 4722 } 4723 4724 if (control_values) 4725 { 4726 struct wined3d_shader_loop_control loop_control; 4727 loop_control.count = control_values[0]; 4728 loop_control.start = control_values[1]; 4729 loop_control.step = (int)control_values[2]; 4730 4731 if (loop_control.step > 0) 4732 { 4733 shader_addline(buffer, "for (aL%u = %u; aL%u < (%u * %d + %u); aL%u += %d)\n{\n", 4734 state->current_loop_depth, loop_control.start, 4735 state->current_loop_depth, loop_control.count, loop_control.step, loop_control.start, 4736 state->current_loop_depth, loop_control.step); 4737 } 4738 else if (loop_control.step < 0) 4739 { 4740 shader_addline(buffer, "for (aL%u = %u; aL%u > (%u * %d + %u); aL%u += %d)\n{\n", 4741 state->current_loop_depth, loop_control.start, 4742 state->current_loop_depth, loop_control.count, loop_control.step, loop_control.start, 4743 state->current_loop_depth, loop_control.step); 4744 } 4745 else 4746 { 4747 shader_addline(buffer, "for (aL%u = %u, tmpInt%u = 0; tmpInt%u < %u; tmpInt%u++)\n{\n", 4748 state->current_loop_depth, loop_control.start, state->current_loop_depth, 4749 state->current_loop_depth, loop_control.count, 4750 state->current_loop_depth); 4751 } 4752 } 4753 else 4754 { 4755 shader_addline(buffer, "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z)\n{\n", 4756 state->current_loop_depth, state->current_loop_reg, 4757 src1_param.reg_name, state->current_loop_depth, src1_param.reg_name, 4758 state->current_loop_depth, state->current_loop_reg, src1_param.reg_name); 4759 } 4760 4761 ++state->current_loop_reg; 4762 } 4763 else 4764 { 4765 shader_addline(buffer, "for (;;)\n{\n"); 4766 } 4767 4768 ++state->current_loop_depth; 4769 } 4770 4771 static void shader_glsl_end(const struct wined3d_shader_instruction *ins) 4772 { 4773 struct wined3d_shader_parser_state *state = ins->ctx->state; 4774 4775 shader_addline(ins->ctx->buffer, "}\n"); 4776 4777 if (ins->handler_idx == WINED3DSIH_ENDLOOP) 4778 { 4779 --state->current_loop_depth; 4780 --state->current_loop_reg; 4781 } 4782 4783 if (ins->handler_idx == WINED3DSIH_ENDREP) 4784 { 4785 --state->current_loop_depth; 4786 } 4787 } 4788 4789 static void shader_glsl_rep(const struct wined3d_shader_instruction *ins) 4790 { 4791 struct wined3d_shader_parser_state *state = ins->ctx->state; 4792 const struct wined3d_shader *shader = ins->ctx->shader; 4793 const struct wined3d_shader_lconst *constant; 4794 struct glsl_src_param src0_param; 4795 const DWORD *control_values = NULL; 4796 4797 /* Try to hardcode local values to help the GLSL compiler to unroll and optimize the loop */ 4798 if (ins->src[0].reg.type == WINED3DSPR_CONSTINT) 4799 { 4800 LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry) 4801 { 4802 if (constant->idx == ins->src[0].reg.idx[0].offset) 4803 { 4804 control_values = constant->value; 4805 break; 4806 } 4807 } 4808 } 4809 4810 if (control_values) 4811 { 4812 shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %d; tmpInt%d++) {\n", 4813 state->current_loop_depth, state->current_loop_depth, 4814 control_values[0], state->current_loop_depth); 4815 } 4816 else 4817 { 4818 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4819 shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n", 4820 state->current_loop_depth, state->current_loop_depth, 4821 src0_param.param_str, state->current_loop_depth); 4822 } 4823 4824 ++state->current_loop_depth; 4825 } 4826 4827 static void shader_glsl_switch(const struct wined3d_shader_instruction *ins) 4828 { 4829 struct glsl_src_param src0_param; 4830 4831 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4832 shader_addline(ins->ctx->buffer, "switch (%s)\n{\n", src0_param.param_str); 4833 } 4834 4835 static void shader_glsl_case(const struct wined3d_shader_instruction *ins) 4836 { 4837 struct glsl_src_param src0_param; 4838 4839 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4840 shader_addline(ins->ctx->buffer, "case %s:\n", src0_param.param_str); 4841 } 4842 4843 static void shader_glsl_default(const struct wined3d_shader_instruction *ins) 4844 { 4845 shader_addline(ins->ctx->buffer, "default:\n"); 4846 } 4847 4848 static void shader_glsl_generate_conditional_op(const struct wined3d_shader_instruction *ins, 4849 const char *op) 4850 { 4851 struct glsl_src_param src_param; 4852 const char *condition; 4853 4854 condition = ins->flags == WINED3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; 4855 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param); 4856 shader_addline(ins->ctx->buffer, "if (%s(%s)) %s\n", condition, src_param.param_str, op); 4857 } 4858 4859 static void shader_glsl_if(const struct wined3d_shader_instruction *ins) 4860 { 4861 shader_glsl_generate_conditional_op(ins, "{"); 4862 } 4863 4864 static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins) 4865 { 4866 struct glsl_src_param src0_param; 4867 struct glsl_src_param src1_param; 4868 4869 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4870 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 4871 4872 shader_addline(ins->ctx->buffer, "if (%s %s %s) {\n", 4873 src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str); 4874 } 4875 4876 static void shader_glsl_else(const struct wined3d_shader_instruction *ins) 4877 { 4878 shader_addline(ins->ctx->buffer, "} else {\n"); 4879 } 4880 4881 static void shader_glsl_emit(const struct wined3d_shader_instruction *ins) 4882 { 4883 unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset; 4884 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 4885 4886 shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n"); 4887 if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL]) 4888 shader_glsl_fixup_position(ins->ctx->buffer, reg_maps->viewport_array); 4889 4890 if (!stream) 4891 shader_addline(ins->ctx->buffer, "EmitVertex();\n"); 4892 else 4893 FIXME("Unhandled primitive stream %u.\n", stream); 4894 } 4895 4896 static void shader_glsl_break(const struct wined3d_shader_instruction *ins) 4897 { 4898 shader_addline(ins->ctx->buffer, "break;\n"); 4899 } 4900 4901 /* FIXME: According to MSDN the compare is done per component. */ 4902 static void shader_glsl_breakc(const struct wined3d_shader_instruction *ins) 4903 { 4904 struct glsl_src_param src0_param; 4905 struct glsl_src_param src1_param; 4906 4907 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4908 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 4909 4910 shader_addline(ins->ctx->buffer, "if (%s %s %s) break;\n", 4911 src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str); 4912 } 4913 4914 static void shader_glsl_conditional_op(const struct wined3d_shader_instruction *ins) 4915 { 4916 const char *op; 4917 4918 switch (ins->handler_idx) 4919 { 4920 case WINED3DSIH_BREAKP: op = "break;"; break; 4921 case WINED3DSIH_CONTINUEP: op = "continue;"; break; 4922 case WINED3DSIH_RETP: op = "return;"; break; 4923 default: 4924 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 4925 return; 4926 } 4927 4928 shader_glsl_generate_conditional_op(ins, op); 4929 } 4930 4931 static void shader_glsl_continue(const struct wined3d_shader_instruction *ins) 4932 { 4933 shader_addline(ins->ctx->buffer, "continue;\n"); 4934 } 4935 4936 static void shader_glsl_label(const struct wined3d_shader_instruction *ins) 4937 { 4938 shader_addline(ins->ctx->buffer, "}\n"); 4939 shader_addline(ins->ctx->buffer, "void subroutine%u()\n{\n", ins->src[0].reg.idx[0].offset); 4940 4941 /* Subroutines appear at the end of the shader. */ 4942 ins->ctx->state->in_subroutine = TRUE; 4943 } 4944 4945 static void shader_glsl_call(const struct wined3d_shader_instruction *ins) 4946 { 4947 shader_addline(ins->ctx->buffer, "subroutine%u();\n", ins->src[0].reg.idx[0].offset); 4948 } 4949 4950 static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins) 4951 { 4952 struct glsl_src_param src1_param; 4953 4954 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 4955 shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n", 4956 src1_param.param_str, ins->src[0].reg.idx[0].offset); 4957 } 4958 4959 static void shader_glsl_ret(const struct wined3d_shader_instruction *ins) 4960 { 4961 const struct wined3d_shader_version *version = &ins->ctx->shader->reg_maps.shader_version; 4962 4963 if (version->major >= 4 && !ins->ctx->state->in_subroutine) 4964 { 4965 shader_glsl_generate_shader_epilogue(ins->ctx); 4966 shader_addline(ins->ctx->buffer, "return;\n"); 4967 } 4968 } 4969 4970 static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) 4971 { 4972 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, 4973 ins->ctx->reg_maps->shader_version.minor); 4974 struct glsl_sample_function sample_function; 4975 DWORD sample_flags = 0; 4976 DWORD resource_idx; 4977 DWORD mask = 0, swizzle; 4978 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 4979 4980 /* 1.0-1.4: Use destination register as sampler source. 4981 * 2.0+: Use provided sampler source. */ 4982 if (shader_version < WINED3D_SHADER_VERSION(2,0)) 4983 resource_idx = ins->dst[0].reg.idx[0].offset; 4984 else 4985 resource_idx = ins->src[1].reg.idx[0].offset; 4986 4987 if (shader_version < WINED3D_SHADER_VERSION(1,4)) 4988 { 4989 DWORD flags = (priv->cur_ps_args->tex_transform >> resource_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT) 4990 & WINED3D_PSARGS_TEXTRANSFORM_MASK; 4991 enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type; 4992 4993 /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */ 4994 if (flags & WINED3D_PSARGS_PROJECTED && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) 4995 { 4996 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 4997 switch (flags & ~WINED3D_PSARGS_PROJECTED) 4998 { 4999 case WINED3D_TTFF_COUNT1: 5000 FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n"); 5001 break; 5002 case WINED3D_TTFF_COUNT2: 5003 mask = WINED3DSP_WRITEMASK_1; 5004 break; 5005 case WINED3D_TTFF_COUNT3: 5006 mask = WINED3DSP_WRITEMASK_2; 5007 break; 5008 case WINED3D_TTFF_COUNT4: 5009 case WINED3D_TTFF_DISABLE: 5010 mask = WINED3DSP_WRITEMASK_3; 5011 break; 5012 } 5013 } 5014 } 5015 else if (shader_version < WINED3D_SHADER_VERSION(2,0)) 5016 { 5017 enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers; 5018 5019 if (src_mod == WINED3DSPSM_DZ) { 5020 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5021 mask = WINED3DSP_WRITEMASK_2; 5022 } else if (src_mod == WINED3DSPSM_DW) { 5023 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5024 mask = WINED3DSP_WRITEMASK_3; 5025 } 5026 } 5027 else 5028 { 5029 if ((ins->flags & WINED3DSI_TEXLD_PROJECT) 5030 && ins->ctx->reg_maps->resource_info[resource_idx].type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) 5031 { 5032 /* ps 2.0 texldp instruction always divides by the fourth component. */ 5033 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5034 mask = WINED3DSP_WRITEMASK_3; 5035 } 5036 } 5037 5038 shader_glsl_get_sample_function(ins->ctx, resource_idx, resource_idx, sample_flags, &sample_function); 5039 mask |= sample_function.coord_mask; 5040 sample_function.coord_mask = mask; 5041 5042 if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE; 5043 else swizzle = ins->src[1].swizzle; 5044 5045 /* 1.0-1.3: Use destination register as coordinate source. 5046 1.4+: Use provided coordinate source register. */ 5047 if (shader_version < WINED3D_SHADER_VERSION(1,4)) 5048 { 5049 char coord_mask[6]; 5050 shader_glsl_write_mask_to_str(mask, coord_mask); 5051 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL, 5052 "T%u%s", resource_idx, coord_mask); 5053 } 5054 else 5055 { 5056 struct glsl_src_param coord_param; 5057 shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param); 5058 if (ins->flags & WINED3DSI_TEXLD_BIAS) 5059 { 5060 struct glsl_src_param bias; 5061 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias); 5062 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, bias.param_str, 5063 NULL, "%s", coord_param.param_str); 5064 } else { 5065 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL, 5066 "%s", coord_param.param_str); 5067 } 5068 } 5069 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5070 } 5071 5072 static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) 5073 { 5074 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5075 struct glsl_src_param coord_param, dx_param, dy_param; 5076 struct glsl_sample_function sample_function; 5077 DWORD sampler_idx; 5078 DWORD swizzle = ins->src[1].swizzle; 5079 5080 if (!shader_glsl_has_core_grad(gl_info) && !gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 5081 { 5082 FIXME("texldd used, but not supported by hardware. Falling back to regular tex.\n"); 5083 shader_glsl_tex(ins); 5084 return; 5085 } 5086 5087 sampler_idx = ins->src[1].reg.idx[0].offset; 5088 5089 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_GRAD, &sample_function); 5090 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5091 shader_glsl_add_src_param(ins, &ins->src[2], sample_function.deriv_mask, &dx_param); 5092 shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dy_param); 5093 5094 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str, 5095 NULL, NULL, "%s", coord_param.param_str); 5096 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5097 } 5098 5099 static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) 5100 { 5101 const struct wined3d_shader_version *shader_version = &ins->ctx->reg_maps->shader_version; 5102 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5103 struct glsl_src_param coord_param, lod_param; 5104 struct glsl_sample_function sample_function; 5105 DWORD swizzle = ins->src[1].swizzle; 5106 DWORD sampler_idx; 5107 5108 sampler_idx = ins->src[1].reg.idx[0].offset; 5109 5110 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_LOD, &sample_function); 5111 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5112 5113 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); 5114 5115 if (shader_version->type == WINED3D_SHADER_TYPE_PIXEL && !shader_glsl_has_core_grad(gl_info) 5116 && !gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 5117 { 5118 /* Plain GLSL only supports Lod sampling functions in vertex shaders. 5119 * However, the NVIDIA drivers allow them in fragment shaders as well, 5120 * even without the appropriate extension. */ 5121 WARN("Using %s in fragment shader.\n", sample_function.name->buffer); 5122 } 5123 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str, NULL, 5124 "%s", coord_param.param_str); 5125 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5126 } 5127 5128 static unsigned int shader_glsl_find_sampler(const struct wined3d_shader_sampler_map *sampler_map, 5129 unsigned int resource_idx, unsigned int sampler_idx) 5130 { 5131 struct wined3d_shader_sampler_map_entry *entries = sampler_map->entries; 5132 unsigned int i; 5133 5134 for (i = 0; i < sampler_map->count; ++i) 5135 { 5136 if (entries[i].resource_idx == resource_idx && entries[i].sampler_idx == sampler_idx) 5137 return entries[i].bind_idx; 5138 } 5139 5140 ERR("No GLSL sampler found for resource %u / sampler %u.\n", resource_idx, sampler_idx); 5141 5142 return ~0u; 5143 } 5144 5145 static void shader_glsl_atomic(const struct wined3d_shader_instruction *ins) 5146 { 5147 const BOOL is_imm_instruction = WINED3DSIH_IMM_ATOMIC_AND <= ins->handler_idx 5148 && ins->handler_idx <= WINED3DSIH_IMM_ATOMIC_XOR; 5149 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5150 const struct wined3d_shader_version *version = ®_maps->shader_version; 5151 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 5152 struct glsl_src_param structure_idx, offset, data, data2; 5153 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5154 enum wined3d_shader_resource_type resource_type; 5155 struct wined3d_string_buffer *address; 5156 enum wined3d_data_type data_type; 5157 unsigned int resource_idx, stride; 5158 const char *op, *resource; 5159 DWORD coord_mask; 5160 BOOL is_tgsm; 5161 5162 resource_idx = ins->dst[is_imm_instruction].reg.idx[0].offset; 5163 is_tgsm = ins->dst[is_imm_instruction].reg.type == WINED3DSPR_GROUPSHAREDMEM; 5164 if (is_tgsm) 5165 { 5166 if (resource_idx >= reg_maps->tgsm_count) 5167 { 5168 ERR("Invalid TGSM index %u.\n", resource_idx); 5169 return; 5170 } 5171 resource = "g"; 5172 data_type = WINED3D_DATA_UINT; 5173 coord_mask = 1; 5174 stride = reg_maps->tgsm[resource_idx].stride; 5175 } 5176 else 5177 { 5178 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5179 { 5180 ERR("Invalid UAV index %u.\n", resource_idx); 5181 return; 5182 } 5183 resource_type = reg_maps->uav_resource_info[resource_idx].type; 5184 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5185 { 5186 ERR("Unexpected resource type %#x.\n", resource_type); 5187 return; 5188 } 5189 resource = "image"; 5190 data_type = reg_maps->uav_resource_info[resource_idx].data_type; 5191 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1; 5192 stride = reg_maps->uav_resource_info[resource_idx].stride; 5193 } 5194 5195 switch (ins->handler_idx) 5196 { 5197 case WINED3DSIH_ATOMIC_AND: 5198 case WINED3DSIH_IMM_ATOMIC_AND: 5199 if (is_tgsm) 5200 op = "atomicAnd"; 5201 else 5202 op = "imageAtomicAnd"; 5203 break; 5204 case WINED3DSIH_ATOMIC_CMP_STORE: 5205 case WINED3DSIH_IMM_ATOMIC_CMP_EXCH: 5206 if (is_tgsm) 5207 op = "atomicCompSwap"; 5208 else 5209 op = "imageAtomicCompSwap"; 5210 break; 5211 case WINED3DSIH_ATOMIC_IADD: 5212 case WINED3DSIH_IMM_ATOMIC_IADD: 5213 if (is_tgsm) 5214 op = "atomicAdd"; 5215 else 5216 op = "imageAtomicAdd"; 5217 break; 5218 case WINED3DSIH_ATOMIC_IMAX: 5219 case WINED3DSIH_IMM_ATOMIC_IMAX: 5220 if (is_tgsm) 5221 op = "atomicMax"; 5222 else 5223 op = "imageAtomicMax"; 5224 if (data_type != WINED3D_DATA_INT) 5225 { 5226 FIXME("Unhandled opcode %#x for unsigned integers.\n", ins->handler_idx); 5227 return; 5228 } 5229 break; 5230 case WINED3DSIH_ATOMIC_IMIN: 5231 case WINED3DSIH_IMM_ATOMIC_IMIN: 5232 if (is_tgsm) 5233 op = "atomicMin"; 5234 else 5235 op = "imageAtomicMin"; 5236 if (data_type != WINED3D_DATA_INT) 5237 { 5238 FIXME("Unhandled opcode %#x for unsigned integers.\n", ins->handler_idx); 5239 return; 5240 } 5241 break; 5242 case WINED3DSIH_ATOMIC_OR: 5243 case WINED3DSIH_IMM_ATOMIC_OR: 5244 if (is_tgsm) 5245 op = "atomicOr"; 5246 else 5247 op = "imageAtomicOr"; 5248 break; 5249 case WINED3DSIH_ATOMIC_UMAX: 5250 case WINED3DSIH_IMM_ATOMIC_UMAX: 5251 if (is_tgsm) 5252 op = "atomicMax"; 5253 else 5254 op = "imageAtomicMax"; 5255 if (data_type != WINED3D_DATA_UINT) 5256 { 5257 FIXME("Unhandled opcode %#x for signed integers.\n", ins->handler_idx); 5258 return; 5259 } 5260 break; 5261 case WINED3DSIH_ATOMIC_UMIN: 5262 case WINED3DSIH_IMM_ATOMIC_UMIN: 5263 if (is_tgsm) 5264 op = "atomicMin"; 5265 else 5266 op = "imageAtomicMin"; 5267 if (data_type != WINED3D_DATA_UINT) 5268 { 5269 FIXME("Unhandled opcode %#x for signed integers.\n", ins->handler_idx); 5270 return; 5271 } 5272 break; 5273 case WINED3DSIH_ATOMIC_XOR: 5274 case WINED3DSIH_IMM_ATOMIC_XOR: 5275 if (is_tgsm) 5276 op = "atomicXor"; 5277 else 5278 op = "imageAtomicXor"; 5279 break; 5280 case WINED3DSIH_IMM_ATOMIC_EXCH: 5281 if (is_tgsm) 5282 op = "atomicExchange"; 5283 else 5284 op = "imageAtomicExchange"; 5285 break; 5286 default: 5287 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 5288 return; 5289 } 5290 5291 address = string_buffer_get(priv->string_buffers); 5292 if (stride) 5293 { 5294 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &structure_idx); 5295 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &offset); 5296 string_buffer_sprintf(address, "%s * %u + %s / 4", structure_idx.param_str, stride, offset.param_str); 5297 } 5298 else 5299 { 5300 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &offset); 5301 string_buffer_sprintf(address, "%s", offset.param_str); 5302 if (is_tgsm || (reg_maps->uav_resource_info[resource_idx].flags & WINED3D_VIEW_BUFFER_RAW)) 5303 shader_addline(address, "/ 4"); 5304 } 5305 5306 if (is_imm_instruction) 5307 shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], data_type); 5308 5309 if (is_tgsm) 5310 shader_addline(buffer, "%s(%s_%s%u[%s], ", 5311 op, shader_glsl_get_prefix(version->type), resource, resource_idx, address->buffer); 5312 else 5313 shader_addline(buffer, "%s(%s_%s%u, %s, ", 5314 op, shader_glsl_get_prefix(version->type), resource, resource_idx, address->buffer); 5315 5316 shader_glsl_add_src_param_ext(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &data, data_type); 5317 shader_addline(buffer, "%s", data.param_str); 5318 if (ins->src_count >= 3) 5319 { 5320 shader_glsl_add_src_param_ext(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &data2, data_type); 5321 shader_addline(buffer, ", %s", data2.param_str); 5322 } 5323 5324 if (is_imm_instruction) 5325 shader_addline(buffer, ")"); 5326 shader_addline(buffer, ");\n"); 5327 5328 string_buffer_release(priv->string_buffers, address); 5329 } 5330 5331 static void shader_glsl_uav_counter(const struct wined3d_shader_instruction *ins) 5332 { 5333 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5334 const char *op; 5335 5336 if (ins->handler_idx == WINED3DSIH_IMM_ATOMIC_ALLOC) 5337 op = "atomicCounterIncrement"; 5338 else 5339 op = "atomicCounterDecrement"; 5340 5341 shader_glsl_append_dst(ins->ctx->buffer, ins); 5342 shader_addline(ins->ctx->buffer, "%s(%s_counter%u));\n", op, prefix, ins->src[0].reg.idx[0].offset); 5343 } 5344 5345 static void shader_glsl_ld_uav(const struct wined3d_shader_instruction *ins) 5346 { 5347 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5348 const struct wined3d_shader_version *version = ®_maps->shader_version; 5349 enum wined3d_shader_resource_type resource_type; 5350 struct glsl_src_param image_coord_param; 5351 enum wined3d_data_type data_type; 5352 DWORD coord_mask, write_mask; 5353 unsigned int uav_idx; 5354 char dst_swizzle[6]; 5355 5356 uav_idx = ins->src[1].reg.idx[0].offset; 5357 if (uav_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5358 { 5359 ERR("Invalid UAV index %u.\n", uav_idx); 5360 return; 5361 } 5362 resource_type = reg_maps->uav_resource_info[uav_idx].type; 5363 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5364 { 5365 ERR("Unexpected resource type %#x.\n", resource_type); 5366 resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; 5367 } 5368 data_type = reg_maps->uav_resource_info[uav_idx].data_type; 5369 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1; 5370 5371 write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], data_type); 5372 shader_glsl_get_swizzle(&ins->src[1], FALSE, write_mask, dst_swizzle); 5373 5374 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &image_coord_param); 5375 shader_addline(ins->ctx->buffer, "imageLoad(%s_image%u, %s)%s);\n", 5376 shader_glsl_get_prefix(version->type), uav_idx, image_coord_param.param_str, dst_swizzle); 5377 } 5378 5379 static void shader_glsl_ld_raw_structured(const struct wined3d_shader_instruction *ins) 5380 { 5381 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5382 const struct wined3d_shader_src_param *src = &ins->src[ins->src_count - 1]; 5383 unsigned int i, swizzle, resource_idx, bind_idx, stride, src_idx = 0; 5384 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5385 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 5386 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5387 struct glsl_src_param structure_idx, offset; 5388 struct wined3d_string_buffer *address; 5389 struct wined3d_shader_dst_param dst; 5390 const char *function, *resource; 5391 5392 resource_idx = src->reg.idx[0].offset; 5393 if (src->reg.type == WINED3DSPR_RESOURCE) 5394 { 5395 if (resource_idx >= ARRAY_SIZE(reg_maps->resource_info)) 5396 { 5397 ERR("Invalid resource index %u.\n", resource_idx); 5398 return; 5399 } 5400 stride = reg_maps->resource_info[resource_idx].stride; 5401 bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, WINED3D_SAMPLER_DEFAULT); 5402 function = "texelFetch"; 5403 resource = "sampler"; 5404 } 5405 else if (src->reg.type == WINED3DSPR_UAV) 5406 { 5407 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5408 { 5409 ERR("Invalid UAV index %u.\n", resource_idx); 5410 return; 5411 } 5412 stride = reg_maps->uav_resource_info[resource_idx].stride; 5413 bind_idx = resource_idx; 5414 function = "imageLoad"; 5415 resource = "image"; 5416 } 5417 else 5418 { 5419 if (resource_idx >= reg_maps->tgsm_count) 5420 { 5421 ERR("Invalid TGSM index %u.\n", resource_idx); 5422 return; 5423 } 5424 stride = reg_maps->tgsm[resource_idx].stride; 5425 bind_idx = resource_idx; 5426 function = NULL; 5427 resource = "g"; 5428 } 5429 5430 address = string_buffer_get(priv->string_buffers); 5431 if (ins->handler_idx == WINED3DSIH_LD_STRUCTURED) 5432 { 5433 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &structure_idx); 5434 shader_addline(address, "%s * %u + ", structure_idx.param_str, stride); 5435 } 5436 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &offset); 5437 shader_addline(address, "%s / 4", offset.param_str); 5438 5439 dst = ins->dst[0]; 5440 if (shader_glsl_get_write_mask_size(dst.write_mask) > 1) 5441 { 5442 /* The instruction is split into multiple lines. The first lines may 5443 * overwrite source parameters of the following lines. */ 5444 shader_addline(buffer, "tmp0.x = intBitsToFloat(%s);\n", address->buffer); 5445 string_buffer_sprintf(address, "floatBitsToInt(tmp0.x)"); 5446 } 5447 5448 for (i = 0; i < 4; ++i) 5449 { 5450 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i); 5451 if (!shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type)) 5452 continue; 5453 5454 swizzle = shader_glsl_swizzle_get_component(src->swizzle, i); 5455 if (function) 5456 shader_addline(buffer, "%s(%s_%s%u, %s + %u).x);\n", 5457 function, prefix, resource, bind_idx, address->buffer, swizzle); 5458 else 5459 shader_addline(buffer, "%s_%s%u[%s + %u]);\n", 5460 prefix, resource, bind_idx, address->buffer, swizzle); 5461 } 5462 5463 string_buffer_release(priv->string_buffers, address); 5464 } 5465 5466 static void shader_glsl_store_uav(const struct wined3d_shader_instruction *ins) 5467 { 5468 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5469 const struct wined3d_shader_version *version = ®_maps->shader_version; 5470 struct glsl_src_param image_coord_param, image_data_param; 5471 enum wined3d_shader_resource_type resource_type; 5472 enum wined3d_data_type data_type; 5473 unsigned int uav_idx; 5474 DWORD coord_mask; 5475 5476 uav_idx = ins->dst[0].reg.idx[0].offset; 5477 if (uav_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5478 { 5479 ERR("Invalid UAV index %u.\n", uav_idx); 5480 return; 5481 } 5482 resource_type = reg_maps->uav_resource_info[uav_idx].type; 5483 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5484 { 5485 ERR("Unexpected resource type %#x.\n", resource_type); 5486 return; 5487 } 5488 data_type = reg_maps->uav_resource_info[uav_idx].data_type; 5489 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1; 5490 5491 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &image_coord_param); 5492 shader_glsl_add_src_param_ext(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &image_data_param, data_type); 5493 shader_addline(ins->ctx->buffer, "imageStore(%s_image%u, %s, %s);\n", 5494 shader_glsl_get_prefix(version->type), uav_idx, 5495 image_coord_param.param_str, image_data_param.param_str); 5496 } 5497 5498 static void shader_glsl_store_raw_structured(const struct wined3d_shader_instruction *ins) 5499 { 5500 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5501 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5502 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 5503 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5504 struct glsl_src_param structure_idx, offset, data; 5505 unsigned int i, resource_idx, stride, src_idx = 0; 5506 struct wined3d_string_buffer *address; 5507 DWORD write_mask; 5508 BOOL is_tgsm; 5509 5510 resource_idx = ins->dst[0].reg.idx[0].offset; 5511 is_tgsm = ins->dst[0].reg.type == WINED3DSPR_GROUPSHAREDMEM; 5512 if (is_tgsm) 5513 { 5514 if (resource_idx >= reg_maps->tgsm_count) 5515 { 5516 ERR("Invalid TGSM index %u.\n", resource_idx); 5517 return; 5518 } 5519 stride = reg_maps->tgsm[resource_idx].stride; 5520 } 5521 else 5522 { 5523 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5524 { 5525 ERR("Invalid UAV index %u.\n", resource_idx); 5526 return; 5527 } 5528 stride = reg_maps->uav_resource_info[resource_idx].stride; 5529 } 5530 5531 address = string_buffer_get(priv->string_buffers); 5532 if (ins->handler_idx == WINED3DSIH_STORE_STRUCTURED) 5533 { 5534 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &structure_idx); 5535 shader_addline(address, "%s * %u + ", structure_idx.param_str, stride); 5536 } 5537 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &offset); 5538 shader_addline(address, "%s / 4", offset.param_str); 5539 5540 for (i = 0; i < 4; ++i) 5541 { 5542 if (!(write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i))) 5543 continue; 5544 5545 shader_glsl_add_src_param(ins, &ins->src[src_idx], write_mask, &data); 5546 5547 if (is_tgsm) 5548 shader_addline(buffer, "%s_g%u[%s + %u] = %s;\n", 5549 prefix, resource_idx, address->buffer, i, data.param_str); 5550 else 5551 shader_addline(buffer, "imageStore(%s_image%u, %s + %u, uvec4(%s, 0, 0, 0));\n", 5552 prefix, resource_idx, address->buffer, i, data.param_str); 5553 } 5554 5555 string_buffer_release(priv->string_buffers, address); 5556 } 5557 5558 static void shader_glsl_sync(const struct wined3d_shader_instruction *ins) 5559 { 5560 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5561 unsigned int sync_flags = ins->flags; 5562 5563 if (sync_flags & WINED3DSSF_THREAD_GROUP) 5564 { 5565 shader_addline(buffer, "barrier();\n"); 5566 sync_flags &= ~(WINED3DSSF_THREAD_GROUP | WINED3DSSF_GROUP_SHARED_MEMORY); 5567 } 5568 5569 if (sync_flags & WINED3DSSF_GROUP_SHARED_MEMORY) 5570 { 5571 shader_addline(buffer, "memoryBarrierShared();\n"); 5572 sync_flags &= ~WINED3DSSF_GROUP_SHARED_MEMORY; 5573 } 5574 5575 if (sync_flags) 5576 FIXME("Unhandled sync flags %#x.\n", sync_flags); 5577 } 5578 5579 static const struct wined3d_shader_resource_info *shader_glsl_get_resource_info( 5580 const struct wined3d_shader_instruction *ins, const struct wined3d_shader_register *reg) 5581 { 5582 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5583 unsigned int idx = reg->idx[0].offset; 5584 5585 if (reg->type == WINED3DSPR_RESOURCE) 5586 { 5587 if (idx >= ARRAY_SIZE(reg_maps->resource_info)) 5588 { 5589 ERR("Invalid resource index %u.\n", idx); 5590 return NULL; 5591 } 5592 return ®_maps->resource_info[idx]; 5593 } 5594 5595 if (reg->type == WINED3DSPR_UAV) 5596 { 5597 if (idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5598 { 5599 ERR("Invalid UAV index %u.\n", idx); 5600 return NULL; 5601 } 5602 return ®_maps->uav_resource_info[idx]; 5603 } 5604 5605 FIXME("Unhandled register type %#x.\n", reg->type); 5606 return NULL; 5607 } 5608 5609 static void shader_glsl_bufinfo(const struct wined3d_shader_instruction *ins) 5610 { 5611 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5612 const struct wined3d_shader_resource_info *resource_info; 5613 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5614 unsigned int resource_idx; 5615 char dst_swizzle[6]; 5616 DWORD write_mask; 5617 5618 write_mask = shader_glsl_append_dst(buffer, ins); 5619 shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle); 5620 5621 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[0].reg))) 5622 return; 5623 resource_idx = ins->src[0].reg.idx[0].offset; 5624 5625 shader_addline(buffer, "ivec2("); 5626 if (ins->src[0].reg.type == WINED3DSPR_RESOURCE) 5627 { 5628 unsigned int bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, 5629 resource_idx, WINED3D_SAMPLER_DEFAULT); 5630 shader_addline(buffer, "textureSize(%s_sampler%u)", prefix, bind_idx); 5631 } 5632 else 5633 { 5634 shader_addline(buffer, "imageSize(%s_image%u)", prefix, resource_idx); 5635 } 5636 if (resource_info->stride) 5637 shader_addline(buffer, " / %u", resource_info->stride); 5638 else if (resource_info->flags & WINED3D_VIEW_BUFFER_RAW) 5639 shader_addline(buffer, " * 4"); 5640 shader_addline(buffer, ", %u)%s);\n", resource_info->stride, dst_swizzle); 5641 } 5642 5643 static BOOL is_multisampled(enum wined3d_shader_resource_type resource_type) 5644 { 5645 return resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DMS 5646 || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY; 5647 } 5648 5649 static BOOL is_mipmapped(enum wined3d_shader_resource_type resource_type) 5650 { 5651 return resource_type != WINED3D_SHADER_RESOURCE_BUFFER && !is_multisampled(resource_type); 5652 } 5653 5654 static void shader_glsl_resinfo(const struct wined3d_shader_instruction *ins) 5655 { 5656 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; 5657 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5658 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5659 enum wined3d_shader_resource_type resource_type; 5660 enum wined3d_shader_register_type reg_type; 5661 unsigned int resource_idx, bind_idx, i; 5662 enum wined3d_data_type dst_data_type; 5663 struct glsl_src_param lod_param; 5664 BOOL supports_mipmaps; 5665 char dst_swizzle[6]; 5666 DWORD write_mask; 5667 5668 dst_data_type = ins->dst[0].reg.data_type; 5669 if (ins->flags == WINED3DSI_RESINFO_UINT) 5670 dst_data_type = WINED3D_DATA_UINT; 5671 else if (ins->flags) 5672 FIXME("Unhandled flags %#x.\n", ins->flags); 5673 5674 reg_type = ins->src[1].reg.type; 5675 resource_idx = ins->src[1].reg.idx[0].offset; 5676 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &lod_param); 5677 if (reg_type == WINED3DSPR_RESOURCE) 5678 { 5679 resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type; 5680 bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, 5681 resource_idx, WINED3D_SAMPLER_DEFAULT); 5682 } 5683 else 5684 { 5685 resource_type = ins->ctx->reg_maps->uav_resource_info[resource_idx].type; 5686 bind_idx = resource_idx; 5687 } 5688 5689 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5690 { 5691 ERR("Unexpected resource type %#x.\n", resource_type); 5692 return; 5693 } 5694 5695 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], dst_data_type); 5696 shader_glsl_get_swizzle(&ins->src[1], FALSE, write_mask, dst_swizzle); 5697 5698 if (dst_data_type == WINED3D_DATA_UINT) 5699 shader_addline(buffer, "uvec4("); 5700 else 5701 shader_addline(buffer, "vec4("); 5702 5703 if (reg_type == WINED3DSPR_RESOURCE) 5704 { 5705 shader_addline(buffer, "textureSize(%s_sampler%u", 5706 shader_glsl_get_prefix(version->type), bind_idx); 5707 } 5708 else 5709 { 5710 shader_addline(buffer, "imageSize(%s_image%u", 5711 shader_glsl_get_prefix(version->type), bind_idx); 5712 } 5713 5714 supports_mipmaps = is_mipmapped(resource_type) && reg_type != WINED3DSPR_UAV; 5715 if (supports_mipmaps) 5716 shader_addline(buffer, ", %s", lod_param.param_str); 5717 shader_addline(buffer, "), "); 5718 5719 for (i = 0; i < 3 - resource_type_info[resource_type].resinfo_size; ++i) 5720 shader_addline(buffer, "0, "); 5721 5722 if (supports_mipmaps) 5723 { 5724 if (gl_info->supported[ARB_TEXTURE_QUERY_LEVELS]) 5725 { 5726 shader_addline(buffer, "textureQueryLevels(%s_sampler%u)", 5727 shader_glsl_get_prefix(version->type), bind_idx); 5728 } 5729 else 5730 { 5731 FIXME("textureQueryLevels is not supported, returning 1 level.\n"); 5732 shader_addline(buffer, "1"); 5733 } 5734 } 5735 else 5736 { 5737 shader_addline(buffer, "1"); 5738 } 5739 5740 shader_addline(buffer, ")%s);\n", dst_swizzle); 5741 } 5742 5743 static void shader_glsl_sample_info(const struct wined3d_shader_instruction *ins) 5744 { 5745 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5746 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5747 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5748 const struct wined3d_shader_dst_param *dst = ins->dst; 5749 const struct wined3d_shader_src_param *src = ins->src; 5750 enum wined3d_shader_resource_type resource_type; 5751 enum wined3d_data_type dst_data_type; 5752 unsigned int resource_idx, bind_idx; 5753 char dst_swizzle[6]; 5754 DWORD write_mask; 5755 5756 dst_data_type = dst->reg.data_type; 5757 if (ins->flags == WINED3DSI_SAMPLE_INFO_UINT) 5758 dst_data_type = WINED3D_DATA_UINT; 5759 else if (ins->flags) 5760 FIXME("Unhandled flags %#x.\n", ins->flags); 5761 5762 write_mask = shader_glsl_append_dst_ext(buffer, ins, dst, dst_data_type); 5763 shader_glsl_get_swizzle(src, FALSE, write_mask, dst_swizzle); 5764 5765 if (dst_data_type == WINED3D_DATA_UINT) 5766 shader_addline(buffer, "uvec4("); 5767 else 5768 shader_addline(buffer, "vec4("); 5769 5770 if (src->reg.type == WINED3DSPR_RASTERIZER) 5771 { 5772 if (gl_info->supported[ARB_SAMPLE_SHADING]) 5773 { 5774 shader_addline(buffer, "gl_NumSamples"); 5775 } 5776 else 5777 { 5778 FIXME("OpenGL implementation does not support ARB_sample_shading.\n"); 5779 shader_addline(buffer, "1"); 5780 } 5781 } 5782 else 5783 { 5784 resource_idx = src->reg.idx[0].offset; 5785 resource_type = reg_maps->resource_info[resource_idx].type; 5786 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5787 { 5788 ERR("Unexpected resource type %#x.\n", resource_type); 5789 return; 5790 } 5791 bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, WINED3D_SAMPLER_DEFAULT); 5792 5793 if (gl_info->supported[ARB_SHADER_TEXTURE_IMAGE_SAMPLES]) 5794 { 5795 shader_addline(buffer, "textureSamples(%s_sampler%u)", 5796 shader_glsl_get_prefix(reg_maps->shader_version.type), bind_idx); 5797 } 5798 else 5799 { 5800 FIXME("textureSamples() is not supported.\n"); 5801 shader_addline(buffer, "1"); 5802 } 5803 } 5804 5805 shader_addline(buffer, ", 0, 0, 0)%s);\n", dst_swizzle); 5806 } 5807 5808 static void shader_glsl_ld(const struct wined3d_shader_instruction *ins) 5809 { 5810 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5811 struct glsl_src_param coord_param, lod_param, sample_param; 5812 unsigned int resource_idx, sampler_idx, sampler_bind_idx; 5813 struct glsl_sample_function sample_function; 5814 DWORD flags = WINED3D_GLSL_SAMPLE_LOAD; 5815 BOOL has_lod_param; 5816 5817 if (wined3d_shader_instruction_has_texel_offset(ins)) 5818 flags |= WINED3D_GLSL_SAMPLE_OFFSET; 5819 5820 resource_idx = ins->src[1].reg.idx[0].offset; 5821 sampler_idx = WINED3D_SAMPLER_DEFAULT; 5822 5823 if (resource_idx >= ARRAY_SIZE(reg_maps->resource_info)) 5824 { 5825 ERR("Invalid resource index %u.\n", resource_idx); 5826 return; 5827 } 5828 has_lod_param = is_mipmapped(reg_maps->resource_info[resource_idx].type); 5829 5830 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function); 5831 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5832 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); 5833 sampler_bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, sampler_idx); 5834 if (is_multisampled(reg_maps->resource_info[resource_idx].type)) 5835 { 5836 shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &sample_param); 5837 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 5838 NULL, NULL, NULL, &ins->texel_offset, "%s, %s", coord_param.param_str, sample_param.param_str); 5839 } 5840 else 5841 { 5842 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 5843 NULL, NULL, has_lod_param ? lod_param.param_str : NULL, &ins->texel_offset, 5844 "%s", coord_param.param_str); 5845 } 5846 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5847 } 5848 5849 static void shader_glsl_sample(const struct wined3d_shader_instruction *ins) 5850 { 5851 const char *lod_param_str = NULL, *dx_param_str = NULL, *dy_param_str = NULL; 5852 struct glsl_src_param coord_param, lod_param, dx_param, dy_param; 5853 unsigned int resource_idx, sampler_idx, sampler_bind_idx; 5854 struct glsl_sample_function sample_function; 5855 DWORD flags = 0; 5856 5857 if (ins->handler_idx == WINED3DSIH_SAMPLE_GRAD) 5858 flags |= WINED3D_GLSL_SAMPLE_GRAD; 5859 if (ins->handler_idx == WINED3DSIH_SAMPLE_LOD) 5860 flags |= WINED3D_GLSL_SAMPLE_LOD; 5861 if (wined3d_shader_instruction_has_texel_offset(ins)) 5862 flags |= WINED3D_GLSL_SAMPLE_OFFSET; 5863 5864 resource_idx = ins->src[1].reg.idx[0].offset; 5865 sampler_idx = ins->src[2].reg.idx[0].offset; 5866 5867 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function); 5868 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5869 5870 switch (ins->handler_idx) 5871 { 5872 case WINED3DSIH_SAMPLE: 5873 break; 5874 case WINED3DSIH_SAMPLE_B: 5875 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param); 5876 lod_param_str = lod_param.param_str; 5877 break; 5878 case WINED3DSIH_SAMPLE_GRAD: 5879 shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dx_param); 5880 shader_glsl_add_src_param(ins, &ins->src[4], sample_function.deriv_mask, &dy_param); 5881 dx_param_str = dx_param.param_str; 5882 dy_param_str = dy_param.param_str; 5883 break; 5884 case WINED3DSIH_SAMPLE_LOD: 5885 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param); 5886 lod_param_str = lod_param.param_str; 5887 break; 5888 default: 5889 ERR("Unhandled opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 5890 break; 5891 } 5892 5893 sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx); 5894 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 5895 dx_param_str, dy_param_str, lod_param_str, &ins->texel_offset, "%s", coord_param.param_str); 5896 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5897 } 5898 5899 /* GLSL doesn't provide a function to sample from level zero with depth 5900 * comparison for array textures and cube textures. We use textureGrad*() 5901 * to implement sample_c_lz. 5902 */ 5903 static void shader_glsl_gen_sample_c_lz(const struct wined3d_shader_instruction *ins, 5904 unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, 5905 unsigned int coord_size, const char *coord_param, const char *ref_param) 5906 { 5907 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; 5908 unsigned int deriv_size = wined3d_popcount(sample_function->deriv_mask); 5909 const struct wined3d_shader_texel_offset *offset = &ins->texel_offset; 5910 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5911 char dst_swizzle[6]; 5912 5913 WARN("Emitting textureGrad() for sample_c_lz.\n"); 5914 5915 shader_glsl_swizzle_to_str(WINED3DSP_NOSWIZZLE, FALSE, ins->dst[0].write_mask, dst_swizzle); 5916 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], sample_function->data_type); 5917 shader_addline(buffer, "vec4(textureGrad%s(%s_sampler%u, vec%u(%s, %s), vec%u(0.0), vec%u(0.0)", 5918 sample_function->offset_size ? "Offset" : "", 5919 shader_glsl_get_prefix(version->type), sampler_bind_idx, 5920 coord_size, coord_param, ref_param, deriv_size, deriv_size); 5921 if (sample_function->offset_size) 5922 { 5923 int offset_immdata[4] = {offset->u, offset->v, offset->w}; 5924 shader_addline(buffer, ", "); 5925 shader_glsl_append_imm_ivec(buffer, offset_immdata, sample_function->offset_size); 5926 } 5927 shader_addline(buffer, "))%s);\n", dst_swizzle); 5928 } 5929 5930 static void shader_glsl_sample_c(const struct wined3d_shader_instruction *ins) 5931 { 5932 unsigned int resource_idx, sampler_idx, sampler_bind_idx; 5933 const struct wined3d_shader_resource_info *resource_info; 5934 struct glsl_src_param coord_param, compare_param; 5935 struct glsl_sample_function sample_function; 5936 const char *lod_param = NULL; 5937 unsigned int coord_size; 5938 DWORD flags = 0; 5939 5940 if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ) 5941 { 5942 lod_param = "0"; 5943 flags |= WINED3D_GLSL_SAMPLE_LOD; 5944 } 5945 5946 if (wined3d_shader_instruction_has_texel_offset(ins)) 5947 flags |= WINED3D_GLSL_SAMPLE_OFFSET; 5948 5949 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[1].reg))) 5950 return; 5951 resource_idx = ins->src[1].reg.idx[0].offset; 5952 sampler_idx = ins->src[2].reg.idx[0].offset; 5953 5954 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function); 5955 coord_size = shader_glsl_get_write_mask_size(sample_function.coord_mask); 5956 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask >> 1, &coord_param); 5957 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &compare_param); 5958 sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx); 5959 if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ 5960 && (resource_info->type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY 5961 || resource_info->type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)) 5962 { 5963 shader_glsl_gen_sample_c_lz(ins, sampler_bind_idx, &sample_function, 5964 coord_size, coord_param.param_str, compare_param.param_str); 5965 } 5966 else 5967 { 5968 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, WINED3DSP_NOSWIZZLE, 5969 NULL, NULL, lod_param, &ins->texel_offset, "vec%u(%s, %s)", 5970 coord_size, coord_param.param_str, compare_param.param_str); 5971 } 5972 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5973 } 5974 5975 static void shader_glsl_gather4(const struct wined3d_shader_instruction *ins) 5976 { 5977 unsigned int resource_param_idx, resource_idx, sampler_idx, sampler_bind_idx, component_idx; 5978 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5979 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 5980 struct glsl_src_param coord_param, compare_param, offset_param; 5981 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5982 const struct wined3d_shader_resource_info *resource_info; 5983 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5984 unsigned int coord_size, offset_size; 5985 char dst_swizzle[6]; 5986 BOOL has_offset; 5987 5988 if (!gl_info->supported[ARB_TEXTURE_GATHER]) 5989 { 5990 FIXME("OpenGL implementation does not support textureGather.\n"); 5991 return; 5992 } 5993 5994 has_offset = ins->handler_idx == WINED3DSIH_GATHER4_PO 5995 || ins->handler_idx == WINED3DSIH_GATHER4_PO_C 5996 || wined3d_shader_instruction_has_texel_offset(ins); 5997 5998 resource_param_idx = 5999 (ins->handler_idx == WINED3DSIH_GATHER4_PO || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) ? 2 : 1; 6000 resource_idx = ins->src[resource_param_idx].reg.idx[0].offset; 6001 sampler_idx = ins->src[resource_param_idx + 1].reg.idx[0].offset; 6002 component_idx = shader_glsl_swizzle_get_component(ins->src[resource_param_idx + 1].swizzle, 0); 6003 sampler_bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, sampler_idx); 6004 6005 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[resource_param_idx].reg))) 6006 return; 6007 6008 if (resource_info->type >= ARRAY_SIZE(resource_type_info)) 6009 { 6010 ERR("Unexpected resource type %#x.\n", resource_info->type); 6011 return; 6012 } 6013 shader_glsl_get_coord_size(resource_info->type, &coord_size, &offset_size); 6014 6015 shader_glsl_swizzle_to_str(ins->src[resource_param_idx].swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); 6016 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], resource_info->data_type); 6017 6018 shader_glsl_add_src_param(ins, &ins->src[0], (1u << coord_size) - 1, &coord_param); 6019 6020 shader_addline(buffer, "textureGather%s(%s_sampler%u, %s", 6021 has_offset ? "Offset" : "", prefix, sampler_bind_idx, coord_param.param_str); 6022 if (ins->handler_idx == WINED3DSIH_GATHER4_C || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) 6023 { 6024 shader_glsl_add_src_param(ins, &ins->src[resource_param_idx + 2], WINED3DSP_WRITEMASK_0, &compare_param); 6025 shader_addline(buffer, ", %s", compare_param.param_str); 6026 } 6027 if (ins->handler_idx == WINED3DSIH_GATHER4_PO || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) 6028 { 6029 shader_glsl_add_src_param(ins, &ins->src[1], (1u << offset_size) - 1, &offset_param); 6030 shader_addline(buffer, ", %s", offset_param.param_str); 6031 } 6032 else if (has_offset) 6033 { 6034 int offset_immdata[4] = {ins->texel_offset.u, ins->texel_offset.v, ins->texel_offset.w}; 6035 shader_addline(buffer, ", "); 6036 shader_glsl_append_imm_ivec(buffer, offset_immdata, offset_size); 6037 } 6038 if (component_idx) 6039 shader_addline(buffer, ", %u", component_idx); 6040 6041 shader_addline(buffer, ")%s);\n", dst_swizzle); 6042 } 6043 6044 static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins) 6045 { 6046 /* FIXME: Make this work for more than just 2D textures */ 6047 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6048 DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 6049 6050 if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4)) 6051 { 6052 char dst_mask[6]; 6053 6054 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 6055 shader_addline(buffer, "clamp(ffp_texcoord[%u], 0.0, 1.0)%s);\n", 6056 ins->dst[0].reg.idx[0].offset, dst_mask); 6057 } 6058 else 6059 { 6060 enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers; 6061 DWORD reg = ins->src[0].reg.idx[0].offset; 6062 char dst_swizzle[6]; 6063 6064 shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle); 6065 6066 if (src_mod == WINED3DSPSM_DZ || src_mod == WINED3DSPSM_DW) 6067 { 6068 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); 6069 struct glsl_src_param div_param; 6070 DWORD src_writemask = src_mod == WINED3DSPSM_DZ ? WINED3DSP_WRITEMASK_2 : WINED3DSP_WRITEMASK_3; 6071 6072 shader_glsl_add_src_param(ins, &ins->src[0], src_writemask, &div_param); 6073 6074 if (mask_size > 1) 6075 shader_addline(buffer, "ffp_texcoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str); 6076 else 6077 shader_addline(buffer, "ffp_texcoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str); 6078 } 6079 else 6080 { 6081 shader_addline(buffer, "ffp_texcoord[%u]%s);\n", reg, dst_swizzle); 6082 } 6083 } 6084 } 6085 6086 /** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL: 6087 * Take a 3-component dot product of the TexCoord[dstreg] and src, 6088 * then perform a 1D texture lookup from stage dstregnum, place into dst. */ 6089 static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) 6090 { 6091 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6092 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6093 struct glsl_sample_function sample_function; 6094 struct glsl_src_param src0_param; 6095 UINT mask_size; 6096 6097 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6098 6099 /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one 6100 * scalar, and projected sampling would require 4. 6101 * 6102 * It is a dependent read - not valid with conditional NP2 textures 6103 */ 6104 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6105 mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask); 6106 6107 switch(mask_size) 6108 { 6109 case 1: 6110 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, 6111 NULL, "dot(ffp_texcoord[%u].xyz, %s)", sampler_idx, src0_param.param_str); 6112 break; 6113 6114 case 2: 6115 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, 6116 NULL, "vec2(dot(ffp_texcoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str); 6117 break; 6118 6119 case 3: 6120 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, 6121 NULL, "vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str); 6122 break; 6123 6124 default: 6125 FIXME("Unexpected mask size %u\n", mask_size); 6126 break; 6127 } 6128 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6129 } 6130 6131 /** Process the WINED3DSIO_TEXDP3 instruction in GLSL: 6132 * Take a 3-component dot product of the TexCoord[dstreg] and src. */ 6133 static void shader_glsl_texdp3(const struct wined3d_shader_instruction *ins) 6134 { 6135 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6136 DWORD dstreg = ins->dst[0].reg.idx[0].offset; 6137 struct glsl_src_param src0_param; 6138 DWORD dst_mask; 6139 unsigned int mask_size; 6140 6141 dst_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 6142 mask_size = shader_glsl_get_write_mask_size(dst_mask); 6143 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6144 6145 if (mask_size > 1) { 6146 shader_addline(ins->ctx->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str); 6147 } else { 6148 shader_addline(ins->ctx->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str); 6149 } 6150 } 6151 6152 /** Process the WINED3DSIO_TEXDEPTH instruction in GLSL: 6153 * Calculate the depth as dst.x / dst.y */ 6154 static void shader_glsl_texdepth(const struct wined3d_shader_instruction *ins) 6155 { 6156 struct glsl_dst_param dst_param; 6157 6158 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 6159 6160 /* Tests show that texdepth never returns anything below 0.0, and that r5.y is clamped to 1.0. 6161 * Negative input is accepted, -0.25 / -0.5 returns 0.5. GL should clamp gl_FragDepth to [0;1], but 6162 * this doesn't always work, so clamp the results manually. Whether or not the x value is clamped at 1 6163 * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result 6164 * >= 1.0 or < 0.0 6165 */ 6166 shader_addline(ins->ctx->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n", 6167 dst_param.reg_name, dst_param.reg_name); 6168 } 6169 6170 /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL: 6171 * Last row of a 3x2 matrix multiply, use the result to calculate the depth: 6172 * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated) 6173 * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y 6174 */ 6175 static void shader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins) 6176 { 6177 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6178 DWORD dstreg = ins->dst[0].reg.idx[0].offset; 6179 struct glsl_src_param src0_param; 6180 6181 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6182 6183 shader_addline(ins->ctx->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str); 6184 shader_addline(ins->ctx->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n"); 6185 } 6186 6187 /** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL 6188 * Calculate the 1st of a 2-row matrix multiplication. */ 6189 static void shader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins) 6190 { 6191 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6192 DWORD reg = ins->dst[0].reg.idx[0].offset; 6193 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6194 struct glsl_src_param src0_param; 6195 6196 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6197 shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6198 } 6199 6200 /** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL 6201 * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */ 6202 static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins) 6203 { 6204 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6205 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6206 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6207 DWORD reg = ins->dst[0].reg.idx[0].offset; 6208 struct glsl_src_param src0_param; 6209 6210 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6211 shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + tex_mx->current_row, reg, src0_param.param_str); 6212 tex_mx->texcoord_w[tex_mx->current_row++] = reg; 6213 } 6214 6215 static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins) 6216 { 6217 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6218 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6219 struct glsl_sample_function sample_function; 6220 DWORD reg = ins->dst[0].reg.idx[0].offset; 6221 struct glsl_src_param src0_param; 6222 6223 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6224 shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6225 6226 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6227 6228 /* Sample the texture using the calculated coordinates */ 6229 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xy"); 6230 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6231 } 6232 6233 /** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL 6234 * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */ 6235 static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins) 6236 { 6237 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6238 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6239 struct glsl_sample_function sample_function; 6240 DWORD reg = ins->dst[0].reg.idx[0].offset; 6241 struct glsl_src_param src0_param; 6242 6243 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6244 shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6245 6246 /* Dependent read, not valid with conditional NP2 */ 6247 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6248 6249 /* Sample the texture using the calculated coordinates */ 6250 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xyz"); 6251 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6252 6253 tex_mx->current_row = 0; 6254 } 6255 6256 /** Process the WINED3DSIO_TEXM3X3 instruction in GLSL 6257 * Perform the 3rd row of a 3x3 matrix multiply */ 6258 static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) 6259 { 6260 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6261 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6262 DWORD reg = ins->dst[0].reg.idx[0].offset; 6263 struct glsl_src_param src0_param; 6264 char dst_mask[6]; 6265 6266 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6267 6268 shader_glsl_append_dst(ins->ctx->buffer, ins); 6269 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 6270 shader_addline(ins->ctx->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask); 6271 6272 tex_mx->current_row = 0; 6273 } 6274 6275 /* Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL 6276 * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ 6277 static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins) 6278 { 6279 struct glsl_src_param src0_param; 6280 struct glsl_src_param src1_param; 6281 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6282 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6283 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6284 struct glsl_sample_function sample_function; 6285 DWORD reg = ins->dst[0].reg.idx[0].offset; 6286 char coord_mask[6]; 6287 6288 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6289 shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param); 6290 6291 /* Perform the last matrix multiply operation */ 6292 shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6293 /* Reflection calculation */ 6294 shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str); 6295 6296 /* Dependent read, not valid with conditional NP2 */ 6297 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6298 shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask); 6299 6300 /* Sample the texture */ 6301 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 6302 NULL, NULL, NULL, NULL, "tmp0%s", coord_mask); 6303 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6304 6305 tex_mx->current_row = 0; 6306 } 6307 6308 /* Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL 6309 * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ 6310 static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins) 6311 { 6312 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6313 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6314 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6315 struct glsl_sample_function sample_function; 6316 DWORD reg = ins->dst[0].reg.idx[0].offset; 6317 struct glsl_src_param src0_param; 6318 char coord_mask[6]; 6319 6320 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6321 6322 /* Perform the last matrix multiply operation */ 6323 shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str); 6324 6325 /* Construct the eye-ray vector from w coordinates */ 6326 shader_addline(buffer, "tmp1.xyz = normalize(vec3(ffp_texcoord[%u].w, ffp_texcoord[%u].w, ffp_texcoord[%u].w));\n", 6327 tex_mx->texcoord_w[0], tex_mx->texcoord_w[1], reg); 6328 shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n"); 6329 6330 /* Dependent read, not valid with conditional NP2 */ 6331 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6332 shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask); 6333 6334 /* Sample the texture using the calculated coordinates */ 6335 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 6336 NULL, NULL, NULL, NULL, "tmp0%s", coord_mask); 6337 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6338 6339 tex_mx->current_row = 0; 6340 } 6341 6342 /** Process the WINED3DSIO_TEXBEM instruction in GLSL. 6343 * Apply a fake bump map transform. 6344 * texbem is pshader <= 1.3 only, this saves a few version checks 6345 */ 6346 static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins) 6347 { 6348 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 6349 struct glsl_sample_function sample_function; 6350 struct glsl_src_param coord_param; 6351 DWORD sampler_idx; 6352 DWORD mask; 6353 DWORD flags; 6354 char coord_mask[6]; 6355 6356 sampler_idx = ins->dst[0].reg.idx[0].offset; 6357 flags = (priv->cur_ps_args->tex_transform >> sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT) 6358 & WINED3D_PSARGS_TEXTRANSFORM_MASK; 6359 6360 /* Dependent read, not valid with conditional NP2 */ 6361 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6362 mask = sample_function.coord_mask; 6363 6364 shader_glsl_write_mask_to_str(mask, coord_mask); 6365 6366 /* With projected textures, texbem only divides the static texture coord, 6367 * not the displacement, so we can't let GL handle this. */ 6368 if (flags & WINED3D_PSARGS_PROJECTED) 6369 { 6370 DWORD div_mask=0; 6371 char coord_div_mask[3]; 6372 switch (flags & ~WINED3D_PSARGS_PROJECTED) 6373 { 6374 case WINED3D_TTFF_COUNT1: 6375 FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n"); 6376 break; 6377 case WINED3D_TTFF_COUNT2: 6378 div_mask = WINED3DSP_WRITEMASK_1; 6379 break; 6380 case WINED3D_TTFF_COUNT3: 6381 div_mask = WINED3DSP_WRITEMASK_2; 6382 break; 6383 case WINED3D_TTFF_COUNT4: 6384 case WINED3D_TTFF_DISABLE: 6385 div_mask = WINED3DSP_WRITEMASK_3; 6386 break; 6387 } 6388 shader_glsl_write_mask_to_str(div_mask, coord_div_mask); 6389 shader_addline(ins->ctx->buffer, "T%u%s /= T%u%s;\n", sampler_idx, coord_mask, sampler_idx, coord_div_mask); 6390 } 6391 6392 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &coord_param); 6393 6394 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6395 "T%u%s + vec4(bumpenv_mat%u * %s, 0.0, 0.0)%s", sampler_idx, coord_mask, sampler_idx, 6396 coord_param.param_str, coord_mask); 6397 6398 if (ins->handler_idx == WINED3DSIH_TEXBEML) 6399 { 6400 struct glsl_src_param luminance_param; 6401 struct glsl_dst_param dst_param; 6402 6403 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &luminance_param); 6404 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 6405 6406 shader_addline(ins->ctx->buffer, "%s%s *= (%s * bumpenv_lum_scale%u + bumpenv_lum_offset%u);\n", 6407 dst_param.reg_name, dst_param.mask_str, 6408 luminance_param.param_str, sampler_idx, sampler_idx); 6409 } 6410 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6411 } 6412 6413 static void shader_glsl_bem(const struct wined3d_shader_instruction *ins) 6414 { 6415 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6416 struct glsl_src_param src0_param, src1_param; 6417 6418 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param); 6419 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); 6420 6421 shader_glsl_append_dst(ins->ctx->buffer, ins); 6422 shader_addline(ins->ctx->buffer, "%s + bumpenv_mat%u * %s);\n", 6423 src0_param.param_str, sampler_idx, src1_param.param_str); 6424 } 6425 6426 /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL 6427 * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ 6428 static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) 6429 { 6430 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6431 struct glsl_sample_function sample_function; 6432 struct glsl_src_param src0_param; 6433 6434 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); 6435 6436 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6437 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6438 "%s.wx", src0_param.reg_name); 6439 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6440 } 6441 6442 /** Process the WINED3DSIO_TEXREG2GB instruction in GLSL 6443 * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */ 6444 static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) 6445 { 6446 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6447 struct glsl_sample_function sample_function; 6448 struct glsl_src_param src0_param; 6449 6450 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); 6451 6452 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6453 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6454 "%s.yz", src0_param.reg_name); 6455 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6456 } 6457 6458 /** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL 6459 * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */ 6460 static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins) 6461 { 6462 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6463 struct glsl_sample_function sample_function; 6464 struct glsl_src_param src0_param; 6465 6466 /* Dependent read, not valid with conditional NP2 */ 6467 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6468 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param); 6469 6470 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6471 "%s", src0_param.param_str); 6472 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6473 } 6474 6475 /** Process the WINED3DSIO_TEXKILL instruction in GLSL. 6476 * If any of the first 3 components are < 0, discard this pixel */ 6477 static void shader_glsl_texkill(const struct wined3d_shader_instruction *ins) 6478 { 6479 if (ins->ctx->reg_maps->shader_version.major >= 4) 6480 { 6481 shader_glsl_generate_conditional_op(ins, "discard;"); 6482 } 6483 else 6484 { 6485 struct glsl_dst_param dst_param; 6486 6487 /* The argument is a destination parameter, and no writemasks are allowed */ 6488 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 6489 6490 /* 2.0 shaders compare all 4 components in texkill. */ 6491 if (ins->ctx->reg_maps->shader_version.major >= 2) 6492 shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyzw, vec4(0.0)))) discard;\n", dst_param.reg_name); 6493 /* 1.x shaders only compare the first 3 components, probably due to 6494 * the nature of the texkill instruction as a tex* instruction, and 6495 * phase, which kills all .w components. Even if all 4 components are 6496 * defined, only the first 3 are used. */ 6497 else 6498 shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_param.reg_name); 6499 } 6500 } 6501 6502 /** Process the WINED3DSIO_DP2ADD instruction in GLSL. 6503 * dst = dot2(src0, src1) + src2 */ 6504 static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins) 6505 { 6506 struct glsl_src_param src0_param; 6507 struct glsl_src_param src1_param; 6508 struct glsl_src_param src2_param; 6509 DWORD write_mask; 6510 unsigned int mask_size; 6511 6512 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 6513 mask_size = shader_glsl_get_write_mask_size(write_mask); 6514 6515 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param); 6516 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); 6517 shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &src2_param); 6518 6519 if (mask_size > 1) { 6520 shader_addline(ins->ctx->buffer, "vec%d(dot(%s, %s) + %s));\n", 6521 mask_size, src0_param.param_str, src1_param.param_str, src2_param.param_str); 6522 } else { 6523 shader_addline(ins->ctx->buffer, "dot(%s, %s) + %s);\n", 6524 src0_param.param_str, src1_param.param_str, src2_param.param_str); 6525 } 6526 } 6527 6528 static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, 6529 const struct wined3d_shader_signature *input_signature, 6530 const struct wined3d_shader_reg_maps *reg_maps, 6531 const struct ps_compile_args *args, const struct wined3d_gl_info *gl_info, BOOL unroll) 6532 { 6533 unsigned int i; 6534 6535 for (i = 0; i < input_signature->element_count; ++i) 6536 { 6537 const struct wined3d_shader_signature_element *input = &input_signature->elements[i]; 6538 const char *semantic_name; 6539 UINT semantic_idx; 6540 char reg_mask[6]; 6541 6542 /* Unused */ 6543 if (!(reg_maps->input_registers & (1u << input->register_idx))) 6544 continue; 6545 6546 semantic_name = input->semantic_name; 6547 semantic_idx = input->semantic_idx; 6548 shader_glsl_write_mask_to_str(input->mask, reg_mask); 6549 6550 if (args->vp_mode == WINED3D_VP_MODE_SHADER) 6551 { 6552 if (input->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx) 6553 { 6554 shader_addline(buffer, "ps_in[%u]%s = vpos%s;\n", 6555 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6556 } 6557 else if (args->pointsprite && shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) 6558 { 6559 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", input->register_idx); 6560 } 6561 else if (input->sysval_semantic == WINED3D_SV_IS_FRONT_FACE) 6562 { 6563 shader_addline(buffer, "ps_in[%u]%s = uintBitsToFloat(gl_FrontFacing ? 0xffffffffu : 0u);\n", 6564 input->register_idx, reg_mask); 6565 } 6566 else if (input->sysval_semantic == WINED3D_SV_SAMPLE_INDEX) 6567 { 6568 if (gl_info->supported[ARB_SAMPLE_SHADING]) 6569 shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_SampleID);\n", 6570 input->register_idx, reg_mask); 6571 else 6572 FIXME("ARB_sample_shading is not supported.\n"); 6573 } 6574 else if (input->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx) 6575 { 6576 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT]) 6577 shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_Layer);\n", 6578 input->register_idx, reg_mask); 6579 else 6580 FIXME("ARB_fragment_layer_viewport is not supported.\n"); 6581 } 6582 else if (input->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx) 6583 { 6584 if (gl_info->supported[ARB_VIEWPORT_ARRAY]) 6585 shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_ViewportIndex);\n", 6586 input->register_idx, reg_mask); 6587 else 6588 FIXME("ARB_viewport_array is not supported.\n"); 6589 } 6590 else 6591 { 6592 if (input->sysval_semantic) 6593 FIXME("Unhandled sysval semantic %#x.\n", input->sysval_semantic); 6594 shader_addline(buffer, unroll ? "ps_in[%u]%s = %s%u%s;\n" : "ps_in[%u]%s = %s[%u]%s;\n", 6595 shader->u.ps.input_reg_map[input->register_idx], reg_mask, 6596 shader_glsl_shader_input_name(gl_info), 6597 shader->u.ps.input_reg_map[input->register_idx], reg_mask); 6598 } 6599 } 6600 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) 6601 { 6602 if (args->pointsprite) 6603 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", 6604 shader->u.ps.input_reg_map[input->register_idx]); 6605 else if (args->vp_mode == WINED3D_VP_MODE_NONE && args->texcoords_initialized & (1u << semantic_idx)) 6606 shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n", 6607 shader->u.ps.input_reg_map[input->register_idx], reg_mask, 6608 needs_legacy_glsl_syntax(gl_info) 6609 ? "gl_TexCoord" : "ffp_varying_texcoord", semantic_idx, reg_mask); 6610 else 6611 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", 6612 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6613 } 6614 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR)) 6615 { 6616 if (!semantic_idx) 6617 shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_diffuse)%s;\n", 6618 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6619 else if (semantic_idx == 1) 6620 shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_specular)%s;\n", 6621 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6622 else 6623 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", 6624 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6625 } 6626 else 6627 { 6628 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", 6629 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6630 } 6631 } 6632 } 6633 6634 static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry) 6635 { 6636 struct glsl_program_key key; 6637 6638 key.vs_id = entry->vs.id; 6639 key.hs_id = entry->hs.id; 6640 key.ds_id = entry->ds.id; 6641 key.gs_id = entry->gs.id; 6642 key.ps_id = entry->ps.id; 6643 key.cs_id = entry->cs.id; 6644 6645 if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1) 6646 { 6647 ERR("Failed to insert program entry.\n"); 6648 } 6649 } 6650 6651 static struct glsl_shader_prog_link *get_glsl_program_entry(const struct shader_glsl_priv *priv, 6652 const struct glsl_program_key *key) 6653 { 6654 struct wine_rb_entry *entry; 6655 6656 entry = wine_rb_get(&priv->program_lookup, key); 6657 return entry ? WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry) : NULL; 6658 } 6659 6660 /* Context activation is done by the caller. */ 6661 static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info, 6662 struct glsl_shader_prog_link *entry) 6663 { 6664 wine_rb_remove(&priv->program_lookup, &entry->program_lookup_entry); 6665 6666 GL_EXTCALL(glDeleteProgram(entry->id)); 6667 if (entry->vs.id) 6668 list_remove(&entry->vs.shader_entry); 6669 if (entry->hs.id) 6670 list_remove(&entry->hs.shader_entry); 6671 if (entry->ds.id) 6672 list_remove(&entry->ds.shader_entry); 6673 if (entry->gs.id) 6674 list_remove(&entry->gs.shader_entry); 6675 if (entry->ps.id) 6676 list_remove(&entry->ps.shader_entry); 6677 if (entry->cs.id) 6678 list_remove(&entry->cs.shader_entry); 6679 heap_free(entry); 6680 } 6681 6682 static void shader_glsl_setup_vs3_output(struct shader_glsl_priv *priv, 6683 const struct wined3d_gl_info *gl_info, const DWORD *map, 6684 const struct wined3d_shader_signature *input_signature, 6685 const struct wined3d_shader_reg_maps *reg_maps_in, 6686 const struct wined3d_shader_signature *output_signature, 6687 const struct wined3d_shader_reg_maps *reg_maps_out) 6688 { 6689 struct wined3d_string_buffer *destination = string_buffer_get(&priv->string_buffers); 6690 const char *out_array_name = shader_glsl_shader_output_name(gl_info); 6691 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6692 unsigned int in_count = vec4_varyings(3, gl_info); 6693 unsigned int max_varyings = needs_legacy_glsl_syntax(gl_info) ? in_count + 2 : in_count; 6694 DWORD in_idx, *set = NULL; 6695 unsigned int i, j; 6696 char reg_mask[6]; 6697 6698 set = heap_calloc(max_varyings, sizeof(*set)); 6699 6700 for (i = 0; i < input_signature->element_count; ++i) 6701 { 6702 const struct wined3d_shader_signature_element *input = &input_signature->elements[i]; 6703 6704 if (!(reg_maps_in->input_registers & (1u << input->register_idx))) 6705 continue; 6706 6707 in_idx = map[input->register_idx]; 6708 /* Declared, but not read register */ 6709 if (in_idx == ~0u) 6710 continue; 6711 if (in_idx >= max_varyings) 6712 { 6713 FIXME("More input varyings declared than supported, expect issues.\n"); 6714 continue; 6715 } 6716 6717 if (in_idx == in_count) 6718 string_buffer_sprintf(destination, "gl_FrontColor"); 6719 else if (in_idx == in_count + 1) 6720 string_buffer_sprintf(destination, "gl_FrontSecondaryColor"); 6721 else 6722 string_buffer_sprintf(destination, "%s[%u]", out_array_name, in_idx); 6723 6724 if (!set[in_idx]) 6725 set[in_idx] = ~0u; 6726 6727 for (j = 0; j < output_signature->element_count; ++j) 6728 { 6729 const struct wined3d_shader_signature_element *output = &output_signature->elements[j]; 6730 DWORD mask; 6731 6732 if (!(reg_maps_out->output_registers & (1u << output->register_idx)) 6733 || input->semantic_idx != output->semantic_idx 6734 || strcmp(input->semantic_name, output->semantic_name) 6735 || !(mask = input->mask & output->mask)) 6736 continue; 6737 6738 if (set[in_idx] == ~0u) 6739 set[in_idx] = 0; 6740 set[in_idx] |= mask & reg_maps_out->u.output_registers_mask[output->register_idx]; 6741 shader_glsl_write_mask_to_str(mask, reg_mask); 6742 6743 shader_addline(buffer, "%s%s = outputs[%u]%s;\n", 6744 destination->buffer, reg_mask, output->register_idx, reg_mask); 6745 } 6746 } 6747 6748 for (i = 0; i < max_varyings; ++i) 6749 { 6750 unsigned int size; 6751 6752 if (!set[i] || set[i] == WINED3DSP_WRITEMASK_ALL) 6753 continue; 6754 6755 if (set[i] == ~0u) 6756 set[i] = 0; 6757 6758 size = 0; 6759 if (!(set[i] & WINED3DSP_WRITEMASK_0)) 6760 reg_mask[size++] = 'x'; 6761 if (!(set[i] & WINED3DSP_WRITEMASK_1)) 6762 reg_mask[size++] = 'y'; 6763 if (!(set[i] & WINED3DSP_WRITEMASK_2)) 6764 reg_mask[size++] = 'z'; 6765 if (!(set[i] & WINED3DSP_WRITEMASK_3)) 6766 reg_mask[size++] = 'w'; 6767 reg_mask[size] = '\0'; 6768 6769 if (i == in_count) 6770 string_buffer_sprintf(destination, "gl_FrontColor"); 6771 else if (i == in_count + 1) 6772 string_buffer_sprintf(destination, "gl_FrontSecondaryColor"); 6773 else 6774 string_buffer_sprintf(destination, "%s[%u]", out_array_name, i); 6775 6776 if (size == 1) 6777 shader_addline(buffer, "%s.%s = 0.0;\n", destination->buffer, reg_mask); 6778 else 6779 shader_addline(buffer, "%s.%s = vec%u(0.0);\n", destination->buffer, reg_mask, size); 6780 } 6781 6782 heap_free(set); 6783 string_buffer_release(&priv->string_buffers, destination); 6784 } 6785 6786 static void shader_glsl_setup_sm4_shader_output(struct shader_glsl_priv *priv, 6787 unsigned int input_count, const struct wined3d_shader_signature *output_signature, 6788 const struct wined3d_shader_reg_maps *reg_maps_out, const char *output_variable_name, 6789 BOOL rasterizer_setup) 6790 { 6791 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6792 char reg_mask[6]; 6793 unsigned int i; 6794 6795 for (i = 0; i < output_signature->element_count; ++i) 6796 { 6797 const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; 6798 6799 if (!(reg_maps_out->output_registers & (1u << output->register_idx))) 6800 continue; 6801 6802 if (output->stream_idx) 6803 continue; 6804 6805 if (output->register_idx >= input_count) 6806 continue; 6807 6808 shader_glsl_write_mask_to_str(output->mask, reg_mask); 6809 6810 shader_addline(buffer, 6811 rasterizer_setup ? "%s.reg%u%s = outputs[%u]%s;\n" : "%s.reg[%u]%s = outputs[%u]%s;\n", 6812 output_variable_name, output->register_idx, reg_mask, output->register_idx, reg_mask); 6813 } 6814 } 6815 6816 static void shader_glsl_generate_clip_or_cull_distances(struct wined3d_string_buffer *buffer, 6817 const struct wined3d_shader_signature_element *element, DWORD clip_or_cull_distance_mask) 6818 { 6819 unsigned int i, clip_or_cull_index; 6820 const char *name; 6821 char reg_mask[6]; 6822 6823 name = element->sysval_semantic == WINED3D_SV_CLIP_DISTANCE ? "Clip" : "Cull"; 6824 /* Assign consecutive indices starting from 0. */ 6825 clip_or_cull_index = element->semantic_idx ? wined3d_popcount(clip_or_cull_distance_mask & 0xf) : 0; 6826 for (i = 0; i < 4; ++i) 6827 { 6828 if (!(element->mask & (WINED3DSP_WRITEMASK_0 << i))) 6829 continue; 6830 6831 shader_glsl_write_mask_to_str(WINED3DSP_WRITEMASK_0 << i, reg_mask); 6832 shader_addline(buffer, "gl_%sDistance[%u] = outputs[%u]%s;\n", 6833 name, clip_or_cull_index, element->register_idx, reg_mask); 6834 ++clip_or_cull_index; 6835 } 6836 } 6837 6838 static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv, 6839 const struct wined3d_gl_info *gl_info, const DWORD *map, 6840 const struct wined3d_shader_signature *input_signature, 6841 const struct wined3d_shader_reg_maps *reg_maps_in, unsigned int input_count, 6842 const struct wined3d_shader_signature *output_signature, 6843 const struct wined3d_shader_reg_maps *reg_maps_out, BOOL per_vertex_point_size) 6844 { 6845 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6846 const char *semantic_name; 6847 unsigned int semantic_idx; 6848 char reg_mask[6]; 6849 unsigned int i; 6850 6851 /* First, sort out position and point size system values. */ 6852 for (i = 0; i < output_signature->element_count; ++i) 6853 { 6854 const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; 6855 6856 if (!(reg_maps_out->output_registers & (1u << output->register_idx))) 6857 continue; 6858 6859 if (output->stream_idx) 6860 continue; 6861 6862 semantic_name = output->semantic_name; 6863 semantic_idx = output->semantic_idx; 6864 shader_glsl_write_mask_to_str(output->mask, reg_mask); 6865 6866 if (output->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx) 6867 { 6868 shader_addline(buffer, "gl_Position%s = outputs[%u]%s;\n", 6869 reg_mask, output->register_idx, reg_mask); 6870 } 6871 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size) 6872 { 6873 shader_addline(buffer, "gl_PointSize = clamp(outputs[%u].%c, " 6874 "ffp_point.size_min, ffp_point.size_max);\n", output->register_idx, reg_mask[1]); 6875 } 6876 else if (output->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx) 6877 { 6878 shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n", 6879 output->register_idx, reg_mask); 6880 } 6881 else if (output->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx) 6882 { 6883 shader_addline(buffer, "gl_ViewportIndex = floatBitsToInt(outputs[%u])%s;\n", 6884 output->register_idx, reg_mask); 6885 } 6886 else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE) 6887 { 6888 shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask); 6889 } 6890 else if (output->sysval_semantic == WINED3D_SV_CULL_DISTANCE) 6891 { 6892 shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->cull_distance_mask); 6893 } 6894 else if (output->sysval_semantic) 6895 { 6896 FIXME("Unhandled sysval semantic %#x.\n", output->sysval_semantic); 6897 } 6898 } 6899 6900 /* Then, setup the pixel shader input. */ 6901 if (reg_maps_out->shader_version.major < 4) 6902 shader_glsl_setup_vs3_output(priv, gl_info, map, input_signature, reg_maps_in, 6903 output_signature, reg_maps_out); 6904 else 6905 shader_glsl_setup_sm4_shader_output(priv, input_count, output_signature, reg_maps_out, "shader_out", TRUE); 6906 } 6907 6908 /* Context activation is done by the caller. */ 6909 static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl_priv *priv, 6910 const struct wined3d_shader *vs, const struct wined3d_shader *ps, 6911 BOOL per_vertex_point_size, BOOL flatshading, const struct wined3d_gl_info *gl_info) 6912 { 6913 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 6914 DWORD ps_major = ps ? ps->reg_maps.shader_version.major : 0; 6915 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6916 const char *semantic_name; 6917 UINT semantic_idx; 6918 char reg_mask[6]; 6919 unsigned int i; 6920 GLuint ret; 6921 6922 string_buffer_clear(buffer); 6923 6924 shader_glsl_add_version_declaration(buffer, gl_info); 6925 6926 if (per_vertex_point_size) 6927 { 6928 shader_addline(buffer, "uniform struct\n{\n"); 6929 shader_addline(buffer, " float size_min;\n"); 6930 shader_addline(buffer, " float size_max;\n"); 6931 shader_addline(buffer, "} ffp_point;\n"); 6932 } 6933 6934 if (ps_major < 3) 6935 { 6936 DWORD colors_written_mask[2] = {0}; 6937 DWORD texcoords_written_mask[MAX_TEXTURES] = {0}; 6938 6939 if (!legacy_syntax) 6940 { 6941 declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_diffuse;\n"); 6942 declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_specular;\n"); 6943 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 6944 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 6945 } 6946 6947 shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output); 6948 6949 for (i = 0; i < vs->output_signature.element_count; ++i) 6950 { 6951 const struct wined3d_shader_signature_element *output = &vs->output_signature.elements[i]; 6952 DWORD write_mask; 6953 6954 if (!(vs->reg_maps.output_registers & (1u << output->register_idx))) 6955 continue; 6956 6957 semantic_name = output->semantic_name; 6958 semantic_idx = output->semantic_idx; 6959 write_mask = output->mask; 6960 shader_glsl_write_mask_to_str(write_mask, reg_mask); 6961 6962 if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR) && semantic_idx < 2) 6963 { 6964 if (legacy_syntax) 6965 shader_addline(buffer, "gl_Front%sColor%s = outputs[%u]%s;\n", 6966 semantic_idx ? "Secondary" : "", reg_mask, output->register_idx, reg_mask); 6967 else 6968 shader_addline(buffer, "ffp_varying_%s%s = clamp(outputs[%u]%s, 0.0, 1.0);\n", 6969 semantic_idx ? "specular" : "diffuse", reg_mask, output->register_idx, reg_mask); 6970 6971 colors_written_mask[semantic_idx] = write_mask; 6972 } 6973 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION) && !semantic_idx) 6974 { 6975 shader_addline(buffer, "gl_Position%s = outputs[%u]%s;\n", 6976 reg_mask, output->register_idx, reg_mask); 6977 } 6978 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) 6979 { 6980 if (semantic_idx < MAX_TEXTURES) 6981 { 6982 shader_addline(buffer, "%s[%u]%s = outputs[%u]%s;\n", 6983 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", 6984 semantic_idx, reg_mask, output->register_idx, reg_mask); 6985 texcoords_written_mask[semantic_idx] = write_mask; 6986 } 6987 } 6988 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size) 6989 { 6990 shader_addline(buffer, "gl_PointSize = clamp(outputs[%u].%c, " 6991 "ffp_point.size_min, ffp_point.size_max);\n", output->register_idx, reg_mask[1]); 6992 } 6993 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG)) 6994 { 6995 shader_addline(buffer, "%s = clamp(outputs[%u].%c, 0.0, 1.0);\n", 6996 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord", 6997 output->register_idx, reg_mask[1]); 6998 } 6999 } 7000 7001 for (i = 0; i < 2; ++i) 7002 { 7003 if (colors_written_mask[i] != WINED3DSP_WRITEMASK_ALL) 7004 { 7005 shader_glsl_write_mask_to_str(~colors_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask); 7006 if (!i) 7007 shader_addline(buffer, "%s%s = vec4(1.0)%s;\n", 7008 legacy_syntax ? "gl_FrontColor" : "ffp_varying_diffuse", 7009 reg_mask, reg_mask); 7010 else 7011 shader_addline(buffer, "%s%s = vec4(0.0)%s;\n", 7012 legacy_syntax ? "gl_FrontSecondaryColor" : "ffp_varying_specular", 7013 reg_mask, reg_mask); 7014 } 7015 } 7016 for (i = 0; i < MAX_TEXTURES; ++i) 7017 { 7018 if (ps && !(ps->reg_maps.texcoord & (1u << i))) 7019 continue; 7020 7021 if (texcoords_written_mask[i] != WINED3DSP_WRITEMASK_ALL) 7022 { 7023 if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info) 7024 && !texcoords_written_mask[i]) 7025 continue; 7026 7027 shader_glsl_write_mask_to_str(~texcoords_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask); 7028 shader_addline(buffer, "%s[%u]%s = vec4(0.0)%s;\n", 7029 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", i, reg_mask, reg_mask); 7030 } 7031 } 7032 } 7033 else 7034 { 7035 unsigned int in_count = min(vec4_varyings(ps_major, gl_info), ps->limits->packed_input); 7036 7037 shader_glsl_declare_shader_outputs(gl_info, buffer, in_count, FALSE, NULL); 7038 shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output); 7039 shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, ps->u.ps.input_reg_map, &ps->input_signature, 7040 &ps->reg_maps, 0, &vs->output_signature, &vs->reg_maps, per_vertex_point_size); 7041 } 7042 7043 shader_addline(buffer, "}\n"); 7044 7045 ret = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 7046 checkGLcall("glCreateShader(GL_VERTEX_SHADER)"); 7047 shader_glsl_compile(gl_info, ret, buffer->buffer); 7048 7049 return ret; 7050 } 7051 7052 static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *priv, 7053 const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc) 7054 { 7055 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7056 unsigned int i; 7057 7058 shader_addline(buffer, "out shader_in_out\n{\n"); 7059 for (i = 0; i < so_desc->element_count; ++i) 7060 { 7061 const struct wined3d_stream_output_element *e = &so_desc->elements[i]; 7062 7063 if (e->stream_idx) 7064 { 7065 FIXME("Unhandled stream %u.\n", e->stream_idx); 7066 continue; 7067 } 7068 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP) 7069 continue; 7070 7071 if (e->component_idx || e->component_count != 4) 7072 { 7073 if (e->component_count == 1) 7074 shader_addline(buffer, "float"); 7075 else 7076 shader_addline(buffer, "vec%u", e->component_count); 7077 shader_addline(buffer, " reg%u_%u_%u;\n", 7078 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1); 7079 } 7080 else 7081 { 7082 shader_addline(buffer, "vec4 reg%u;\n", e->register_idx); 7083 } 7084 } 7085 shader_addline(buffer, "} shader_out;\n"); 7086 7087 shader_addline(buffer, "void setup_gs_output(in vec4 outputs[%u])\n{\n", 7088 shader->limits->packed_output); 7089 for (i = 0; i < so_desc->element_count; ++i) 7090 { 7091 const struct wined3d_stream_output_element *e = &so_desc->elements[i]; 7092 7093 if (e->stream_idx) 7094 { 7095 FIXME("Unhandled stream %u.\n", e->stream_idx); 7096 continue; 7097 } 7098 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP) 7099 continue; 7100 7101 if (e->component_idx || e->component_count != 4) 7102 { 7103 DWORD write_mask; 7104 char str_mask[6]; 7105 7106 write_mask = ((1u << e->component_count) - 1) << e->component_idx; 7107 shader_glsl_write_mask_to_str(write_mask, str_mask); 7108 shader_addline(buffer, "shader_out.reg%u_%u_%u = outputs[%u]%s;\n", 7109 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1, 7110 e->register_idx, str_mask); 7111 } 7112 else 7113 { 7114 shader_addline(buffer, "shader_out.reg%u = outputs[%u];\n", 7115 e->register_idx, e->register_idx); 7116 } 7117 } 7118 shader_addline(buffer, "}\n"); 7119 } 7120 7121 static void shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv *priv, 7122 const struct wined3d_shader *shader, unsigned int input_count, 7123 const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup, const DWORD *interpolation_mode) 7124 { 7125 const char *prefix = shader_glsl_get_prefix(shader->reg_maps.shader_version.type); 7126 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7127 7128 if (rasterizer_setup) 7129 input_count = min(vec4_varyings(4, gl_info), input_count); 7130 7131 if (input_count) 7132 shader_glsl_declare_shader_outputs(gl_info, buffer, input_count, rasterizer_setup, interpolation_mode); 7133 7134 shader_addline(buffer, "void setup_%s_output(in vec4 outputs[%u])\n{\n", 7135 prefix, shader->limits->packed_output); 7136 7137 if (rasterizer_setup) 7138 shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, NULL, NULL, 7139 NULL, input_count, &shader->output_signature, &shader->reg_maps, FALSE); 7140 else 7141 shader_glsl_setup_sm4_shader_output(priv, input_count, &shader->output_signature, 7142 &shader->reg_maps, "shader_out", rasterizer_setup); 7143 7144 shader_addline(buffer, "}\n"); 7145 } 7146 7147 static void shader_glsl_generate_patch_constant_name(struct wined3d_string_buffer *buffer, 7148 const struct wined3d_shader_signature_element *constant, unsigned int *user_constant_idx, 7149 const char *reg_mask) 7150 { 7151 if (!constant->sysval_semantic) 7152 { 7153 shader_addline(buffer, "user_patch_constant[%u]%s", (*user_constant_idx)++, reg_mask); 7154 return; 7155 } 7156 7157 switch (constant->sysval_semantic) 7158 { 7159 case WINED3D_SV_TESS_FACTOR_QUADEDGE: 7160 case WINED3D_SV_TESS_FACTOR_TRIEDGE: 7161 case WINED3D_SV_TESS_FACTOR_LINEDET: 7162 case WINED3D_SV_TESS_FACTOR_LINEDEN: 7163 shader_addline(buffer, "gl_TessLevelOuter[%u]", constant->semantic_idx); 7164 break; 7165 case WINED3D_SV_TESS_FACTOR_QUADINT: 7166 case WINED3D_SV_TESS_FACTOR_TRIINT: 7167 shader_addline(buffer, "gl_TessLevelInner[%u]", constant->semantic_idx); 7168 break; 7169 default: 7170 FIXME("Unhandled sysval semantic %#x.\n", constant->sysval_semantic); 7171 shader_addline(buffer, "vec4(0.0)%s", reg_mask); 7172 } 7173 } 7174 7175 static void shader_glsl_generate_patch_constant_setup(struct wined3d_string_buffer *buffer, 7176 const struct wined3d_shader_signature *signature, BOOL input_setup) 7177 { 7178 unsigned int i, register_count, user_constant_index, user_constant_count; 7179 7180 register_count = user_constant_count = 0; 7181 for (i = 0; i < signature->element_count; ++i) 7182 { 7183 const struct wined3d_shader_signature_element *constant = &signature->elements[i]; 7184 register_count = max(constant->register_idx + 1, register_count); 7185 if (!constant->sysval_semantic) 7186 ++user_constant_count; 7187 } 7188 7189 if (user_constant_count) 7190 shader_addline(buffer, "patch %s vec4 user_patch_constant[%u];\n", 7191 input_setup ? "in" : "out", user_constant_count); 7192 if (input_setup) 7193 shader_addline(buffer, "vec4 vpc[%u];\n", register_count); 7194 7195 shader_addline(buffer, "void setup_patch_constant_%s()\n{\n", input_setup ? "input" : "output"); 7196 for (i = 0, user_constant_index = 0; i < signature->element_count; ++i) 7197 { 7198 const struct wined3d_shader_signature_element *constant = &signature->elements[i]; 7199 char reg_mask[6]; 7200 7201 shader_glsl_write_mask_to_str(constant->mask, reg_mask); 7202 7203 if (input_setup) 7204 shader_addline(buffer, "vpc[%u]%s", constant->register_idx, reg_mask); 7205 else 7206 shader_glsl_generate_patch_constant_name(buffer, constant, &user_constant_index, reg_mask); 7207 7208 shader_addline(buffer, " = "); 7209 7210 if (input_setup) 7211 shader_glsl_generate_patch_constant_name(buffer, constant, &user_constant_index, reg_mask); 7212 else 7213 shader_addline(buffer, "hs_out[%u]%s", constant->register_idx, reg_mask); 7214 7215 shader_addline(buffer, ";\n"); 7216 } 7217 shader_addline(buffer, "}\n"); 7218 } 7219 7220 static void shader_glsl_generate_srgb_write_correction(struct wined3d_string_buffer *buffer, 7221 const struct wined3d_gl_info *gl_info) 7222 { 7223 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7224 7225 shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(srgb_const0.x));\n", output); 7226 shader_addline(buffer, "tmp0.xyz = tmp0.xyz * vec3(srgb_const0.y) - vec3(srgb_const0.z);\n"); 7227 shader_addline(buffer, "tmp1.xyz = %s.xyz * vec3(srgb_const0.w);\n", output); 7228 shader_addline(buffer, "bvec3 srgb_compare = lessThan(%s.xyz, vec3(srgb_const1.x));\n", output); 7229 shader_addline(buffer, "%s.xyz = mix(tmp0.xyz, tmp1.xyz, vec3(srgb_compare));\n", output); 7230 shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", output, output); 7231 } 7232 7233 static void shader_glsl_generate_fog_code(struct wined3d_string_buffer *buffer, 7234 const struct wined3d_gl_info *gl_info, enum wined3d_ffp_ps_fog_mode mode) 7235 { 7236 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7237 7238 switch (mode) 7239 { 7240 case WINED3D_FFP_PS_FOG_OFF: 7241 return; 7242 7243 case WINED3D_FFP_PS_FOG_LINEAR: 7244 shader_addline(buffer, "float fog = (ffp_fog.end - ffp_varying_fogcoord) * ffp_fog.scale;\n"); 7245 break; 7246 7247 case WINED3D_FFP_PS_FOG_EXP: 7248 shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_varying_fogcoord);\n"); 7249 break; 7250 7251 case WINED3D_FFP_PS_FOG_EXP2: 7252 shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_fog.density" 7253 " * ffp_varying_fogcoord * ffp_varying_fogcoord);\n"); 7254 break; 7255 7256 default: 7257 ERR("Invalid fog mode %#x.\n", mode); 7258 return; 7259 } 7260 7261 shader_addline(buffer, "%s.xyz = mix(ffp_fog.color.xyz, %s.xyz, clamp(fog, 0.0, 1.0));\n", 7262 output, output); 7263 } 7264 7265 static void shader_glsl_generate_alpha_test(struct wined3d_string_buffer *buffer, 7266 const struct wined3d_gl_info *gl_info, enum wined3d_cmp_func alpha_func) 7267 { 7268 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7269 7270 /* alpha_func is the PASS condition, not the DISCARD condition. Instead of 7271 * flipping all the operators here, just negate the comparison below. */ 7272 static const char * const comparison_operator[] = 7273 { 7274 "", /* WINED3D_CMP_NEVER */ 7275 "<", /* WINED3D_CMP_LESS */ 7276 "==", /* WINED3D_CMP_EQUAL */ 7277 "<=", /* WINED3D_CMP_LESSEQUAL */ 7278 ">", /* WINED3D_CMP_GREATER */ 7279 "!=", /* WINED3D_CMP_NOTEQUAL */ 7280 ">=", /* WINED3D_CMP_GREATEREQUAL */ 7281 "" /* WINED3D_CMP_ALWAYS */ 7282 }; 7283 7284 if (alpha_func == WINED3D_CMP_ALWAYS) 7285 return; 7286 7287 if (alpha_func != WINED3D_CMP_NEVER) 7288 shader_addline(buffer, "if (!(%s.a %s alpha_test_ref))\n", 7289 output, comparison_operator[alpha_func - WINED3D_CMP_NEVER]); 7290 shader_addline(buffer, " discard;\n"); 7291 } 7292 7293 static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer, 7294 const struct wined3d_gl_info *gl_info) 7295 { 7296 if (gl_info->supported[ARB_CULL_DISTANCE]) 7297 shader_addline(buffer, "#extension GL_ARB_cull_distance : enable\n"); 7298 if (gl_info->supported[ARB_GPU_SHADER5]) 7299 shader_addline(buffer, "#extension GL_ARB_gpu_shader5 : enable\n"); 7300 if (gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS]) 7301 shader_addline(buffer, "#extension GL_ARB_shader_atomic_counters : enable\n"); 7302 if (gl_info->supported[ARB_SHADER_BIT_ENCODING]) 7303 shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n"); 7304 if (gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE]) 7305 shader_addline(buffer, "#extension GL_ARB_shader_image_load_store : enable\n"); 7306 if (gl_info->supported[ARB_SHADER_IMAGE_SIZE]) 7307 shader_addline(buffer, "#extension GL_ARB_shader_image_size : enable\n"); 7308 if (gl_info->supported[ARB_SHADER_STORAGE_BUFFER_OBJECT]) 7309 shader_addline(buffer, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); 7310 if (gl_info->supported[ARB_SHADER_TEXTURE_IMAGE_SAMPLES]) 7311 shader_addline(buffer, "#extension GL_ARB_shader_texture_image_samples : enable\n"); 7312 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) 7313 shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n"); 7314 if (gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]) 7315 shader_addline(buffer, "#extension GL_ARB_shading_language_packing : enable\n"); 7316 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) 7317 shader_addline(buffer, "#extension GL_ARB_texture_cube_map_array : enable\n"); 7318 if (gl_info->supported[ARB_TEXTURE_GATHER]) 7319 shader_addline(buffer, "#extension GL_ARB_texture_gather : enable\n"); 7320 if (gl_info->supported[ARB_TEXTURE_QUERY_LEVELS]) 7321 shader_addline(buffer, "#extension GL_ARB_texture_query_levels : enable\n"); 7322 if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT]) 7323 shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n"); 7324 if (gl_info->supported[ARB_VIEWPORT_ARRAY]) 7325 shader_addline(buffer, "#extension GL_ARB_viewport_array : enable\n"); 7326 if (gl_info->supported[EXT_GPU_SHADER4]) 7327 shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n"); 7328 if (gl_info->supported[EXT_TEXTURE_ARRAY]) 7329 shader_addline(buffer, "#extension GL_EXT_texture_array : enable\n"); 7330 } 7331 7332 static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_info, 7333 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 7334 const struct ps_compile_args *args) 7335 { 7336 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7337 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7338 7339 /* Pixel shaders < 2.0 place the resulting color in R0 implicitly. */ 7340 if (reg_maps->shader_version.major < 2) 7341 shader_addline(buffer, "%s = R0;\n", output); 7342 7343 if (args->srgb_correction) 7344 shader_glsl_generate_srgb_write_correction(buffer, gl_info); 7345 7346 /* SM < 3 does not replace the fog stage. */ 7347 if (reg_maps->shader_version.major < 3) 7348 shader_glsl_generate_fog_code(buffer, gl_info, args->fog); 7349 7350 shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1); 7351 7352 if (reg_maps->sample_mask) 7353 shader_addline(buffer, "gl_SampleMask[0] = floatBitsToInt(sample_mask);\n"); 7354 } 7355 7356 /* Context activation is done by the caller. */ 7357 static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context, 7358 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, 7359 const struct wined3d_shader *shader, 7360 const struct ps_compile_args *args, struct ps_np2fixup_info *np2fixup_info) 7361 { 7362 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7363 const struct wined3d_shader_version *version = ®_maps->shader_version; 7364 const char *prefix = shader_glsl_get_prefix(version->type); 7365 const struct wined3d_gl_info *gl_info = context->gl_info; 7366 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 7367 unsigned int i, extra_constants_needed = 0; 7368 struct shader_glsl_ctx_priv priv_ctx; 7369 GLuint shader_id; 7370 DWORD map; 7371 7372 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7373 priv_ctx.cur_ps_args = args; 7374 priv_ctx.cur_np2fixup_info = np2fixup_info; 7375 priv_ctx.string_buffers = string_buffers; 7376 7377 shader_glsl_add_version_declaration(buffer, gl_info); 7378 7379 shader_glsl_enable_extensions(buffer, gl_info); 7380 if (gl_info->supported[ARB_CONSERVATIVE_DEPTH]) 7381 shader_addline(buffer, "#extension GL_ARB_conservative_depth : enable\n"); 7382 if (gl_info->supported[ARB_DERIVATIVE_CONTROL]) 7383 shader_addline(buffer, "#extension GL_ARB_derivative_control : enable\n"); 7384 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7385 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 7386 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7387 shader_addline(buffer, "#extension GL_ARB_fragment_coord_conventions : enable\n"); 7388 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT]) 7389 shader_addline(buffer, "#extension GL_ARB_fragment_layer_viewport : enable\n"); 7390 if (gl_info->supported[ARB_SAMPLE_SHADING]) 7391 shader_addline(buffer, "#extension GL_ARB_sample_shading : enable\n"); 7392 if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 7393 shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n"); 7394 /* The spec says that it doesn't have to be explicitly enabled, but the 7395 * nvidia drivers write a warning if we don't do so. */ 7396 if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) 7397 shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); 7398 7399 /* Base Declarations */ 7400 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7401 7402 if (gl_info->supported[ARB_CONSERVATIVE_DEPTH]) 7403 { 7404 if (shader->u.ps.depth_output == WINED3DSPR_DEPTHOUTGE) 7405 shader_addline(buffer, "layout (depth_greater) out float gl_FragDepth;\n"); 7406 else if (shader->u.ps.depth_output == WINED3DSPR_DEPTHOUTLE) 7407 shader_addline(buffer, "layout (depth_less) out float gl_FragDepth;\n"); 7408 } 7409 7410 /* Declare uniforms for NP2 texcoord fixup: 7411 * This is NOT done inside the loop that declares the texture samplers 7412 * since the NP2 fixup code is currently only used for the GeforceFX 7413 * series and when forcing the ARB_npot extension off. Modern cards just 7414 * skip the code anyway, so put it inside a separate loop. */ 7415 if (args->np2_fixup) 7416 { 7417 struct ps_np2fixup_info *fixup = priv_ctx.cur_np2fixup_info; 7418 unsigned int cur = 0; 7419 7420 /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] 7421 * while D3D has them in the (normalized) [0,1]x[0,1] range. 7422 * samplerNP2Fixup stores texture dimensions and is updated through 7423 * shader_glsl_load_np2fixup_constants when the sampler changes. */ 7424 7425 for (i = 0; i < shader->limits->sampler; ++i) 7426 { 7427 if (!reg_maps->resource_info[i].type || !(args->np2_fixup & (1u << i))) 7428 continue; 7429 7430 if (reg_maps->resource_info[i].type != WINED3D_SHADER_RESOURCE_TEXTURE_2D) 7431 { 7432 FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n"); 7433 continue; 7434 } 7435 7436 fixup->idx[i] = cur++; 7437 } 7438 7439 fixup->num_consts = (cur + 1) >> 1; 7440 fixup->active = args->np2_fixup; 7441 shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts); 7442 } 7443 7444 if (version->major < 3 || args->vp_mode != WINED3D_VP_MODE_SHADER) 7445 { 7446 shader_addline(buffer, "uniform struct\n{\n"); 7447 shader_addline(buffer, " vec4 color;\n"); 7448 shader_addline(buffer, " float density;\n"); 7449 shader_addline(buffer, " float end;\n"); 7450 shader_addline(buffer, " float scale;\n"); 7451 shader_addline(buffer, "} ffp_fog;\n"); 7452 7453 if (needs_legacy_glsl_syntax(gl_info)) 7454 { 7455 if (glsl_is_color_reg_read(shader, 0)) 7456 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n"); 7457 if (glsl_is_color_reg_read(shader, 1)) 7458 shader_addline(buffer, "vec4 ffp_varying_specular;\n"); 7459 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 7460 shader_addline(buffer, "float ffp_varying_fogcoord;\n"); 7461 } 7462 else 7463 { 7464 if (glsl_is_color_reg_read(shader, 0)) 7465 declare_in_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_diffuse;\n"); 7466 if (glsl_is_color_reg_read(shader, 1)) 7467 declare_in_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_specular;\n"); 7468 declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 7469 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 7470 declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 7471 } 7472 } 7473 7474 if (version->major >= 3) 7475 { 7476 unsigned int in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input); 7477 7478 if (args->vp_mode == WINED3D_VP_MODE_SHADER && reg_maps->input_registers) 7479 shader_glsl_declare_shader_inputs(gl_info, buffer, in_count, 7480 shader->u.ps.interpolation_mode, version->major >= 4); 7481 shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count); 7482 } 7483 7484 for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i) 7485 { 7486 if (!(map & 1)) 7487 continue; 7488 7489 shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", i); 7490 7491 if (reg_maps->luminanceparams & (1u << i)) 7492 { 7493 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", i); 7494 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", i); 7495 extra_constants_needed++; 7496 } 7497 7498 extra_constants_needed++; 7499 } 7500 7501 if (args->srgb_correction) 7502 { 7503 shader_addline(buffer, "const vec4 srgb_const0 = "); 7504 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0); 7505 shader_addline(buffer, ";\n"); 7506 shader_addline(buffer, "const vec4 srgb_const1 = "); 7507 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1); 7508 shader_addline(buffer, ";\n"); 7509 } 7510 if (reg_maps->vpos || reg_maps->usesdsy) 7511 { 7512 if (reg_maps->usesdsy || !gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7513 { 7514 ++extra_constants_needed; 7515 shader_addline(buffer, "uniform vec4 ycorrection;\n"); 7516 } 7517 if (reg_maps->vpos) 7518 { 7519 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7520 { 7521 if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER) 7522 shader_addline(buffer, "layout(%spixel_center_integer) in vec4 gl_FragCoord;\n", 7523 args->render_offscreen ? "" : "origin_upper_left, "); 7524 else if (!args->render_offscreen) 7525 shader_addline(buffer, "layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 7526 } 7527 shader_addline(buffer, "vec4 vpos;\n"); 7528 } 7529 } 7530 7531 if (args->alpha_test_func + 1 != WINED3D_CMP_ALWAYS) 7532 shader_addline(buffer, "uniform float alpha_test_ref;\n"); 7533 7534 if (!needs_legacy_glsl_syntax(gl_info)) 7535 { 7536 if (args->dual_source_blend) 7537 { 7538 for (i = 0; i < gl_info->limits.dual_buffers * 2; i++) 7539 { 7540 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7541 shader_addline(buffer, "layout(location = %u, index = %u) ", i / 2, i % 2); 7542 shader_addline(buffer, "out vec4 ps_out%u;\n", i); 7543 } 7544 } 7545 else 7546 { 7547 for (i = 0; i < gl_info->limits.buffers; i++) 7548 { 7549 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7550 shader_addline(buffer, "layout(location = %u) ", i); 7551 shader_addline(buffer, "out vec4 ps_out%u;\n", i); 7552 } 7553 } 7554 } 7555 7556 if (shader->limits->constant_float + extra_constants_needed >= gl_info->limits.glsl_ps_float_constants) 7557 FIXME("Insufficient uniforms to run this shader.\n"); 7558 7559 if (shader->u.ps.force_early_depth_stencil) 7560 shader_addline(buffer, "layout(early_fragment_tests) in;\n"); 7561 7562 shader_addline(buffer, "void main()\n{\n"); 7563 7564 if (reg_maps->sample_mask) 7565 shader_addline(buffer, "float sample_mask = uintBitsToFloat(0xffffffffu);\n"); 7566 7567 /* Direct3D applications expect integer vPos values, while OpenGL drivers 7568 * add approximately 0.5. This causes off-by-one problems as spotted by 7569 * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly 7570 * 0.5, but rather something like 0.49999999 or 0.50000001, which still 7571 * causes precision troubles when we just subtract 0.5. 7572 * 7573 * To deal with that, just floor() the position. This will eliminate the 7574 * fraction on all cards. 7575 * 7576 * TODO: Test how this behaves with multisampling. 7577 * 7578 * An advantage of floor is that it works even if the driver doesn't add 7579 * 0.5. It is somewhat questionable if 1.5, 2.5, ... are the proper values 7580 * to return in gl_FragCoord, even though coordinates specify the pixel 7581 * centers instead of the pixel corners. This code will behave correctly 7582 * on drivers that returns integer values. */ 7583 if (reg_maps->vpos) 7584 { 7585 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7586 shader_addline(buffer, "vpos = gl_FragCoord;\n"); 7587 else if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER) 7588 shader_addline(buffer, 7589 "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n"); 7590 else 7591 shader_addline(buffer, 7592 "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1);\n"); 7593 } 7594 7595 if (reg_maps->shader_version.major < 3 || args->vp_mode != WINED3D_VP_MODE_SHADER) 7596 { 7597 unsigned int i; 7598 WORD map = reg_maps->texcoord; 7599 7600 if (legacy_syntax) 7601 { 7602 if (glsl_is_color_reg_read(shader, 0)) 7603 shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n"); 7604 if (glsl_is_color_reg_read(shader, 1)) 7605 shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n"); 7606 } 7607 7608 for (i = 0; map; map >>= 1, ++i) 7609 { 7610 if (map & 1) 7611 { 7612 if (args->pointsprite) 7613 shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", i); 7614 else if (args->texcoords_initialized & (1u << i)) 7615 shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n", i, 7616 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", i); 7617 else 7618 shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", i); 7619 shader_addline(buffer, "vec4 T%u = ffp_texcoord[%u];\n", i, i); 7620 } 7621 } 7622 7623 if (legacy_syntax) 7624 shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n"); 7625 } 7626 7627 /* Pack 3.0 inputs */ 7628 if (reg_maps->shader_version.major >= 3) 7629 shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args, gl_info, 7630 reg_maps->shader_version.major >= 4); 7631 7632 /* Base Shader Body */ 7633 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 7634 return 0; 7635 7636 /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ 7637 if (reg_maps->shader_version.major < 4) 7638 shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, args); 7639 7640 shader_addline(buffer, "}\n"); 7641 7642 shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); 7643 TRACE("Compiling shader object %u.\n", shader_id); 7644 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7645 7646 return shader_id; 7647 } 7648 7649 static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_info, 7650 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 7651 const struct vs_compile_args *args) 7652 { 7653 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7654 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 7655 unsigned int i; 7656 7657 /* Unpack outputs. */ 7658 shader_addline(buffer, "setup_vs_output(vs_out);\n"); 7659 7660 /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used 7661 * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), 7662 * the fog frag coord is thrown away. If the fog frag coord is used, but not written by 7663 * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0). 7664 */ 7665 if (reg_maps->shader_version.major < 3) 7666 { 7667 if (args->fog_src == VS_FOG_Z) 7668 shader_addline(buffer, "%s = gl_Position.z;\n", 7669 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); 7670 else if (!reg_maps->fog) 7671 shader_addline(buffer, "%s = 0.0;\n", 7672 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); 7673 } 7674 7675 /* We always store the clipplanes without y inversion. */ 7676 if (args->clip_enabled) 7677 { 7678 if (legacy_syntax) 7679 shader_addline(buffer, "gl_ClipVertex = gl_Position;\n"); 7680 else 7681 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 7682 shader_addline(buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i); 7683 } 7684 7685 if (args->point_size && !args->per_vertex_point_size) 7686 shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n"); 7687 7688 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7689 shader_glsl_fixup_position(buffer, FALSE); 7690 } 7691 7692 /* Context activation is done by the caller. */ 7693 static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context, 7694 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct vs_compile_args *args) 7695 { 7696 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7697 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7698 const struct wined3d_shader_version *version = ®_maps->shader_version; 7699 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7700 const struct wined3d_gl_info *gl_info = context->gl_info; 7701 struct shader_glsl_ctx_priv priv_ctx; 7702 GLuint shader_id; 7703 unsigned int i; 7704 7705 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7706 priv_ctx.cur_vs_args = args; 7707 priv_ctx.string_buffers = string_buffers; 7708 7709 shader_glsl_add_version_declaration(buffer, gl_info); 7710 7711 shader_glsl_enable_extensions(buffer, gl_info); 7712 if (gl_info->supported[ARB_DRAW_INSTANCED]) 7713 shader_addline(buffer, "#extension GL_ARB_draw_instanced : enable\n"); 7714 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7715 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 7716 7717 /* Base Declarations */ 7718 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7719 7720 for (i = 0; i < shader->input_signature.element_count; ++i) 7721 shader_glsl_declare_generic_vertex_attribute(buffer, gl_info, &shader->input_signature.elements[i]); 7722 7723 if (args->point_size && !args->per_vertex_point_size) 7724 { 7725 shader_addline(buffer, "uniform struct\n{\n"); 7726 shader_addline(buffer, " float size;\n"); 7727 shader_addline(buffer, " float size_min;\n"); 7728 shader_addline(buffer, " float size_max;\n"); 7729 shader_addline(buffer, "} ffp_point;\n"); 7730 } 7731 7732 if (!needs_legacy_glsl_syntax(gl_info)) 7733 { 7734 if (args->clip_enabled) 7735 shader_addline(buffer, "uniform vec4 clip_planes[%u];\n", gl_info->limits.user_clip_distances); 7736 7737 if (version->major < 3) 7738 { 7739 declare_out_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_diffuse;\n"); 7740 declare_out_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_specular;\n"); 7741 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 7742 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 7743 } 7744 } 7745 7746 if (version->major < 4) 7747 shader_addline(buffer, "void setup_vs_output(in vec4[%u]);\n", shader->limits->packed_output); 7748 7749 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7750 shader_addline(buffer, "uniform vec4 pos_fixup;\n"); 7751 7752 if (reg_maps->shader_version.major >= 4) 7753 shader_glsl_generate_sm4_output_setup(priv, shader, args->next_shader_input_count, 7754 gl_info, args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode); 7755 7756 shader_addline(buffer, "void main()\n{\n"); 7757 7758 if (reg_maps->input_rel_addressing) 7759 { 7760 unsigned int highest_input_register = wined3d_log2i(reg_maps->input_registers); 7761 shader_addline(buffer, "vec4 vs_in[%u];\n", highest_input_register + 1); 7762 for (i = 0; i < shader->input_signature.element_count; ++i) 7763 { 7764 const struct wined3d_shader_signature_element *e = &shader->input_signature.elements[i]; 7765 shader_addline(buffer, "vs_in[%u] = vs_in%u;\n", e->register_idx, e->register_idx); 7766 } 7767 } 7768 7769 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 7770 return 0; 7771 7772 /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ 7773 if (reg_maps->shader_version.major < 4) 7774 shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, args); 7775 7776 shader_addline(buffer, "}\n"); 7777 7778 shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 7779 TRACE("Compiling shader object %u.\n", shader_id); 7780 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7781 7782 return shader_id; 7783 } 7784 7785 static void shader_glsl_generate_default_control_point_phase(const struct wined3d_shader *shader, 7786 struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps) 7787 { 7788 const struct wined3d_shader_signature *output_signature = &shader->output_signature; 7789 char reg_mask[6]; 7790 unsigned int i; 7791 7792 for (i = 0; i < output_signature->element_count; ++i) 7793 { 7794 const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; 7795 7796 shader_glsl_write_mask_to_str(output->mask, reg_mask); 7797 shader_addline(buffer, "shader_out[gl_InvocationID].reg[%u]%s = shader_in[gl_InvocationID].reg[%u]%s;\n", 7798 output->register_idx, reg_mask, output->register_idx, reg_mask); 7799 } 7800 } 7801 7802 static HRESULT shader_glsl_generate_shader_phase(const struct wined3d_shader *shader, 7803 struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps, 7804 struct shader_glsl_ctx_priv *priv_ctx, const struct wined3d_shader_phase *phase, 7805 const char *phase_name, unsigned phase_idx) 7806 { 7807 unsigned int i; 7808 HRESULT hr; 7809 7810 shader_addline(buffer, "void hs_%s_phase%u(%s)\n{\n", 7811 phase_name, phase_idx, phase->instance_count ? "int phase_instance_id" : ""); 7812 for (i = 0; i < phase->temporary_count; ++i) 7813 shader_addline(buffer, "vec4 R%u;\n", i); 7814 hr = shader_generate_code(shader, buffer, reg_maps, priv_ctx, phase->start, phase->end); 7815 shader_addline(buffer, "}\n"); 7816 return hr; 7817 } 7818 7819 static void shader_glsl_generate_shader_phase_invocation(struct wined3d_string_buffer *buffer, 7820 const struct wined3d_shader_phase *phase, const char *phase_name, unsigned int phase_idx) 7821 { 7822 if (phase->instance_count) 7823 { 7824 shader_addline(buffer, "for (int i = 0; i < %u; ++i)\n{\n", phase->instance_count); 7825 shader_addline(buffer, "hs_%s_phase%u(i);\n", phase_name, phase_idx); 7826 shader_addline(buffer, "}\n"); 7827 } 7828 else 7829 { 7830 shader_addline(buffer, "hs_%s_phase%u();\n", phase_name, phase_idx); 7831 } 7832 } 7833 7834 static GLuint shader_glsl_generate_hull_shader(const struct wined3d_context *context, 7835 struct shader_glsl_priv *priv, const struct wined3d_shader *shader) 7836 { 7837 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7838 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7839 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7840 const struct wined3d_gl_info *gl_info = context->gl_info; 7841 const struct wined3d_hull_shader *hs = &shader->u.hs; 7842 const struct wined3d_shader_phase *phase; 7843 struct shader_glsl_ctx_priv priv_ctx; 7844 GLuint shader_id; 7845 unsigned int i; 7846 7847 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7848 priv_ctx.string_buffers = string_buffers; 7849 7850 shader_glsl_add_version_declaration(buffer, gl_info); 7851 7852 shader_glsl_enable_extensions(buffer, gl_info); 7853 shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n"); 7854 7855 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7856 7857 shader_addline(buffer, "layout(vertices = %u) out;\n", hs->output_vertex_count); 7858 7859 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); 7860 shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out[];\n", shader->limits->packed_output); 7861 7862 shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, FALSE); 7863 7864 if (hs->phases.control_point) 7865 { 7866 shader_addline(buffer, "void setup_hs_output(in vec4 outputs[%u])\n{\n", 7867 shader->limits->packed_output); 7868 shader_glsl_setup_sm4_shader_output(priv, shader->limits->packed_output, &shader->output_signature, 7869 &shader->reg_maps, "shader_out[gl_InvocationID]", FALSE); 7870 shader_addline(buffer, "}\n"); 7871 } 7872 7873 shader_addline(buffer, "void hs_control_point_phase()\n{\n"); 7874 if ((phase = hs->phases.control_point)) 7875 { 7876 for (i = 0; i < phase->temporary_count; ++i) 7877 shader_addline(buffer, "vec4 R%u;\n", i); 7878 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, phase->start, phase->end))) 7879 return 0; 7880 shader_addline(buffer, "setup_hs_output(hs_out);\n"); 7881 } 7882 else 7883 { 7884 shader_glsl_generate_default_control_point_phase(shader, buffer, reg_maps); 7885 } 7886 shader_addline(buffer, "}\n"); 7887 7888 for (i = 0; i < hs->phases.fork_count; ++i) 7889 { 7890 if (FAILED(shader_glsl_generate_shader_phase(shader, buffer, reg_maps, &priv_ctx, 7891 &hs->phases.fork[i], "fork", i))) 7892 return 0; 7893 } 7894 7895 for (i = 0; i < hs->phases.join_count; ++i) 7896 { 7897 if (FAILED(shader_glsl_generate_shader_phase(shader, buffer, reg_maps, &priv_ctx, 7898 &hs->phases.join[i], "join", i))) 7899 return 0; 7900 } 7901 7902 shader_addline(buffer, "void main()\n{\n"); 7903 shader_addline(buffer, "hs_control_point_phase();\n"); 7904 if (reg_maps->vocp) 7905 shader_addline(buffer, "barrier();\n"); 7906 for (i = 0; i < hs->phases.fork_count; ++i) 7907 shader_glsl_generate_shader_phase_invocation(buffer, &hs->phases.fork[i], "fork", i); 7908 for (i = 0; i < hs->phases.join_count; ++i) 7909 shader_glsl_generate_shader_phase_invocation(buffer, &hs->phases.join[i], "join", i); 7910 shader_addline(buffer, "setup_patch_constant_output();\n"); 7911 shader_addline(buffer, "}\n"); 7912 7913 shader_id = GL_EXTCALL(glCreateShader(GL_TESS_CONTROL_SHADER)); 7914 TRACE("Compiling shader object %u.\n", shader_id); 7915 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7916 7917 return shader_id; 7918 } 7919 7920 static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_info, 7921 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 7922 const struct ds_compile_args *args) 7923 { 7924 shader_addline(buffer, "setup_ds_output(ds_out);\n"); 7925 7926 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7927 shader_glsl_fixup_position(buffer, FALSE); 7928 } 7929 7930 static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context, 7931 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct ds_compile_args *args) 7932 { 7933 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7934 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7935 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7936 const struct wined3d_gl_info *gl_info = context->gl_info; 7937 struct shader_glsl_ctx_priv priv_ctx; 7938 GLuint shader_id; 7939 7940 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7941 priv_ctx.cur_ds_args = args; 7942 priv_ctx.string_buffers = string_buffers; 7943 7944 shader_glsl_add_version_declaration(buffer, gl_info); 7945 7946 shader_glsl_enable_extensions(buffer, gl_info); 7947 shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n"); 7948 7949 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7950 7951 shader_addline(buffer, "layout("); 7952 switch (shader->u.ds.tessellator_domain) 7953 { 7954 case WINED3D_TESSELLATOR_DOMAIN_LINE: 7955 shader_addline(buffer, "isolines"); 7956 break; 7957 case WINED3D_TESSELLATOR_DOMAIN_QUAD: 7958 shader_addline(buffer, "quads"); 7959 break; 7960 case WINED3D_TESSELLATOR_DOMAIN_TRIANGLE: 7961 shader_addline(buffer, "triangles"); 7962 break; 7963 } 7964 switch (args->tessellator_output_primitive) 7965 { 7966 case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CW: 7967 if (args->render_offscreen) 7968 shader_addline(buffer, ", ccw"); 7969 else 7970 shader_addline(buffer, ", cw"); 7971 break; 7972 case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW: 7973 if (args->render_offscreen) 7974 shader_addline(buffer, ", cw"); 7975 else 7976 shader_addline(buffer, ", ccw"); 7977 break; 7978 case WINED3D_TESSELLATOR_OUTPUT_POINT: 7979 shader_addline(buffer, ", point_mode"); 7980 break; 7981 case WINED3D_TESSELLATOR_OUTPUT_LINE: 7982 break; 7983 } 7984 switch (args->tessellator_partitioning) 7985 { 7986 case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: 7987 shader_addline(buffer, ", fractional_odd_spacing"); 7988 break; 7989 case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: 7990 shader_addline(buffer, ", fractional_even_spacing"); 7991 break; 7992 case WINED3D_TESSELLATOR_PARTITIONING_INTEGER: 7993 case WINED3D_TESSELLATOR_PARTITIONING_POW2: 7994 shader_addline(buffer, ", equal_spacing"); 7995 break; 7996 } 7997 shader_addline(buffer, ") in;\n"); 7998 7999 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); 8000 8001 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 8002 shader_addline(buffer, "uniform vec4 pos_fixup;\n"); 8003 8004 shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info, 8005 args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode); 8006 shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, TRUE); 8007 8008 shader_addline(buffer, "void main()\n{\n"); 8009 shader_addline(buffer, "setup_patch_constant_input();\n"); 8010 8011 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 8012 return 0; 8013 8014 shader_addline(buffer, "}\n"); 8015 8016 shader_id = GL_EXTCALL(glCreateShader(GL_TESS_EVALUATION_SHADER)); 8017 TRACE("Compiling shader object %u.\n", shader_id); 8018 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 8019 8020 return shader_id; 8021 } 8022 8023 /* Context activation is done by the caller. */ 8024 static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context *context, 8025 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct gs_compile_args *args) 8026 { 8027 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 8028 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 8029 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 8030 const struct wined3d_gl_info *gl_info = context->gl_info; 8031 const struct wined3d_shader_signature_element *output; 8032 enum wined3d_primitive_type primitive_type; 8033 struct shader_glsl_ctx_priv priv_ctx; 8034 unsigned int max_vertices; 8035 unsigned int i, j; 8036 GLuint shader_id; 8037 8038 memset(&priv_ctx, 0, sizeof(priv_ctx)); 8039 priv_ctx.string_buffers = string_buffers; 8040 8041 shader_glsl_add_version_declaration(buffer, gl_info); 8042 8043 shader_glsl_enable_extensions(buffer, gl_info); 8044 8045 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 8046 8047 primitive_type = shader->u.gs.input_type ? shader->u.gs.input_type : args->primitive_type; 8048 shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(primitive_type)); 8049 if (shader->u.gs.instance_count > 1) 8050 shader_addline(buffer, ", invocations = %u", shader->u.gs.instance_count); 8051 shader_addline(buffer, ") in;\n"); 8052 8053 primitive_type = shader->u.gs.output_type ? shader->u.gs.output_type : args->primitive_type; 8054 if (!(max_vertices = shader->u.gs.vertices_out)) 8055 { 8056 switch (args->primitive_type) 8057 { 8058 case WINED3D_PT_POINTLIST: 8059 max_vertices = 1; 8060 break; 8061 case WINED3D_PT_LINELIST: 8062 max_vertices = 2; 8063 break; 8064 case WINED3D_PT_TRIANGLELIST: 8065 max_vertices = 3; 8066 break; 8067 default: 8068 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(args->primitive_type)); 8069 break; 8070 } 8071 } 8072 shader_addline(buffer, "layout(%s, max_vertices = %u) out;\n", 8073 glsl_primitive_type_from_d3d(primitive_type), max_vertices); 8074 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); 8075 8076 if (!gl_info->supported[ARB_CLIP_CONTROL]) 8077 { 8078 shader_addline(buffer, "uniform vec4 pos_fixup"); 8079 if (reg_maps->viewport_array) 8080 shader_addline(buffer, "[%u]", WINED3D_MAX_VIEWPORTS); 8081 shader_addline(buffer, ";\n"); 8082 } 8083 8084 if (is_rasterization_disabled(shader)) 8085 { 8086 shader_glsl_generate_stream_output_setup(priv, shader, &shader->u.gs.so_desc); 8087 } 8088 else 8089 { 8090 shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, 8091 gl_info, TRUE, args->interpolation_mode); 8092 } 8093 8094 shader_addline(buffer, "void main()\n{\n"); 8095 if (shader->function) 8096 { 8097 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 8098 return 0; 8099 } 8100 else 8101 { 8102 for (i = 0; i < max_vertices; ++i) 8103 { 8104 for (j = 0; j < shader->output_signature.element_count; ++j) 8105 { 8106 output = &shader->output_signature.elements[j]; 8107 shader_addline(buffer, "gs_out[%u] = shader_in[%u].reg[%u];\n", 8108 output->register_idx, i, output->register_idx); 8109 } 8110 shader_addline(buffer, "setup_gs_output(gs_out);\n"); 8111 if (!gl_info->supported[ARB_CLIP_CONTROL]) 8112 shader_glsl_fixup_position(buffer, FALSE); 8113 shader_addline(buffer, "EmitVertex();\n"); 8114 } 8115 } 8116 shader_addline(buffer, "}\n"); 8117 8118 shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); 8119 TRACE("Compiling shader object %u.\n", shader_id); 8120 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 8121 8122 return shader_id; 8123 } 8124 8125 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx) 8126 { 8127 const struct shader_glsl_ctx_priv *priv = ctx->backend_data; 8128 const struct wined3d_gl_info *gl_info = ctx->gl_info; 8129 struct wined3d_string_buffer *buffer = ctx->buffer; 8130 const struct wined3d_shader *shader = ctx->shader; 8131 8132 switch (shader->reg_maps.shader_version.type) 8133 { 8134 case WINED3D_SHADER_TYPE_PIXEL: 8135 shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, priv->cur_ps_args); 8136 break; 8137 case WINED3D_SHADER_TYPE_VERTEX: 8138 shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, priv->cur_vs_args); 8139 break; 8140 case WINED3D_SHADER_TYPE_DOMAIN: 8141 shader_glsl_generate_ds_epilogue(gl_info, buffer, shader, priv->cur_ds_args); 8142 break; 8143 case WINED3D_SHADER_TYPE_GEOMETRY: 8144 case WINED3D_SHADER_TYPE_COMPUTE: 8145 break; 8146 default: 8147 FIXME("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type); 8148 break; 8149 } 8150 } 8151 8152 /* Context activation is done by the caller. */ 8153 static GLuint shader_glsl_generate_compute_shader(const struct wined3d_context *context, 8154 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, 8155 const struct wined3d_shader *shader) 8156 { 8157 const struct wined3d_shader_thread_group_size *thread_group_size = &shader->u.cs.thread_group_size; 8158 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 8159 const struct wined3d_gl_info *gl_info = context->gl_info; 8160 struct shader_glsl_ctx_priv priv_ctx; 8161 GLuint shader_id; 8162 unsigned int i; 8163 8164 memset(&priv_ctx, 0, sizeof(priv_ctx)); 8165 priv_ctx.string_buffers = string_buffers; 8166 8167 shader_glsl_add_version_declaration(buffer, gl_info); 8168 8169 shader_glsl_enable_extensions(buffer, gl_info); 8170 shader_addline(buffer, "#extension GL_ARB_compute_shader : enable\n"); 8171 8172 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 8173 8174 for (i = 0; i < reg_maps->tgsm_count; ++i) 8175 { 8176 if (reg_maps->tgsm[i].size) 8177 shader_addline(buffer, "shared uint cs_g%u[%u];\n", i, reg_maps->tgsm[i].size); 8178 } 8179 8180 shader_addline(buffer, "layout(local_size_x = %u, local_size_y = %u, local_size_z = %u) in;\n", 8181 thread_group_size->x, thread_group_size->y, thread_group_size->z); 8182 8183 shader_addline(buffer, "void main()\n{\n"); 8184 shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL); 8185 shader_addline(buffer, "}\n"); 8186 8187 shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER)); 8188 TRACE("Compiling shader object %u.\n", shader_id); 8189 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 8190 8191 return shader_id; 8192 } 8193 8194 static GLuint find_glsl_pshader(const struct wined3d_context *context, 8195 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, 8196 struct wined3d_shader *shader, 8197 const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info) 8198 { 8199 struct glsl_ps_compiled_shader *gl_shaders, *new_array; 8200 struct glsl_shader_private *shader_data; 8201 struct ps_np2fixup_info *np2fixup; 8202 UINT i; 8203 DWORD new_size; 8204 GLuint ret; 8205 8206 if (!shader->backend_data) 8207 { 8208 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8209 { 8210 ERR("Failed to allocate backend data.\n"); 8211 return 0; 8212 } 8213 } 8214 shader_data = shader->backend_data; 8215 gl_shaders = shader_data->gl_shaders.ps; 8216 8217 /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), 8218 * so a linear search is more performant than a hashmap or a binary search 8219 * (cache coherency etc) 8220 */ 8221 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8222 { 8223 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) 8224 { 8225 if (args->np2_fixup) 8226 *np2fixup_info = &gl_shaders[i].np2fixup; 8227 return gl_shaders[i].id; 8228 } 8229 } 8230 8231 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8232 if (shader_data->shader_array_size == shader_data->num_gl_shaders) 8233 { 8234 if (shader_data->num_gl_shaders) 8235 { 8236 new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); 8237 new_array = heap_realloc(shader_data->gl_shaders.ps, new_size * sizeof(*gl_shaders)); 8238 } 8239 else 8240 { 8241 new_array = heap_alloc(sizeof(*gl_shaders)); 8242 new_size = 1; 8243 } 8244 8245 if(!new_array) { 8246 ERR("Out of memory\n"); 8247 return 0; 8248 } 8249 shader_data->gl_shaders.ps = new_array; 8250 shader_data->shader_array_size = new_size; 8251 gl_shaders = new_array; 8252 } 8253 8254 gl_shaders[shader_data->num_gl_shaders].args = *args; 8255 8256 np2fixup = &gl_shaders[shader_data->num_gl_shaders].np2fixup; 8257 memset(np2fixup, 0, sizeof(*np2fixup)); 8258 *np2fixup_info = args->np2_fixup ? np2fixup : NULL; 8259 8260 pixelshader_update_resource_types(shader, args->tex_types); 8261 8262 string_buffer_clear(buffer); 8263 ret = shader_glsl_generate_pshader(context, buffer, string_buffers, shader, args, np2fixup); 8264 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8265 8266 return ret; 8267 } 8268 8269 static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, 8270 const DWORD use_map) 8271 { 8272 if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; 8273 if((stored->clip_enabled) != new->clip_enabled) return FALSE; 8274 if (stored->point_size != new->point_size) 8275 return FALSE; 8276 if (stored->per_vertex_point_size != new->per_vertex_point_size) 8277 return FALSE; 8278 if (stored->flatshading != new->flatshading) 8279 return FALSE; 8280 if (stored->next_shader_type != new->next_shader_type) 8281 return FALSE; 8282 if (stored->next_shader_input_count != new->next_shader_input_count) 8283 return FALSE; 8284 return stored->fog_src == new->fog_src; 8285 } 8286 8287 static GLuint find_glsl_vshader(const struct wined3d_context *context, struct shader_glsl_priv *priv, 8288 struct wined3d_shader *shader, const struct vs_compile_args *args) 8289 { 8290 UINT i; 8291 DWORD new_size; 8292 DWORD use_map = context->stream_info.use_map; 8293 struct glsl_vs_compiled_shader *gl_shaders, *new_array; 8294 struct glsl_shader_private *shader_data; 8295 GLuint ret; 8296 8297 if (!shader->backend_data) 8298 { 8299 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8300 { 8301 ERR("Failed to allocate backend data.\n"); 8302 return 0; 8303 } 8304 } 8305 shader_data = shader->backend_data; 8306 gl_shaders = shader_data->gl_shaders.vs; 8307 8308 /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), 8309 * so a linear search is more performant than a hashmap or a binary search 8310 * (cache coherency etc) 8311 */ 8312 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8313 { 8314 if (vs_args_equal(&gl_shaders[i].args, args, use_map)) 8315 return gl_shaders[i].id; 8316 } 8317 8318 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8319 8320 if (shader_data->shader_array_size == shader_data->num_gl_shaders) 8321 { 8322 if (shader_data->num_gl_shaders) 8323 { 8324 new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); 8325 new_array = heap_realloc(shader_data->gl_shaders.vs, new_size * sizeof(*gl_shaders)); 8326 } 8327 else 8328 { 8329 new_array = heap_alloc(sizeof(*gl_shaders)); 8330 new_size = 1; 8331 } 8332 8333 if(!new_array) { 8334 ERR("Out of memory\n"); 8335 return 0; 8336 } 8337 shader_data->gl_shaders.vs = new_array; 8338 shader_data->shader_array_size = new_size; 8339 gl_shaders = new_array; 8340 } 8341 8342 gl_shaders[shader_data->num_gl_shaders].args = *args; 8343 8344 string_buffer_clear(&priv->shader_buffer); 8345 ret = shader_glsl_generate_vshader(context, priv, shader, args); 8346 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8347 8348 return ret; 8349 } 8350 8351 static GLuint find_glsl_hull_shader(const struct wined3d_context *context, 8352 struct shader_glsl_priv *priv, struct wined3d_shader *shader) 8353 { 8354 struct glsl_hs_compiled_shader *gl_shaders, *new_array; 8355 struct glsl_shader_private *shader_data; 8356 unsigned int new_size; 8357 GLuint ret; 8358 8359 if (!shader->backend_data) 8360 { 8361 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8362 { 8363 ERR("Failed to allocate backend data.\n"); 8364 return 0; 8365 } 8366 } 8367 shader_data = shader->backend_data; 8368 gl_shaders = shader_data->gl_shaders.hs; 8369 8370 if (shader_data->num_gl_shaders > 0) 8371 { 8372 assert(shader_data->num_gl_shaders == 1); 8373 return gl_shaders[0].id; 8374 } 8375 8376 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8377 8378 assert(!shader_data->gl_shaders.hs); 8379 new_size = 1; 8380 if (!(new_array = heap_alloc(sizeof(*new_array)))) 8381 { 8382 ERR("Failed to allocate GL shaders array.\n"); 8383 return 0; 8384 } 8385 shader_data->gl_shaders.hs = new_array; 8386 shader_data->shader_array_size = new_size; 8387 gl_shaders = new_array; 8388 8389 string_buffer_clear(&priv->shader_buffer); 8390 ret = shader_glsl_generate_hull_shader(context, priv, shader); 8391 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8392 8393 return ret; 8394 } 8395 8396 static GLuint find_glsl_domain_shader(const struct wined3d_context *context, 8397 struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct ds_compile_args *args) 8398 { 8399 struct glsl_ds_compiled_shader *gl_shaders, *new_array; 8400 struct glsl_shader_private *shader_data; 8401 unsigned int i, new_size; 8402 GLuint ret; 8403 8404 if (!shader->backend_data) 8405 { 8406 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8407 { 8408 ERR("Failed to allocate backend data.\n"); 8409 return 0; 8410 } 8411 } 8412 shader_data = shader->backend_data; 8413 gl_shaders = shader_data->gl_shaders.ds; 8414 8415 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8416 { 8417 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) 8418 return gl_shaders[i].id; 8419 } 8420 8421 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8422 8423 if (shader_data->num_gl_shaders) 8424 { 8425 new_size = shader_data->shader_array_size + 1; 8426 new_array = heap_realloc(shader_data->gl_shaders.ds, new_size * sizeof(*new_array)); 8427 } 8428 else 8429 { 8430 new_array = heap_alloc(sizeof(*new_array)); 8431 new_size = 1; 8432 } 8433 8434 if (!new_array) 8435 { 8436 ERR("Failed to allocate GL shaders array.\n"); 8437 return 0; 8438 } 8439 shader_data->gl_shaders.ds = new_array; 8440 shader_data->shader_array_size = new_size; 8441 gl_shaders = new_array; 8442 8443 string_buffer_clear(&priv->shader_buffer); 8444 ret = shader_glsl_generate_domain_shader(context, priv, shader, args); 8445 gl_shaders[shader_data->num_gl_shaders].args = *args; 8446 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8447 8448 return ret; 8449 } 8450 8451 static GLuint find_glsl_geometry_shader(const struct wined3d_context *context, 8452 struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct gs_compile_args *args) 8453 { 8454 struct glsl_gs_compiled_shader *gl_shaders, *new_array; 8455 struct glsl_shader_private *shader_data; 8456 unsigned int i, new_size; 8457 GLuint ret; 8458 8459 if (!shader->backend_data) 8460 { 8461 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8462 { 8463 ERR("Failed to allocate backend data.\n"); 8464 return 0; 8465 } 8466 } 8467 shader_data = shader->backend_data; 8468 gl_shaders = shader_data->gl_shaders.gs; 8469 8470 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8471 { 8472 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) 8473 return gl_shaders[i].id; 8474 } 8475 8476 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8477 8478 if (shader_data->num_gl_shaders) 8479 { 8480 new_size = shader_data->shader_array_size + 1; 8481 new_array = heap_realloc(shader_data->gl_shaders.gs, new_size * sizeof(*new_array)); 8482 } 8483 else 8484 { 8485 new_array = heap_alloc(sizeof(*new_array)); 8486 new_size = 1; 8487 } 8488 8489 if (!new_array) 8490 { 8491 ERR("Failed to allocate GL shaders array.\n"); 8492 return 0; 8493 } 8494 shader_data->gl_shaders.gs = new_array; 8495 shader_data->shader_array_size = new_size; 8496 gl_shaders = new_array; 8497 8498 string_buffer_clear(&priv->shader_buffer); 8499 ret = shader_glsl_generate_geometry_shader(context, priv, shader, args); 8500 gl_shaders[shader_data->num_gl_shaders].args = *args; 8501 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8502 8503 return ret; 8504 } 8505 8506 static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, const char *material) 8507 { 8508 switch (mcs) 8509 { 8510 case WINED3D_MCS_MATERIAL: 8511 return material; 8512 case WINED3D_MCS_COLOR1: 8513 return "ffp_attrib_diffuse"; 8514 case WINED3D_MCS_COLOR2: 8515 return "ffp_attrib_specular"; 8516 default: 8517 ERR("Invalid material color source %#x.\n", mcs); 8518 return "<invalid>"; 8519 } 8520 } 8521 8522 static void shader_glsl_ffp_vertex_lighting_footer(struct wined3d_string_buffer *buffer, 8523 const struct wined3d_ffp_vs_settings *settings, unsigned int idx) 8524 { 8525 shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)" 8526 " * ffp_light[%u].diffuse.xyz * att;\n", idx); 8527 if (settings->localviewer) 8528 shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n"); 8529 else 8530 shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n"); 8531 shader_addline(buffer, "if (dot(dir, normal) > 0.0 && t > 0.0) specular +=" 8532 " pow(t, ffp_material.shininess) * ffp_light[%u].specular * att;\n", idx); 8533 } 8534 8535 static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer, 8536 const struct wined3d_ffp_vs_settings *settings, BOOL legacy_lighting) 8537 { 8538 const char *diffuse, *specular, *emissive, *ambient; 8539 unsigned int i, idx; 8540 8541 if (!settings->lighting) 8542 { 8543 shader_addline(buffer, "ffp_varying_diffuse = ffp_attrib_diffuse;\n"); 8544 shader_addline(buffer, "ffp_varying_specular = ffp_attrib_specular;\n"); 8545 return; 8546 } 8547 8548 shader_addline(buffer, "vec3 ambient = ffp_light_ambient;\n"); 8549 shader_addline(buffer, "vec3 diffuse = vec3(0.0);\n"); 8550 shader_addline(buffer, "vec4 specular = vec4(0.0);\n"); 8551 shader_addline(buffer, "vec3 dir, dst;\n"); 8552 shader_addline(buffer, "float att, t;\n"); 8553 8554 ambient = shader_glsl_ffp_mcs(settings->ambient_source, "ffp_material.ambient"); 8555 diffuse = shader_glsl_ffp_mcs(settings->diffuse_source, "ffp_material.diffuse"); 8556 specular = shader_glsl_ffp_mcs(settings->specular_source, "ffp_material.specular"); 8557 emissive = shader_glsl_ffp_mcs(settings->emissive_source, "ffp_material.emissive"); 8558 8559 idx = 0; 8560 for (i = 0; i < settings->point_light_count; ++i, ++idx) 8561 { 8562 shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx); 8563 shader_addline(buffer, "dst.z = dot(dir, dir);\n"); 8564 shader_addline(buffer, "dst.y = sqrt(dst.z);\n"); 8565 shader_addline(buffer, "dst.x = 1.0;\n"); 8566 if (legacy_lighting) 8567 { 8568 shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx); 8569 shader_addline(buffer, "dst.z = dst.y * dst.y;\n"); 8570 shader_addline(buffer, "if (dst.y > 0.0)\n{\n"); 8571 } 8572 else 8573 { 8574 shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx); 8575 } 8576 shader_addline(buffer, "att = dot(dst.xyz, vec3(ffp_light[%u].c_att," 8577 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", idx, idx, idx); 8578 if (!legacy_lighting) 8579 shader_addline(buffer, "att = 1.0 / att;\n"); 8580 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx); 8581 if (!settings->normal) 8582 { 8583 shader_addline(buffer, "}\n"); 8584 continue; 8585 } 8586 shader_addline(buffer, "dir = normalize(dir);\n"); 8587 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8588 shader_addline(buffer, "}\n"); 8589 } 8590 8591 for (i = 0; i < settings->spot_light_count; ++i, ++idx) 8592 { 8593 shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx); 8594 shader_addline(buffer, "dst.z = dot(dir, dir);\n"); 8595 shader_addline(buffer, "dst.y = sqrt(dst.z);\n"); 8596 shader_addline(buffer, "dst.x = 1.0;\n"); 8597 if (legacy_lighting) 8598 { 8599 shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx); 8600 shader_addline(buffer, "dst.z = dst.y * dst.y;\n"); 8601 shader_addline(buffer, "if (dst.y > 0.0)\n{\n"); 8602 } 8603 else 8604 { 8605 shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx); 8606 } 8607 shader_addline(buffer, "dir = normalize(dir);\n"); 8608 shader_addline(buffer, "t = dot(-dir, normalize(ffp_light[%u].direction));\n", idx); 8609 shader_addline(buffer, "if (t > ffp_light[%u].cos_htheta) att = 1.0;\n", idx); 8610 shader_addline(buffer, "else if (t <= ffp_light[%u].cos_hphi) att = 0.0;\n", idx); 8611 shader_addline(buffer, "else att = pow((t - ffp_light[%u].cos_hphi)" 8612 " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff);\n", 8613 idx, idx, idx, idx); 8614 if (legacy_lighting) 8615 shader_addline(buffer, "att *= dot(dst.xyz, vec3(ffp_light[%u].c_att," 8616 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", 8617 idx, idx, idx); 8618 else 8619 shader_addline(buffer, "att /= dot(dst.xyz, vec3(ffp_light[%u].c_att," 8620 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", 8621 idx, idx, idx); 8622 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx); 8623 if (!settings->normal) 8624 { 8625 shader_addline(buffer, "}\n"); 8626 continue; 8627 } 8628 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8629 shader_addline(buffer, "}\n"); 8630 } 8631 8632 for (i = 0; i < settings->directional_light_count; ++i, ++idx) 8633 { 8634 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx); 8635 if (!settings->normal) 8636 continue; 8637 shader_addline(buffer, "att = 1.0;\n"); 8638 shader_addline(buffer, "dir = normalize(ffp_light[%u].direction.xyz);\n", idx); 8639 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8640 } 8641 8642 for (i = 0; i < settings->parallel_point_light_count; ++i, ++idx) 8643 { 8644 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx); 8645 if (!settings->normal) 8646 continue; 8647 shader_addline(buffer, "att = 1.0;\n"); 8648 shader_addline(buffer, "dir = normalize(ffp_light[%u].position.xyz);\n", idx); 8649 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8650 } 8651 8652 shader_addline(buffer, "ffp_varying_diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n", 8653 ambient, diffuse, emissive); 8654 shader_addline(buffer, "ffp_varying_diffuse.w = %s.w;\n", diffuse); 8655 shader_addline(buffer, "ffp_varying_specular = %s * specular;\n", specular); 8656 } 8657 8658 /* Context activation is done by the caller. */ 8659 static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *priv, 8660 const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info) 8661 { 8662 static const struct attrib_info 8663 { 8664 const char type[6]; 8665 const char name[24]; 8666 } 8667 attrib_info[] = 8668 { 8669 {"vec4", "ffp_attrib_position"}, /* WINED3D_FFP_POSITION */ 8670 {"vec4", "ffp_attrib_blendweight"}, /* WINED3D_FFP_BLENDWEIGHT */ 8671 {"vec4", "ffp_attrib_blendindices"}, /* WINED3D_FFP_BLENDINDICES */ 8672 {"vec3", "ffp_attrib_normal"}, /* WINED3D_FFP_NORMAL */ 8673 {"float", "ffp_attrib_psize"}, /* WINED3D_FFP_PSIZE */ 8674 {"vec4", "ffp_attrib_diffuse"}, /* WINED3D_FFP_DIFFUSE */ 8675 {"vec4", "ffp_attrib_specular"}, /* WINED3D_FFP_SPECULAR */ 8676 }; 8677 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 8678 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 8679 BOOL output_legacy_fogcoord = legacy_syntax; 8680 BOOL legacy_lighting = priv->legacy_lighting; 8681 GLuint shader_obj; 8682 unsigned int i; 8683 char var[64]; 8684 8685 string_buffer_clear(buffer); 8686 8687 shader_glsl_add_version_declaration(buffer, gl_info); 8688 8689 if (shader_glsl_use_explicit_attrib_location(gl_info)) 8690 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 8691 8692 for (i = 0; i < WINED3D_FFP_ATTRIBS_COUNT; ++i) 8693 { 8694 const char *type = i < ARRAY_SIZE(attrib_info) ? attrib_info[i].type : "vec4"; 8695 8696 if (shader_glsl_use_explicit_attrib_location(gl_info)) 8697 shader_addline(buffer, "layout(location = %u) ", i); 8698 shader_addline(buffer, "%s %s vs_in%u;\n", get_attribute_keyword(gl_info), type, i); 8699 } 8700 shader_addline(buffer, "\n"); 8701 8702 shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); 8703 shader_addline(buffer, "uniform mat3 ffp_normal_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); 8704 shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n"); 8705 shader_addline(buffer, "uniform mat4 ffp_texture_matrix[%u];\n", MAX_TEXTURES); 8706 8707 shader_addline(buffer, "uniform struct\n{\n"); 8708 shader_addline(buffer, " vec4 emissive;\n"); 8709 shader_addline(buffer, " vec4 ambient;\n"); 8710 shader_addline(buffer, " vec4 diffuse;\n"); 8711 shader_addline(buffer, " vec4 specular;\n"); 8712 shader_addline(buffer, " float shininess;\n"); 8713 shader_addline(buffer, "} ffp_material;\n"); 8714 8715 shader_addline(buffer, "uniform vec3 ffp_light_ambient;\n"); 8716 shader_addline(buffer, "uniform struct\n{\n"); 8717 shader_addline(buffer, " vec4 diffuse;\n"); 8718 shader_addline(buffer, " vec4 specular;\n"); 8719 shader_addline(buffer, " vec4 ambient;\n"); 8720 shader_addline(buffer, " vec4 position;\n"); 8721 shader_addline(buffer, " vec3 direction;\n"); 8722 shader_addline(buffer, " float range;\n"); 8723 shader_addline(buffer, " float falloff;\n"); 8724 shader_addline(buffer, " float c_att;\n"); 8725 shader_addline(buffer, " float l_att;\n"); 8726 shader_addline(buffer, " float q_att;\n"); 8727 shader_addline(buffer, " float cos_htheta;\n"); 8728 shader_addline(buffer, " float cos_hphi;\n"); 8729 shader_addline(buffer, "} ffp_light[%u];\n", MAX_ACTIVE_LIGHTS); 8730 8731 if (settings->point_size) 8732 { 8733 shader_addline(buffer, "uniform struct\n{\n"); 8734 shader_addline(buffer, " float size;\n"); 8735 shader_addline(buffer, " float size_min;\n"); 8736 shader_addline(buffer, " float size_max;\n"); 8737 shader_addline(buffer, " float c_att;\n"); 8738 shader_addline(buffer, " float l_att;\n"); 8739 shader_addline(buffer, " float q_att;\n"); 8740 shader_addline(buffer, "} ffp_point;\n"); 8741 } 8742 8743 if (legacy_syntax) 8744 { 8745 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n"); 8746 shader_addline(buffer, "vec4 ffp_varying_specular;\n"); 8747 shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 8748 shader_addline(buffer, "float ffp_varying_fogcoord;\n"); 8749 } 8750 else 8751 { 8752 if (settings->clipping) 8753 shader_addline(buffer, "uniform vec4 clip_planes[%u];\n", gl_info->limits.user_clip_distances); 8754 8755 declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n"); 8756 declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_specular;\n"); 8757 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 8758 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 8759 } 8760 8761 shader_addline(buffer, "\nvoid main()\n{\n"); 8762 shader_addline(buffer, "float m;\n"); 8763 shader_addline(buffer, "vec3 r;\n"); 8764 8765 for (i = 0; i < ARRAY_SIZE(attrib_info); ++i) 8766 { 8767 if (attrib_info[i].name[0]) 8768 shader_addline(buffer, "%s %s = vs_in%u%s;\n", attrib_info[i].type, attrib_info[i].name, 8769 i, settings->swizzle_map & (1u << i) ? ".zyxw" : ""); 8770 } 8771 for (i = 0; i < MAX_TEXTURES; ++i) 8772 { 8773 unsigned int coord_idx = settings->texgen[i] & 0x0000ffff; 8774 if ((settings->texgen[i] & 0xffff0000) == WINED3DTSS_TCI_PASSTHRU 8775 && settings->texcoords & (1u << i)) 8776 shader_addline(buffer, "vec4 ffp_attrib_texcoord%u = vs_in%u;\n", i, coord_idx + WINED3D_FFP_TEXCOORD0); 8777 } 8778 8779 shader_addline(buffer, "ffp_attrib_blendweight[%u] = 1.0;\n", settings->vertexblends); 8780 8781 if (settings->transformed) 8782 { 8783 shader_addline(buffer, "vec4 ec_pos = vec4(ffp_attrib_position.xyz, 1.0);\n"); 8784 shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); 8785 shader_addline(buffer, "if (ffp_attrib_position.w != 0.0) gl_Position /= ffp_attrib_position.w;\n"); 8786 } 8787 else 8788 { 8789 if (!settings->sw_blending) 8790 { 8791 for (i = 0; i < settings->vertexblends; ++i) 8792 shader_addline(buffer, "ffp_attrib_blendweight[%u] -= ffp_attrib_blendweight[%u];\n", settings->vertexblends, i); 8793 8794 shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n"); 8795 for (i = 0; i < settings->vertexblends + 1; ++i) 8796 { 8797 sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); 8798 shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%s] * ffp_attrib_position);\n", i, var); 8799 } 8800 } 8801 else 8802 { 8803 shader_addline(buffer, "vec4 ec_pos = ffp_attrib_position;\n"); 8804 } 8805 8806 shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); 8807 if (settings->clipping) 8808 { 8809 if (legacy_syntax) 8810 shader_addline(buffer, "gl_ClipVertex = ec_pos;\n"); 8811 else 8812 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 8813 shader_addline(buffer, "gl_ClipDistance[%u] = dot(ec_pos, clip_planes[%u]);\n", i, i); 8814 } 8815 shader_addline(buffer, "ec_pos /= ec_pos.w;\n"); 8816 } 8817 8818 shader_addline(buffer, "vec3 normal = vec3(0.0);\n"); 8819 if (settings->normal) 8820 { 8821 if (!settings->sw_blending) 8822 { 8823 for (i = 0; i < settings->vertexblends + 1; ++i) 8824 { 8825 sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); 8826 shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (ffp_normal_matrix[%s] * ffp_attrib_normal);\n", i, var); 8827 } 8828 } 8829 else 8830 { 8831 shader_addline(buffer, "normal = ffp_attrib_normal;\n"); 8832 } 8833 8834 if (settings->normalize) 8835 shader_addline(buffer, "normal = normalize(normal);\n"); 8836 } 8837 8838 shader_glsl_ffp_vertex_lighting(buffer, settings, legacy_lighting); 8839 if (legacy_syntax) 8840 { 8841 shader_addline(buffer, "gl_FrontColor = ffp_varying_diffuse;\n"); 8842 shader_addline(buffer, "gl_FrontSecondaryColor = ffp_varying_specular;\n"); 8843 } 8844 else 8845 { 8846 shader_addline(buffer, "ffp_varying_diffuse = clamp(ffp_varying_diffuse, 0.0, 1.0);\n"); 8847 shader_addline(buffer, "ffp_varying_specular = clamp(ffp_varying_specular, 0.0, 1.0);\n"); 8848 } 8849 8850 for (i = 0; i < MAX_TEXTURES; ++i) 8851 { 8852 BOOL output_legacy_texcoord = legacy_syntax; 8853 8854 switch (settings->texgen[i] & 0xffff0000) 8855 { 8856 case WINED3DTSS_TCI_PASSTHRU: 8857 if (settings->texcoords & (1u << i)) 8858 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ffp_attrib_texcoord%u;\n", 8859 i, i, i); 8860 else if (gl_info->limits.glsl_varyings >= wined3d_max_compat_varyings(gl_info)) 8861 shader_addline(buffer, "ffp_varying_texcoord[%u] = vec4(0.0);\n", i); 8862 else 8863 output_legacy_texcoord = FALSE; 8864 break; 8865 8866 case WINED3DTSS_TCI_CAMERASPACENORMAL: 8867 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * vec4(normal, 1.0);\n", i, i); 8868 break; 8869 8870 case WINED3DTSS_TCI_CAMERASPACEPOSITION: 8871 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ec_pos;\n", i, i); 8872 break; 8873 8874 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: 8875 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]" 8876 " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i); 8877 break; 8878 8879 case WINED3DTSS_TCI_SPHEREMAP: 8880 shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n"); 8881 shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n"); 8882 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]" 8883 " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);\n", i, i); 8884 break; 8885 8886 default: 8887 ERR("Unhandled texgen %#x.\n", settings->texgen[i]); 8888 break; 8889 } 8890 if (output_legacy_texcoord) 8891 shader_addline(buffer, "gl_TexCoord[%u] = ffp_varying_texcoord[%u];\n", i, i); 8892 } 8893 8894 switch (settings->fog_mode) 8895 { 8896 case WINED3D_FFP_VS_FOG_OFF: 8897 output_legacy_fogcoord = FALSE; 8898 break; 8899 8900 case WINED3D_FFP_VS_FOG_FOGCOORD: 8901 shader_addline(buffer, "ffp_varying_fogcoord = ffp_attrib_specular.w * 255.0;\n"); 8902 break; 8903 8904 case WINED3D_FFP_VS_FOG_RANGE: 8905 shader_addline(buffer, "ffp_varying_fogcoord = length(ec_pos.xyz);\n"); 8906 break; 8907 8908 case WINED3D_FFP_VS_FOG_DEPTH: 8909 if (settings->ortho_fog) 8910 { 8911 if (gl_info->supported[ARB_CLIP_CONTROL]) 8912 shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z;\n"); 8913 else 8914 /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */ 8915 shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z * 0.5 + 0.5;\n"); 8916 } 8917 else if (settings->transformed) 8918 { 8919 shader_addline(buffer, "ffp_varying_fogcoord = ec_pos.z;\n"); 8920 } 8921 else 8922 { 8923 shader_addline(buffer, "ffp_varying_fogcoord = abs(ec_pos.z);\n"); 8924 } 8925 break; 8926 8927 default: 8928 ERR("Unhandled fog mode %#x.\n", settings->fog_mode); 8929 break; 8930 } 8931 if (output_legacy_fogcoord) 8932 shader_addline(buffer, "gl_FogFragCoord = ffp_varying_fogcoord;\n"); 8933 8934 if (settings->point_size) 8935 { 8936 shader_addline(buffer, "gl_PointSize = %s / sqrt(ffp_point.c_att" 8937 " + ffp_point.l_att * length(ec_pos.xyz)" 8938 " + ffp_point.q_att * dot(ec_pos.xyz, ec_pos.xyz));\n", 8939 settings->per_vertex_point_size ? "ffp_attrib_psize" : "ffp_point.size"); 8940 shader_addline(buffer, "gl_PointSize = clamp(gl_PointSize, ffp_point.size_min, ffp_point.size_max);\n"); 8941 } 8942 8943 shader_addline(buffer, "}\n"); 8944 8945 shader_obj = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 8946 shader_glsl_compile(gl_info, shader_obj, buffer->buffer); 8947 8948 return shader_obj; 8949 } 8950 8951 static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buffer *buffer, 8952 DWORD argnum, unsigned int stage, DWORD arg) 8953 { 8954 const char *ret; 8955 8956 if (arg == ARG_UNUSED) 8957 return "<unused arg>"; 8958 8959 switch (arg & WINED3DTA_SELECTMASK) 8960 { 8961 case WINED3DTA_DIFFUSE: 8962 ret = "ffp_varying_diffuse"; 8963 break; 8964 8965 case WINED3DTA_CURRENT: 8966 ret = "ret"; 8967 break; 8968 8969 case WINED3DTA_TEXTURE: 8970 switch (stage) 8971 { 8972 case 0: ret = "tex0"; break; 8973 case 1: ret = "tex1"; break; 8974 case 2: ret = "tex2"; break; 8975 case 3: ret = "tex3"; break; 8976 case 4: ret = "tex4"; break; 8977 case 5: ret = "tex5"; break; 8978 case 6: ret = "tex6"; break; 8979 case 7: ret = "tex7"; break; 8980 default: 8981 ret = "<invalid texture>"; 8982 break; 8983 } 8984 break; 8985 8986 case WINED3DTA_TFACTOR: 8987 ret = "tex_factor"; 8988 break; 8989 8990 case WINED3DTA_SPECULAR: 8991 ret = "ffp_varying_specular"; 8992 break; 8993 8994 case WINED3DTA_TEMP: 8995 ret = "temp_reg"; 8996 break; 8997 8998 case WINED3DTA_CONSTANT: 8999 switch (stage) 9000 { 9001 case 0: ret = "tss_const0"; break; 9002 case 1: ret = "tss_const1"; break; 9003 case 2: ret = "tss_const2"; break; 9004 case 3: ret = "tss_const3"; break; 9005 case 4: ret = "tss_const4"; break; 9006 case 5: ret = "tss_const5"; break; 9007 case 6: ret = "tss_const6"; break; 9008 case 7: ret = "tss_const7"; break; 9009 default: 9010 ret = "<invalid constant>"; 9011 break; 9012 } 9013 break; 9014 9015 default: 9016 return "<unhandled arg>"; 9017 } 9018 9019 if (arg & WINED3DTA_COMPLEMENT) 9020 { 9021 shader_addline(buffer, "arg%u = vec4(1.0) - %s;\n", argnum, ret); 9022 if (argnum == 0) 9023 ret = "arg0"; 9024 else if (argnum == 1) 9025 ret = "arg1"; 9026 else if (argnum == 2) 9027 ret = "arg2"; 9028 } 9029 9030 if (arg & WINED3DTA_ALPHAREPLICATE) 9031 { 9032 shader_addline(buffer, "arg%u = vec4(%s.w);\n", argnum, ret); 9033 if (argnum == 0) 9034 ret = "arg0"; 9035 else if (argnum == 1) 9036 ret = "arg1"; 9037 else if (argnum == 2) 9038 ret = "arg2"; 9039 } 9040 9041 return ret; 9042 } 9043 9044 static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL color, 9045 BOOL alpha, BOOL tmp_dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) 9046 { 9047 const char *dstmask, *dstreg, *arg0, *arg1, *arg2; 9048 9049 if (color && alpha) 9050 dstmask = ""; 9051 else if (color) 9052 dstmask = ".xyz"; 9053 else 9054 dstmask = ".w"; 9055 9056 dstreg = tmp_dst ? "temp_reg" : "ret"; 9057 9058 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0); 9059 arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1); 9060 arg2 = shader_glsl_get_ffp_fragment_op_arg(buffer, 2, stage, dw_arg2); 9061 9062 switch (op) 9063 { 9064 case WINED3D_TOP_DISABLE: 9065 break; 9066 9067 case WINED3D_TOP_SELECT_ARG1: 9068 shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg1, dstmask); 9069 break; 9070 9071 case WINED3D_TOP_SELECT_ARG2: 9072 shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg2, dstmask); 9073 break; 9074 9075 case WINED3D_TOP_MODULATE: 9076 shader_addline(buffer, "%s%s = %s%s * %s%s;\n", dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9077 break; 9078 9079 case WINED3D_TOP_MODULATE_4X: 9080 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 4.0, 0.0, 1.0);\n", 9081 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9082 break; 9083 9084 case WINED3D_TOP_MODULATE_2X: 9085 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 2.0, 0.0, 1.0);\n", 9086 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9087 break; 9088 9089 case WINED3D_TOP_ADD: 9090 shader_addline(buffer, "%s%s = clamp(%s%s + %s%s, 0.0, 1.0);\n", 9091 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9092 break; 9093 9094 case WINED3D_TOP_ADD_SIGNED: 9095 shader_addline(buffer, "%s%s = clamp(%s%s + (%s - vec4(0.5))%s, 0.0, 1.0);\n", 9096 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9097 break; 9098 9099 case WINED3D_TOP_ADD_SIGNED_2X: 9100 shader_addline(buffer, "%s%s = clamp((%s%s + (%s - vec4(0.5))%s) * 2.0, 0.0, 1.0);\n", 9101 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9102 break; 9103 9104 case WINED3D_TOP_SUBTRACT: 9105 shader_addline(buffer, "%s%s = clamp(%s%s - %s%s, 0.0, 1.0);\n", 9106 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 9107 break; 9108 9109 case WINED3D_TOP_ADD_SMOOTH: 9110 shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s%s, 0.0, 1.0);\n", 9111 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1, dstmask); 9112 break; 9113 9114 case WINED3D_TOP_BLEND_DIFFUSE_ALPHA: 9115 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_DIFFUSE); 9116 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 9117 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 9118 break; 9119 9120 case WINED3D_TOP_BLEND_TEXTURE_ALPHA: 9121 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE); 9122 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 9123 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 9124 break; 9125 9126 case WINED3D_TOP_BLEND_FACTOR_ALPHA: 9127 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TFACTOR); 9128 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 9129 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 9130 break; 9131 9132 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: 9133 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE); 9134 shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n", 9135 dstreg, dstmask, arg2, dstmask, arg0, arg1, dstmask); 9136 break; 9137 9138 case WINED3D_TOP_BLEND_CURRENT_ALPHA: 9139 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_CURRENT); 9140 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 9141 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 9142 break; 9143 9144 case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR: 9145 shader_addline(buffer, "%s%s = clamp(%s%s * %s.w + %s%s, 0.0, 1.0);\n", 9146 dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask); 9147 break; 9148 9149 case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA: 9150 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s.w, 0.0, 1.0);\n", 9151 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1); 9152 break; 9153 9154 case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR: 9155 shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n", 9156 dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask); 9157 break; 9158 case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA: 9159 shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s.w, 0.0, 1.0);\n", 9160 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1); 9161 break; 9162 9163 case WINED3D_TOP_BUMPENVMAP: 9164 case WINED3D_TOP_BUMPENVMAP_LUMINANCE: 9165 /* These are handled in the first pass, nothing to do. */ 9166 break; 9167 9168 case WINED3D_TOP_DOTPRODUCT3: 9169 shader_addline(buffer, "%s%s = vec4(clamp(dot(%s.xyz - 0.5, %s.xyz - 0.5) * 4.0, 0.0, 1.0))%s;\n", 9170 dstreg, dstmask, arg1, arg2, dstmask); 9171 break; 9172 9173 case WINED3D_TOP_MULTIPLY_ADD: 9174 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s%s, 0.0, 1.0);\n", 9175 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg0, dstmask); 9176 break; 9177 9178 case WINED3D_TOP_LERP: 9179 /* MSDN isn't quite right here. */ 9180 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s%s);\n", 9181 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0, dstmask); 9182 break; 9183 9184 default: 9185 FIXME("Unhandled operation %#x.\n", op); 9186 break; 9187 } 9188 } 9189 9190 /* Context activation is done by the caller. */ 9191 static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *priv, 9192 const struct ffp_frag_settings *settings, const struct wined3d_context *context) 9193 { 9194 const char *output = needs_legacy_glsl_syntax(context->gl_info) ? "gl_FragData[0]" : "ps_out0"; 9195 struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers); 9196 enum wined3d_cmp_func alpha_test_func = settings->alpha_test_func + 1; 9197 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 9198 BYTE lum_map = 0, bump_map = 0, tex_map = 0, tss_const_map = 0; 9199 const struct wined3d_gl_info *gl_info = context->gl_info; 9200 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 9201 BOOL tempreg_used = FALSE, tfactor_used = FALSE; 9202 UINT lowest_disabled_stage; 9203 GLuint shader_id; 9204 DWORD arg0, arg1, arg2; 9205 unsigned int stage; 9206 9207 string_buffer_clear(buffer); 9208 9209 /* Find out which textures are read */ 9210 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9211 { 9212 if (settings->op[stage].cop == WINED3D_TOP_DISABLE) 9213 break; 9214 9215 arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK; 9216 arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK; 9217 arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK; 9218 9219 if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE 9220 || (stage == 0 && settings->color_key_enabled)) 9221 tex_map |= 1u << stage; 9222 if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) 9223 tfactor_used = TRUE; 9224 if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) 9225 tempreg_used = TRUE; 9226 if (settings->op[stage].tmp_dst) 9227 tempreg_used = TRUE; 9228 if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT) 9229 tss_const_map |= 1u << stage; 9230 9231 switch (settings->op[stage].cop) 9232 { 9233 case WINED3D_TOP_BUMPENVMAP_LUMINANCE: 9234 lum_map |= 1u << stage; 9235 /* fall through */ 9236 case WINED3D_TOP_BUMPENVMAP: 9237 bump_map |= 1u << stage; 9238 /* fall through */ 9239 case WINED3D_TOP_BLEND_TEXTURE_ALPHA: 9240 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: 9241 tex_map |= 1u << stage; 9242 break; 9243 9244 case WINED3D_TOP_BLEND_FACTOR_ALPHA: 9245 tfactor_used = TRUE; 9246 break; 9247 9248 default: 9249 break; 9250 } 9251 9252 if (settings->op[stage].aop == WINED3D_TOP_DISABLE) 9253 continue; 9254 9255 arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK; 9256 arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK; 9257 arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK; 9258 9259 if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE) 9260 tex_map |= 1u << stage; 9261 if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) 9262 tfactor_used = TRUE; 9263 if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) 9264 tempreg_used = TRUE; 9265 if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT) 9266 tss_const_map |= 1u << stage; 9267 } 9268 lowest_disabled_stage = stage; 9269 9270 shader_glsl_add_version_declaration(buffer, gl_info); 9271 9272 if (shader_glsl_use_explicit_attrib_location(gl_info)) 9273 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 9274 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) 9275 shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n"); 9276 if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) 9277 shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); 9278 9279 if (!needs_legacy_glsl_syntax(gl_info)) 9280 { 9281 if (shader_glsl_use_explicit_attrib_location(gl_info)) 9282 shader_addline(buffer, "layout(location = 0) "); 9283 shader_addline(buffer, "out vec4 ps_out0;\n"); 9284 } 9285 9286 shader_addline(buffer, "vec4 tmp0, tmp1;\n"); 9287 shader_addline(buffer, "vec4 ret;\n"); 9288 if (tempreg_used || settings->sRGB_write) 9289 shader_addline(buffer, "vec4 temp_reg = vec4(0.0);\n"); 9290 shader_addline(buffer, "vec4 arg0, arg1, arg2;\n"); 9291 9292 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9293 { 9294 const char *sampler_type; 9295 9296 if (tss_const_map & (1u << stage)) 9297 shader_addline(buffer, "uniform vec4 tss_const%u;\n", stage); 9298 9299 if (!(tex_map & (1u << stage))) 9300 continue; 9301 9302 switch (settings->op[stage].tex_type) 9303 { 9304 case WINED3D_GL_RES_TYPE_TEX_1D: 9305 sampler_type = "1D"; 9306 break; 9307 case WINED3D_GL_RES_TYPE_TEX_2D: 9308 sampler_type = "2D"; 9309 break; 9310 case WINED3D_GL_RES_TYPE_TEX_3D: 9311 sampler_type = "3D"; 9312 break; 9313 case WINED3D_GL_RES_TYPE_TEX_CUBE: 9314 sampler_type = "Cube"; 9315 break; 9316 case WINED3D_GL_RES_TYPE_TEX_RECT: 9317 sampler_type = "2DRect"; 9318 break; 9319 default: 9320 FIXME("Unhandled sampler type %#x.\n", settings->op[stage].tex_type); 9321 sampler_type = NULL; 9322 break; 9323 } 9324 if (sampler_type) 9325 { 9326 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 9327 shader_glsl_append_sampler_binding_qualifier(buffer, context, NULL, stage); 9328 shader_addline(buffer, "uniform sampler%s ps_sampler%u;\n", sampler_type, stage); 9329 } 9330 9331 shader_addline(buffer, "vec4 tex%u;\n", stage); 9332 9333 if (!(bump_map & (1u << stage))) 9334 continue; 9335 shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", stage); 9336 9337 if (!(lum_map & (1u << stage))) 9338 continue; 9339 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", stage); 9340 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", stage); 9341 } 9342 if (tfactor_used) 9343 shader_addline(buffer, "uniform vec4 tex_factor;\n"); 9344 if (settings->color_key_enabled) 9345 shader_addline(buffer, "uniform vec4 color_key[2];\n"); 9346 shader_addline(buffer, "uniform vec4 specular_enable;\n"); 9347 9348 if (settings->sRGB_write) 9349 { 9350 shader_addline(buffer, "const vec4 srgb_const0 = "); 9351 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0); 9352 shader_addline(buffer, ";\n"); 9353 shader_addline(buffer, "const vec4 srgb_const1 = "); 9354 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1); 9355 shader_addline(buffer, ";\n"); 9356 } 9357 9358 shader_addline(buffer, "uniform struct\n{\n"); 9359 shader_addline(buffer, " vec4 color;\n"); 9360 shader_addline(buffer, " float density;\n"); 9361 shader_addline(buffer, " float end;\n"); 9362 shader_addline(buffer, " float scale;\n"); 9363 shader_addline(buffer, "} ffp_fog;\n"); 9364 9365 if (alpha_test_func != WINED3D_CMP_ALWAYS) 9366 shader_addline(buffer, "uniform float alpha_test_ref;\n"); 9367 9368 if (legacy_syntax) 9369 { 9370 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n"); 9371 shader_addline(buffer, "vec4 ffp_varying_specular;\n"); 9372 shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 9373 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 9374 shader_addline(buffer, "float ffp_varying_fogcoord;\n"); 9375 } 9376 else 9377 { 9378 declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n"); 9379 declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_specular;\n"); 9380 declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 9381 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 9382 declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 9383 } 9384 9385 shader_addline(buffer, "void main()\n{\n"); 9386 9387 if (legacy_syntax) 9388 { 9389 shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n"); 9390 shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n"); 9391 } 9392 9393 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9394 { 9395 if (tex_map & (1u << stage)) 9396 { 9397 if (settings->pointsprite) 9398 shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", stage); 9399 else if (settings->texcoords_initialized & (1u << stage)) 9400 shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n", 9401 stage, legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", stage); 9402 else 9403 shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", stage); 9404 } 9405 } 9406 9407 if (legacy_syntax && settings->fog != WINED3D_FFP_PS_FOG_OFF) 9408 shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n"); 9409 9410 if (lowest_disabled_stage < 7 && settings->emul_clipplanes) 9411 shader_addline(buffer, "if (any(lessThan(ffp_texcoord[7], vec4(0.0)))) discard;\n"); 9412 9413 /* Generate texture sampling instructions */ 9414 for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage) 9415 { 9416 const char *texture_function, *coord_mask; 9417 BOOL proj; 9418 9419 if (!(tex_map & (1u << stage))) 9420 continue; 9421 9422 if (settings->op[stage].projected == WINED3D_PROJECTION_NONE) 9423 { 9424 proj = FALSE; 9425 } 9426 else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4 9427 || settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) 9428 { 9429 proj = TRUE; 9430 } 9431 else 9432 { 9433 FIXME("Unexpected projection mode %d\n", settings->op[stage].projected); 9434 proj = TRUE; 9435 } 9436 9437 if (settings->op[stage].tex_type == WINED3D_GL_RES_TYPE_TEX_CUBE) 9438 proj = FALSE; 9439 9440 switch (settings->op[stage].tex_type) 9441 { 9442 case WINED3D_GL_RES_TYPE_TEX_1D: 9443 if (proj) 9444 { 9445 texture_function = "texture1DProj"; 9446 coord_mask = "xw"; 9447 } 9448 else 9449 { 9450 texture_function = "texture1D"; 9451 coord_mask = "x"; 9452 } 9453 break; 9454 case WINED3D_GL_RES_TYPE_TEX_2D: 9455 if (proj) 9456 { 9457 texture_function = "texture2DProj"; 9458 coord_mask = "xyw"; 9459 } 9460 else 9461 { 9462 texture_function = "texture2D"; 9463 coord_mask = "xy"; 9464 } 9465 break; 9466 case WINED3D_GL_RES_TYPE_TEX_3D: 9467 if (proj) 9468 { 9469 texture_function = "texture3DProj"; 9470 coord_mask = "xyzw"; 9471 } 9472 else 9473 { 9474 texture_function = "texture3D"; 9475 coord_mask = "xyz"; 9476 } 9477 break; 9478 case WINED3D_GL_RES_TYPE_TEX_CUBE: 9479 texture_function = "textureCube"; 9480 coord_mask = "xyz"; 9481 break; 9482 case WINED3D_GL_RES_TYPE_TEX_RECT: 9483 if (proj) 9484 { 9485 texture_function = "texture2DRectProj"; 9486 coord_mask = "xyw"; 9487 } 9488 else 9489 { 9490 texture_function = "texture2DRect"; 9491 coord_mask = "xy"; 9492 } 9493 break; 9494 default: 9495 FIXME("Unhandled texture type %#x.\n", settings->op[stage].tex_type); 9496 texture_function = ""; 9497 coord_mask = "xyzw"; 9498 break; 9499 } 9500 if (!legacy_syntax) 9501 texture_function = proj ? "textureProj" : "texture"; 9502 9503 if (stage > 0 9504 && (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP 9505 || settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)) 9506 { 9507 shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1); 9508 9509 /* With projective textures, texbem only divides the static 9510 * texture coordinate, not the displacement, so multiply the 9511 * displacement with the dividing parameter before passing it to 9512 * TXP. */ 9513 if (settings->op[stage].projected != WINED3D_PROJECTION_NONE) 9514 { 9515 if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4) 9516 { 9517 shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n", 9518 stage, stage); 9519 shader_addline(buffer, "ret.zw = ffp_texcoord[%u].ww;\n", stage); 9520 } 9521 else 9522 { 9523 shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].z) + ffp_texcoord[%u].xy;\n", 9524 stage, stage); 9525 shader_addline(buffer, "ret.zw = ffp_texcoord[%u].zz;\n", stage); 9526 } 9527 } 9528 else 9529 { 9530 shader_addline(buffer, "ret = ffp_texcoord[%u] + ret.xyxy;\n", stage); 9531 } 9532 9533 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ret.%s);\n", 9534 stage, texture_function, stage, coord_mask); 9535 9536 if (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE) 9537 shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n", 9538 stage, stage - 1, stage - 1, stage - 1); 9539 } 9540 else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) 9541 { 9542 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n", 9543 stage, texture_function, stage, stage); 9544 } 9545 else 9546 { 9547 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].%s);\n", 9548 stage, texture_function, stage, stage, coord_mask); 9549 } 9550 9551 string_buffer_sprintf(tex_reg_name, "tex%u", stage); 9552 shader_glsl_color_correction_ext(buffer, tex_reg_name->buffer, WINED3DSP_WRITEMASK_ALL, 9553 settings->op[stage].color_fixup); 9554 } 9555 9556 if (settings->color_key_enabled) 9557 { 9558 shader_addline(buffer, "if (all(greaterThanEqual(tex0, color_key[0])) && all(lessThan(tex0, color_key[1])))\n"); 9559 shader_addline(buffer, " discard;\n"); 9560 } 9561 9562 shader_addline(buffer, "ret = ffp_varying_diffuse;\n"); 9563 9564 /* Generate the main shader */ 9565 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9566 { 9567 BOOL op_equal; 9568 9569 if (settings->op[stage].cop == WINED3D_TOP_DISABLE) 9570 break; 9571 9572 if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1 9573 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1) 9574 op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1; 9575 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1 9576 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2) 9577 op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2; 9578 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2 9579 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1) 9580 op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1; 9581 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2 9582 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2) 9583 op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2; 9584 else 9585 op_equal = settings->op[stage].aop == settings->op[stage].cop 9586 && settings->op[stage].carg0 == settings->op[stage].aarg0 9587 && settings->op[stage].carg1 == settings->op[stage].aarg1 9588 && settings->op[stage].carg2 == settings->op[stage].aarg2; 9589 9590 if (settings->op[stage].aop == WINED3D_TOP_DISABLE) 9591 { 9592 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].tmp_dst, 9593 settings->op[stage].cop, settings->op[stage].carg0, 9594 settings->op[stage].carg1, settings->op[stage].carg2); 9595 } 9596 else if (op_equal) 9597 { 9598 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].tmp_dst, 9599 settings->op[stage].cop, settings->op[stage].carg0, 9600 settings->op[stage].carg1, settings->op[stage].carg2); 9601 } 9602 else if (settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP 9603 && settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE) 9604 { 9605 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].tmp_dst, 9606 settings->op[stage].cop, settings->op[stage].carg0, 9607 settings->op[stage].carg1, settings->op[stage].carg2); 9608 shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].tmp_dst, 9609 settings->op[stage].aop, settings->op[stage].aarg0, 9610 settings->op[stage].aarg1, settings->op[stage].aarg2); 9611 } 9612 } 9613 9614 shader_addline(buffer, "%s = ffp_varying_specular * specular_enable + ret;\n", output); 9615 9616 if (settings->sRGB_write) 9617 shader_glsl_generate_srgb_write_correction(buffer, gl_info); 9618 9619 shader_glsl_generate_fog_code(buffer, gl_info, settings->fog); 9620 9621 shader_glsl_generate_alpha_test(buffer, gl_info, alpha_test_func); 9622 9623 shader_addline(buffer, "}\n"); 9624 9625 shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); 9626 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 9627 9628 string_buffer_release(&priv->string_buffers, tex_reg_name); 9629 return shader_id; 9630 } 9631 9632 static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv *priv, 9633 const struct wined3d_gl_info *gl_info, const struct wined3d_ffp_vs_settings *settings) 9634 { 9635 struct glsl_ffp_vertex_shader *shader; 9636 const struct wine_rb_entry *entry; 9637 9638 if ((entry = wine_rb_get(&priv->ffp_vertex_shaders, settings))) 9639 return WINE_RB_ENTRY_VALUE(entry, struct glsl_ffp_vertex_shader, desc.entry); 9640 9641 if (!(shader = heap_alloc(sizeof(*shader)))) 9642 return NULL; 9643 9644 shader->desc.settings = *settings; 9645 shader->id = shader_glsl_generate_ffp_vertex_shader(priv, settings, gl_info); 9646 list_init(&shader->linked_programs); 9647 if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1) 9648 ERR("Failed to insert ffp vertex shader.\n"); 9649 9650 return shader; 9651 } 9652 9653 static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv, 9654 const struct ffp_frag_settings *args, const struct wined3d_context *context) 9655 { 9656 struct glsl_ffp_fragment_shader *glsl_desc; 9657 const struct ffp_frag_desc *desc; 9658 9659 if ((desc = find_ffp_frag_shader(&priv->ffp_fragment_shaders, args))) 9660 return CONTAINING_RECORD(desc, struct glsl_ffp_fragment_shader, entry); 9661 9662 if (!(glsl_desc = heap_alloc(sizeof(*glsl_desc)))) 9663 return NULL; 9664 9665 glsl_desc->entry.settings = *args; 9666 glsl_desc->id = shader_glsl_generate_ffp_fragment_shader(priv, args, context); 9667 list_init(&glsl_desc->linked_programs); 9668 add_ffp_frag_shader(&priv->ffp_fragment_shaders, &glsl_desc->entry); 9669 9670 return glsl_desc; 9671 } 9672 9673 9674 static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info *gl_info, 9675 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_vs_program *vs, unsigned int vs_c_count) 9676 { 9677 unsigned int i; 9678 struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers); 9679 9680 for (i = 0; i < vs_c_count; ++i) 9681 { 9682 string_buffer_sprintf(name, "vs_c[%u]", i); 9683 vs->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9684 } 9685 memset(&vs->uniform_f_locations[vs_c_count], 0xff, (WINED3D_MAX_VS_CONSTS_F - vs_c_count) * sizeof(GLuint)); 9686 9687 for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i) 9688 { 9689 string_buffer_sprintf(name, "vs_i[%u]", i); 9690 vs->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9691 } 9692 9693 for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i) 9694 { 9695 string_buffer_sprintf(name, "vs_b[%u]", i); 9696 vs->uniform_b_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9697 } 9698 9699 vs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); 9700 9701 for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i) 9702 { 9703 string_buffer_sprintf(name, "ffp_modelview_matrix[%u]", i); 9704 vs->modelview_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9705 } 9706 for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i) 9707 { 9708 string_buffer_sprintf(name, "ffp_normal_matrix[%u]", i); 9709 vs->normal_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9710 } 9711 vs->projection_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_projection_matrix")); 9712 for (i = 0; i < MAX_TEXTURES; ++i) 9713 { 9714 string_buffer_sprintf(name, "ffp_texture_matrix[%u]", i); 9715 vs->texture_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9716 } 9717 vs->material_ambient_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.ambient")); 9718 vs->material_diffuse_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.diffuse")); 9719 vs->material_specular_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.specular")); 9720 vs->material_emissive_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.emissive")); 9721 vs->material_shininess_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.shininess")); 9722 vs->light_ambient_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_light_ambient")); 9723 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) 9724 { 9725 string_buffer_sprintf(name, "ffp_light[%u].diffuse", i); 9726 vs->light_location[i].diffuse = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9727 string_buffer_sprintf(name, "ffp_light[%u].specular", i); 9728 vs->light_location[i].specular = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9729 string_buffer_sprintf(name, "ffp_light[%u].ambient", i); 9730 vs->light_location[i].ambient = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9731 string_buffer_sprintf(name, "ffp_light[%u].position", i); 9732 vs->light_location[i].position = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9733 string_buffer_sprintf(name, "ffp_light[%u].direction", i); 9734 vs->light_location[i].direction = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9735 string_buffer_sprintf(name, "ffp_light[%u].range", i); 9736 vs->light_location[i].range = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9737 string_buffer_sprintf(name, "ffp_light[%u].falloff", i); 9738 vs->light_location[i].falloff = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9739 string_buffer_sprintf(name, "ffp_light[%u].c_att", i); 9740 vs->light_location[i].c_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9741 string_buffer_sprintf(name, "ffp_light[%u].l_att", i); 9742 vs->light_location[i].l_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9743 string_buffer_sprintf(name, "ffp_light[%u].q_att", i); 9744 vs->light_location[i].q_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9745 string_buffer_sprintf(name, "ffp_light[%u].cos_htheta", i); 9746 vs->light_location[i].cos_htheta = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9747 string_buffer_sprintf(name, "ffp_light[%u].cos_hphi", i); 9748 vs->light_location[i].cos_hphi = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9749 } 9750 vs->pointsize_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size")); 9751 vs->pointsize_min_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size_min")); 9752 vs->pointsize_max_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size_max")); 9753 vs->pointsize_c_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.c_att")); 9754 vs->pointsize_l_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.l_att")); 9755 vs->pointsize_q_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.q_att")); 9756 vs->clip_planes_location = GL_EXTCALL(glGetUniformLocation(program_id, "clip_planes")); 9757 9758 string_buffer_release(&priv->string_buffers, name); 9759 } 9760 9761 static void shader_glsl_init_ds_uniform_locations(const struct wined3d_gl_info *gl_info, 9762 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ds_program *ds) 9763 { 9764 ds->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); 9765 } 9766 9767 static void shader_glsl_init_gs_uniform_locations(const struct wined3d_gl_info *gl_info, 9768 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_gs_program *gs) 9769 { 9770 gs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); 9771 } 9772 9773 static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *gl_info, 9774 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ps_program *ps, unsigned int ps_c_count) 9775 { 9776 unsigned int i; 9777 struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers); 9778 9779 for (i = 0; i < ps_c_count; ++i) 9780 { 9781 string_buffer_sprintf(name, "ps_c[%u]", i); 9782 ps->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9783 } 9784 memset(&ps->uniform_f_locations[ps_c_count], 0xff, (WINED3D_MAX_PS_CONSTS_F - ps_c_count) * sizeof(GLuint)); 9785 9786 for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i) 9787 { 9788 string_buffer_sprintf(name, "ps_i[%u]", i); 9789 ps->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9790 } 9791 9792 for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i) 9793 { 9794 string_buffer_sprintf(name, "ps_b[%u]", i); 9795 ps->uniform_b_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9796 } 9797 9798 for (i = 0; i < MAX_TEXTURES; ++i) 9799 { 9800 string_buffer_sprintf(name, "bumpenv_mat%u", i); 9801 ps->bumpenv_mat_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9802 string_buffer_sprintf(name, "bumpenv_lum_scale%u", i); 9803 ps->bumpenv_lum_scale_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9804 string_buffer_sprintf(name, "bumpenv_lum_offset%u", i); 9805 ps->bumpenv_lum_offset_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9806 string_buffer_sprintf(name, "tss_const%u", i); 9807 ps->tss_constant_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9808 } 9809 9810 ps->tex_factor_location = GL_EXTCALL(glGetUniformLocation(program_id, "tex_factor")); 9811 ps->specular_enable_location = GL_EXTCALL(glGetUniformLocation(program_id, "specular_enable")); 9812 9813 ps->fog_color_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.color")); 9814 ps->fog_density_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.density")); 9815 ps->fog_end_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.end")); 9816 ps->fog_scale_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.scale")); 9817 9818 ps->alpha_test_ref_location = GL_EXTCALL(glGetUniformLocation(program_id, "alpha_test_ref")); 9819 9820 ps->np2_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "ps_samplerNP2Fixup")); 9821 ps->ycorrection_location = GL_EXTCALL(glGetUniformLocation(program_id, "ycorrection")); 9822 ps->color_key_location = GL_EXTCALL(glGetUniformLocation(program_id, "color_key")); 9823 9824 string_buffer_release(&priv->string_buffers, name); 9825 } 9826 9827 static HRESULT shader_glsl_compile_compute_shader(struct shader_glsl_priv *priv, 9828 const struct wined3d_context *context, struct wined3d_shader *shader) 9829 { 9830 struct glsl_context_data *ctx_data = context->shader_backend_data; 9831 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 9832 const struct wined3d_gl_info *gl_info = context->gl_info; 9833 struct glsl_cs_compiled_shader *gl_shaders; 9834 struct glsl_shader_private *shader_data; 9835 struct glsl_shader_prog_link *entry; 9836 GLuint shader_id, program_id; 9837 9838 if (!(entry = heap_alloc(sizeof(*entry)))) 9839 { 9840 ERR("Out of memory.\n"); 9841 return E_OUTOFMEMORY; 9842 } 9843 9844 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 9845 { 9846 ERR("Failed to allocate backend data.\n"); 9847 heap_free(entry); 9848 return E_OUTOFMEMORY; 9849 } 9850 shader_data = shader->backend_data; 9851 gl_shaders = shader_data->gl_shaders.cs; 9852 9853 if (!(shader_data->gl_shaders.cs = heap_alloc(sizeof(*gl_shaders)))) 9854 { 9855 ERR("Failed to allocate GL shader array.\n"); 9856 heap_free(entry); 9857 heap_free(shader->backend_data); 9858 shader->backend_data = NULL; 9859 return E_OUTOFMEMORY; 9860 } 9861 shader_data->shader_array_size = 1; 9862 gl_shaders = shader_data->gl_shaders.cs; 9863 9864 TRACE("Compiling compute shader %p.\n", shader); 9865 9866 string_buffer_clear(buffer); 9867 shader_id = shader_glsl_generate_compute_shader(context, buffer, &priv->string_buffers, shader); 9868 gl_shaders[shader_data->num_gl_shaders++].id = shader_id; 9869 9870 program_id = GL_EXTCALL(glCreateProgram()); 9871 TRACE("Created new GLSL shader program %u.\n", program_id); 9872 9873 entry->id = program_id; 9874 entry->vs.id = 0; 9875 entry->hs.id = 0; 9876 entry->ds.id = 0; 9877 entry->gs.id = 0; 9878 entry->ps.id = 0; 9879 entry->cs.id = shader_id; 9880 entry->constant_version = 0; 9881 entry->shader_controlled_clip_distances = 0; 9882 entry->ps.np2_fixup_info = NULL; 9883 add_glsl_program_entry(priv, entry); 9884 9885 TRACE("Attaching GLSL shader object %u to program %u.\n", shader_id, program_id); 9886 GL_EXTCALL(glAttachShader(program_id, shader_id)); 9887 checkGLcall("glAttachShader"); 9888 9889 list_add_head(&shader->linked_programs, &entry->cs.shader_entry); 9890 9891 TRACE("Linking GLSL shader program %u.\n", program_id); 9892 GL_EXTCALL(glLinkProgram(program_id)); 9893 shader_glsl_validate_link(gl_info, program_id); 9894 9895 GL_EXTCALL(glUseProgram(program_id)); 9896 checkGLcall("glUseProgram"); 9897 shader_glsl_load_program_resources(context, priv, program_id, shader); 9898 shader_glsl_load_images(gl_info, priv, program_id, &shader->reg_maps); 9899 9900 entry->constant_update_mask = 0; 9901 9902 GL_EXTCALL(glUseProgram(ctx_data->glsl_program ? ctx_data->glsl_program->id : 0)); 9903 checkGLcall("glUseProgram"); 9904 return WINED3D_OK; 9905 } 9906 9907 static GLuint find_glsl_compute_shader(const struct wined3d_context *context, 9908 struct shader_glsl_priv *priv, struct wined3d_shader *shader) 9909 { 9910 struct glsl_shader_private *shader_data; 9911 9912 if (!shader->backend_data) 9913 { 9914 WARN("Failed to find GLSL program for compute shader %p.\n", shader); 9915 if (FAILED(shader_glsl_compile_compute_shader(priv, context, shader))) 9916 { 9917 ERR("Failed to compile compute shader %p.\n", shader); 9918 return 0; 9919 } 9920 } 9921 shader_data = shader->backend_data; 9922 return shader_data->gl_shaders.cs[0].id; 9923 } 9924 9925 /* Context activation is done by the caller. */ 9926 static void set_glsl_compute_shader_program(const struct wined3d_context *context, 9927 const struct wined3d_state *state, struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data) 9928 { 9929 struct glsl_shader_prog_link *entry; 9930 struct wined3d_shader *shader; 9931 struct glsl_program_key key; 9932 GLuint cs_id; 9933 9934 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))) 9935 return; 9936 9937 if (!(shader = state->shader[WINED3D_SHADER_TYPE_COMPUTE])) 9938 { 9939 WARN("Compute shader is NULL.\n"); 9940 ctx_data->glsl_program = NULL; 9941 return; 9942 } 9943 9944 cs_id = find_glsl_compute_shader(context, priv, shader); 9945 memset(&key, 0, sizeof(key)); 9946 key.cs_id = cs_id; 9947 if (!(entry = get_glsl_program_entry(priv, &key))) 9948 ERR("Failed to find GLSL program for compute shader %p.\n", shader); 9949 ctx_data->glsl_program = entry; 9950 } 9951 9952 /* Context activation is done by the caller. */ 9953 static void set_glsl_shader_program(const struct wined3d_context *context, const struct wined3d_state *state, 9954 struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data) 9955 { 9956 const struct wined3d_d3d_info *d3d_info = context->d3d_info; 9957 const struct wined3d_gl_info *gl_info = context->gl_info; 9958 const struct wined3d_shader *pre_rasterization_shader; 9959 const struct ps_np2fixup_info *np2fixup_info = NULL; 9960 struct wined3d_shader *hshader, *dshader, *gshader; 9961 struct glsl_shader_prog_link *entry = NULL; 9962 struct wined3d_shader *vshader = NULL; 9963 struct wined3d_shader *pshader = NULL; 9964 GLuint reorder_shader_id = 0; 9965 struct glsl_program_key key; 9966 GLuint program_id; 9967 unsigned int i; 9968 GLuint vs_id = 0; 9969 GLuint hs_id = 0; 9970 GLuint ds_id = 0; 9971 GLuint gs_id = 0; 9972 GLuint ps_id = 0; 9973 struct list *ps_list = NULL, *vs_list = NULL; 9974 WORD attribs_map; 9975 struct wined3d_string_buffer *tmp_name; 9976 9977 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_VERTEX)) && ctx_data->glsl_program) 9978 { 9979 vs_id = ctx_data->glsl_program->vs.id; 9980 vs_list = &ctx_data->glsl_program->vs.shader_entry; 9981 9982 if (use_vs(state)) 9983 vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 9984 } 9985 else if (use_vs(state)) 9986 { 9987 struct vs_compile_args vs_compile_args; 9988 9989 vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 9990 9991 find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args, context); 9992 vs_id = find_glsl_vshader(context, priv, vshader, &vs_compile_args); 9993 vs_list = &vshader->linked_programs; 9994 } 9995 else if (priv->vertex_pipe == &glsl_vertex_pipe) 9996 { 9997 struct glsl_ffp_vertex_shader *ffp_shader; 9998 struct wined3d_ffp_vs_settings settings; 9999 10000 wined3d_ffp_get_vs_settings(context, state, &settings); 10001 ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings); 10002 vs_id = ffp_shader->id; 10003 vs_list = &ffp_shader->linked_programs; 10004 } 10005 10006 hshader = state->shader[WINED3D_SHADER_TYPE_HULL]; 10007 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_HULL)) && ctx_data->glsl_program) 10008 hs_id = ctx_data->glsl_program->hs.id; 10009 else if (hshader) 10010 hs_id = find_glsl_hull_shader(context, priv, hshader); 10011 10012 dshader = state->shader[WINED3D_SHADER_TYPE_DOMAIN]; 10013 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_DOMAIN)) && ctx_data->glsl_program) 10014 { 10015 ds_id = ctx_data->glsl_program->ds.id; 10016 } 10017 else if (dshader) 10018 { 10019 struct ds_compile_args args; 10020 10021 find_ds_compile_args(state, dshader, &args, context); 10022 ds_id = find_glsl_domain_shader(context, priv, dshader, &args); 10023 } 10024 10025 gshader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]; 10026 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_GEOMETRY)) && ctx_data->glsl_program) 10027 { 10028 gs_id = ctx_data->glsl_program->gs.id; 10029 } 10030 else if (gshader) 10031 { 10032 struct gs_compile_args args; 10033 10034 find_gs_compile_args(state, gshader, &args, context); 10035 gs_id = find_glsl_geometry_shader(context, priv, gshader, &args); 10036 } 10037 10038 /* A pixel shader is not used when rasterization is disabled. */ 10039 if (is_rasterization_disabled(gshader)) 10040 { 10041 ps_id = 0; 10042 ps_list = NULL; 10043 } 10044 else if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_PIXEL)) && ctx_data->glsl_program) 10045 { 10046 ps_id = ctx_data->glsl_program->ps.id; 10047 ps_list = &ctx_data->glsl_program->ps.shader_entry; 10048 10049 if (use_ps(state)) 10050 pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; 10051 } 10052 else if (use_ps(state)) 10053 { 10054 struct ps_compile_args ps_compile_args; 10055 pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; 10056 find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, context); 10057 ps_id = find_glsl_pshader(context, &priv->shader_buffer, &priv->string_buffers, 10058 pshader, &ps_compile_args, &np2fixup_info); 10059 ps_list = &pshader->linked_programs; 10060 } 10061 else if (priv->fragment_pipe == &glsl_fragment_pipe 10062 && !(vshader && vshader->reg_maps.shader_version.major >= 4)) 10063 { 10064 struct glsl_ffp_fragment_shader *ffp_shader; 10065 struct ffp_frag_settings settings; 10066 10067 gen_ffp_frag_op(context, state, &settings, FALSE); 10068 ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, &settings, context); 10069 ps_id = ffp_shader->id; 10070 ps_list = &ffp_shader->linked_programs; 10071 } 10072 10073 key.vs_id = vs_id; 10074 key.hs_id = hs_id; 10075 key.ds_id = ds_id; 10076 key.gs_id = gs_id; 10077 key.ps_id = ps_id; 10078 key.cs_id = 0; 10079 if ((!vs_id && !hs_id && !ds_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, &key))) 10080 { 10081 ctx_data->glsl_program = entry; 10082 return; 10083 } 10084 10085 /* If we get to this point, then no matching program exists, so we create one */ 10086 program_id = GL_EXTCALL(glCreateProgram()); 10087 TRACE("Created new GLSL shader program %u.\n", program_id); 10088 10089 /* Create the entry */ 10090 entry = heap_alloc(sizeof(*entry)); 10091 entry->id = program_id; 10092 entry->vs.id = vs_id; 10093 entry->hs.id = hs_id; 10094 entry->ds.id = ds_id; 10095 entry->gs.id = gs_id; 10096 entry->ps.id = ps_id; 10097 entry->cs.id = 0; 10098 entry->constant_version = 0; 10099 entry->shader_controlled_clip_distances = 0; 10100 entry->ps.np2_fixup_info = np2fixup_info; 10101 /* Add the hash table entry */ 10102 add_glsl_program_entry(priv, entry); 10103 10104 /* Set the current program */ 10105 ctx_data->glsl_program = entry; 10106 10107 /* Attach GLSL vshader */ 10108 if (vs_id) 10109 { 10110 TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, program_id); 10111 GL_EXTCALL(glAttachShader(program_id, vs_id)); 10112 checkGLcall("glAttachShader"); 10113 10114 list_add_head(vs_list, &entry->vs.shader_entry); 10115 } 10116 10117 if (vshader) 10118 { 10119 attribs_map = vshader->reg_maps.input_registers; 10120 if (vshader->reg_maps.shader_version.major < 4) 10121 { 10122 reorder_shader_id = shader_glsl_generate_vs3_rasterizer_input_setup(priv, vshader, pshader, 10123 state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size, 10124 d3d_info->emulated_flatshading 10125 && state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT, gl_info); 10126 TRACE("Attaching GLSL shader object %u to program %u.\n", reorder_shader_id, program_id); 10127 GL_EXTCALL(glAttachShader(program_id, reorder_shader_id)); 10128 checkGLcall("glAttachShader"); 10129 /* Flag the reorder function for deletion, it will be freed 10130 * automatically when the program is destroyed. */ 10131 GL_EXTCALL(glDeleteShader(reorder_shader_id)); 10132 } 10133 } 10134 else 10135 { 10136 attribs_map = (1u << WINED3D_FFP_ATTRIBS_COUNT) - 1; 10137 } 10138 10139 if (!shader_glsl_use_explicit_attrib_location(gl_info)) 10140 { 10141 /* Bind vertex attributes to a corresponding index number to match 10142 * the same index numbers as ARB_vertex_programs (makes loading 10143 * vertex attributes simpler). With this method, we can use the 10144 * exact same code to load the attributes later for both ARB and 10145 * GLSL shaders. 10146 * 10147 * We have to do this here because we need to know the Program ID 10148 * in order to make the bindings work, and it has to be done prior 10149 * to linking the GLSL program. */ 10150 tmp_name = string_buffer_get(&priv->string_buffers); 10151 for (i = 0; attribs_map; attribs_map >>= 1, ++i) 10152 { 10153 if (!(attribs_map & 1)) 10154 continue; 10155 10156 string_buffer_sprintf(tmp_name, "vs_in%u", i); 10157 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); 10158 if (vshader && vshader->reg_maps.shader_version.major >= 4) 10159 { 10160 string_buffer_sprintf(tmp_name, "vs_in_uint%u", i); 10161 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); 10162 string_buffer_sprintf(tmp_name, "vs_in_int%u", i); 10163 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); 10164 } 10165 } 10166 checkGLcall("glBindAttribLocation"); 10167 string_buffer_release(&priv->string_buffers, tmp_name); 10168 10169 if (!needs_legacy_glsl_syntax(gl_info)) 10170 { 10171 char var[12]; 10172 10173 if (wined3d_dualblend_enabled(state, gl_info)) 10174 { 10175 for (i = 0; i < gl_info->limits.dual_buffers * 2; i++) 10176 { 10177 sprintf(var, "ps_out%u", i); 10178 GL_EXTCALL(glBindFragDataLocationIndexed(program_id, i / 2, i % 2, var)); 10179 checkGLcall("glBindFragDataLocationIndexed"); 10180 } 10181 } 10182 else 10183 { 10184 for (i = 0; i < gl_info->limits.buffers; i++) 10185 { 10186 sprintf(var, "ps_out%u", i); 10187 GL_EXTCALL(glBindFragDataLocation(program_id, i, var)); 10188 checkGLcall("glBindFragDataLocation"); 10189 } 10190 } 10191 } 10192 } 10193 10194 if (hshader) 10195 { 10196 TRACE("Attaching GLSL tessellation control shader object %u to program %u.\n", hs_id, program_id); 10197 GL_EXTCALL(glAttachShader(program_id, hs_id)); 10198 checkGLcall("glAttachShader"); 10199 10200 list_add_head(&hshader->linked_programs, &entry->hs.shader_entry); 10201 } 10202 10203 if (dshader) 10204 { 10205 TRACE("Attaching GLSL tessellation evaluation shader object %u to program %u.\n", ds_id, program_id); 10206 GL_EXTCALL(glAttachShader(program_id, ds_id)); 10207 checkGLcall("glAttachShader"); 10208 10209 list_add_head(&dshader->linked_programs, &entry->ds.shader_entry); 10210 } 10211 10212 if (gshader) 10213 { 10214 TRACE("Attaching GLSL geometry shader object %u to program %u.\n", gs_id, program_id); 10215 GL_EXTCALL(glAttachShader(program_id, gs_id)); 10216 checkGLcall("glAttachShader"); 10217 10218 shader_glsl_init_transform_feedback(context, priv, program_id, gshader); 10219 10220 list_add_head(&gshader->linked_programs, &entry->gs.shader_entry); 10221 } 10222 10223 /* Attach GLSL pshader */ 10224 if (ps_id) 10225 { 10226 TRACE("Attaching GLSL shader object %u to program %u.\n", ps_id, program_id); 10227 GL_EXTCALL(glAttachShader(program_id, ps_id)); 10228 checkGLcall("glAttachShader"); 10229 10230 list_add_head(ps_list, &entry->ps.shader_entry); 10231 } 10232 10233 /* Link the program */ 10234 TRACE("Linking GLSL shader program %u.\n", program_id); 10235 GL_EXTCALL(glLinkProgram(program_id)); 10236 shader_glsl_validate_link(gl_info, program_id); 10237 10238 shader_glsl_init_vs_uniform_locations(gl_info, priv, program_id, &entry->vs, 10239 vshader ? vshader->limits->constant_float : 0); 10240 shader_glsl_init_ds_uniform_locations(gl_info, priv, program_id, &entry->ds); 10241 shader_glsl_init_gs_uniform_locations(gl_info, priv, program_id, &entry->gs); 10242 shader_glsl_init_ps_uniform_locations(gl_info, priv, program_id, &entry->ps, 10243 pshader ? pshader->limits->constant_float : 0); 10244 checkGLcall("find glsl program uniform locations"); 10245 10246 pre_rasterization_shader = gshader ? gshader : dshader ? dshader : vshader; 10247 if (pre_rasterization_shader && pre_rasterization_shader->reg_maps.shader_version.major >= 4) 10248 { 10249 unsigned int clip_distance_count = wined3d_popcount(pre_rasterization_shader->reg_maps.clip_distance_mask); 10250 entry->shader_controlled_clip_distances = 1; 10251 entry->clip_distance_mask = (1u << clip_distance_count) - 1; 10252 } 10253 10254 if (needs_legacy_glsl_syntax(gl_info)) 10255 { 10256 if (pshader && pshader->reg_maps.shader_version.major >= 3 10257 && pshader->u.ps.declared_in_count > vec4_varyings(3, gl_info)) 10258 { 10259 TRACE("Shader %d needs vertex color clamping disabled.\n", program_id); 10260 entry->vs.vertex_color_clamp = GL_FALSE; 10261 } 10262 else 10263 { 10264 entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB; 10265 } 10266 } 10267 else 10268 { 10269 /* With core profile we never change vertex_color_clamp from 10270 * GL_FIXED_ONLY_MODE (which is also the initial value) so we never call 10271 * glClampColorARB(). */ 10272 entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB; 10273 } 10274 10275 /* Set the shader to allow uniform loading on it */ 10276 GL_EXTCALL(glUseProgram(program_id)); 10277 checkGLcall("glUseProgram"); 10278 10279 entry->constant_update_mask = 0; 10280 if (vshader) 10281 { 10282 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_F; 10283 if (vshader->reg_maps.integer_constants) 10284 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_I; 10285 if (vshader->reg_maps.boolean_constants) 10286 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_B; 10287 if (entry->vs.pos_fixup_location != -1) 10288 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 10289 10290 shader_glsl_load_program_resources(context, priv, program_id, vshader); 10291 } 10292 else 10293 { 10294 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW 10295 | WINED3D_SHADER_CONST_FFP_PROJ; 10296 10297 for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i) 10298 { 10299 if (entry->vs.modelview_matrix_location[i] != -1) 10300 { 10301 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND; 10302 break; 10303 } 10304 } 10305 10306 for (i = 0; i < MAX_TEXTURES; ++i) 10307 { 10308 if (entry->vs.texture_matrix_location[i] != -1) 10309 { 10310 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 10311 break; 10312 } 10313 } 10314 if (entry->vs.material_ambient_location != -1 || entry->vs.material_diffuse_location != -1 10315 || entry->vs.material_specular_location != -1 10316 || entry->vs.material_emissive_location != -1 10317 || entry->vs.material_shininess_location != -1) 10318 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MATERIAL; 10319 if (entry->vs.light_ambient_location != -1) 10320 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_LIGHTS; 10321 } 10322 if (entry->vs.clip_planes_location != -1) 10323 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 10324 if (entry->vs.pointsize_min_location != -1) 10325 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 10326 10327 if (hshader) 10328 shader_glsl_load_program_resources(context, priv, program_id, hshader); 10329 10330 if (dshader) 10331 { 10332 if (entry->ds.pos_fixup_location != -1) 10333 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 10334 10335 shader_glsl_load_program_resources(context, priv, program_id, dshader); 10336 } 10337 10338 if (gshader) 10339 { 10340 if (entry->gs.pos_fixup_location != -1) 10341 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 10342 10343 shader_glsl_load_program_resources(context, priv, program_id, gshader); 10344 } 10345 10346 if (ps_id) 10347 { 10348 if (pshader) 10349 { 10350 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_F; 10351 if (pshader->reg_maps.integer_constants) 10352 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_I; 10353 if (pshader->reg_maps.boolean_constants) 10354 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_B; 10355 if (entry->ps.ycorrection_location != -1) 10356 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_Y_CORR; 10357 10358 shader_glsl_load_program_resources(context, priv, program_id, pshader); 10359 shader_glsl_load_images(gl_info, priv, program_id, &pshader->reg_maps); 10360 } 10361 else 10362 { 10363 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS; 10364 10365 shader_glsl_load_samplers(context, priv, program_id, NULL); 10366 } 10367 10368 for (i = 0; i < MAX_TEXTURES; ++i) 10369 { 10370 if (entry->ps.bumpenv_mat_location[i] != -1) 10371 { 10372 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV; 10373 break; 10374 } 10375 } 10376 10377 if (entry->ps.fog_color_location != -1) 10378 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG; 10379 if (entry->ps.alpha_test_ref_location != -1) 10380 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST; 10381 if (entry->ps.np2_fixup_location != -1) 10382 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP; 10383 if (entry->ps.color_key_location != -1) 10384 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY; 10385 } 10386 } 10387 10388 static void shader_glsl_precompile(void *shader_priv, struct wined3d_shader *shader) 10389 { 10390 struct wined3d_device *device = shader->device; 10391 struct wined3d_context *context; 10392 10393 if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_COMPUTE) 10394 { 10395 context = context_acquire(device, NULL, 0); 10396 shader_glsl_compile_compute_shader(shader_priv, context, shader); 10397 context_release(context); 10398 } 10399 } 10400 10401 /* Context activation is done by the caller. */ 10402 static void shader_glsl_select(void *shader_priv, struct wined3d_context *context, 10403 const struct wined3d_state *state) 10404 { 10405 struct glsl_context_data *ctx_data = context->shader_backend_data; 10406 const struct wined3d_gl_info *gl_info = context->gl_info; 10407 struct shader_glsl_priv *priv = shader_priv; 10408 struct glsl_shader_prog_link *glsl_program; 10409 GLenum current_vertex_color_clamp; 10410 GLuint program_id, prev_id; 10411 10412 priv->vertex_pipe->vp_enable(gl_info, !use_vs(state)); 10413 priv->fragment_pipe->enable_extension(gl_info, !use_ps(state)); 10414 10415 prev_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0; 10416 set_glsl_shader_program(context, state, priv, ctx_data); 10417 glsl_program = ctx_data->glsl_program; 10418 10419 if (glsl_program) 10420 { 10421 program_id = glsl_program->id; 10422 current_vertex_color_clamp = glsl_program->vs.vertex_color_clamp; 10423 if (glsl_program->shader_controlled_clip_distances) 10424 context_enable_clip_distances(context, glsl_program->clip_distance_mask); 10425 } 10426 else 10427 { 10428 program_id = 0; 10429 current_vertex_color_clamp = GL_FIXED_ONLY_ARB; 10430 } 10431 10432 if (ctx_data->vertex_color_clamp != current_vertex_color_clamp) 10433 { 10434 ctx_data->vertex_color_clamp = current_vertex_color_clamp; 10435 if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT]) 10436 { 10437 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, current_vertex_color_clamp)); 10438 checkGLcall("glClampColorARB"); 10439 } 10440 else 10441 { 10442 FIXME("Vertex color clamp needs to be changed, but extension not supported.\n"); 10443 } 10444 } 10445 10446 TRACE("Using GLSL program %u.\n", program_id); 10447 10448 if (prev_id != program_id) 10449 { 10450 GL_EXTCALL(glUseProgram(program_id)); 10451 checkGLcall("glUseProgram"); 10452 10453 if (glsl_program) 10454 context->constant_update_mask |= glsl_program->constant_update_mask; 10455 } 10456 10457 context->shader_update_mask |= (1u << WINED3D_SHADER_TYPE_COMPUTE); 10458 } 10459 10460 /* Context activation is done by the caller. */ 10461 static void shader_glsl_select_compute(void *shader_priv, struct wined3d_context *context, 10462 const struct wined3d_state *state) 10463 { 10464 struct glsl_context_data *ctx_data = context->shader_backend_data; 10465 const struct wined3d_gl_info *gl_info = context->gl_info; 10466 struct shader_glsl_priv *priv = shader_priv; 10467 GLuint program_id, prev_id; 10468 10469 prev_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0; 10470 set_glsl_compute_shader_program(context, state, priv, ctx_data); 10471 program_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0; 10472 10473 TRACE("Using GLSL program %u.\n", program_id); 10474 10475 if (prev_id != program_id) 10476 { 10477 GL_EXTCALL(glUseProgram(program_id)); 10478 checkGLcall("glUseProgram"); 10479 } 10480 10481 context->shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL) 10482 | (1u << WINED3D_SHADER_TYPE_VERTEX) 10483 | (1u << WINED3D_SHADER_TYPE_GEOMETRY) 10484 | (1u << WINED3D_SHADER_TYPE_HULL) 10485 | (1u << WINED3D_SHADER_TYPE_DOMAIN); 10486 } 10487 10488 /* "context" is not necessarily the currently active context. */ 10489 static void shader_glsl_invalidate_current_program(struct wined3d_context *context) 10490 { 10491 struct glsl_context_data *ctx_data = context->shader_backend_data; 10492 10493 ctx_data->glsl_program = NULL; 10494 context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL) 10495 | (1u << WINED3D_SHADER_TYPE_VERTEX) 10496 | (1u << WINED3D_SHADER_TYPE_GEOMETRY) 10497 | (1u << WINED3D_SHADER_TYPE_HULL) 10498 | (1u << WINED3D_SHADER_TYPE_DOMAIN) 10499 | (1u << WINED3D_SHADER_TYPE_COMPUTE); 10500 } 10501 10502 /* Context activation is done by the caller. */ 10503 static void shader_glsl_disable(void *shader_priv, struct wined3d_context *context) 10504 { 10505 struct glsl_context_data *ctx_data = context->shader_backend_data; 10506 const struct wined3d_gl_info *gl_info = context->gl_info; 10507 struct shader_glsl_priv *priv = shader_priv; 10508 10509 shader_glsl_invalidate_current_program(context); 10510 GL_EXTCALL(glUseProgram(0)); 10511 checkGLcall("glUseProgram"); 10512 10513 priv->vertex_pipe->vp_enable(gl_info, FALSE); 10514 priv->fragment_pipe->enable_extension(gl_info, FALSE); 10515 10516 if (needs_legacy_glsl_syntax(gl_info) && gl_info->supported[ARB_COLOR_BUFFER_FLOAT]) 10517 { 10518 ctx_data->vertex_color_clamp = GL_FIXED_ONLY_ARB; 10519 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB)); 10520 checkGLcall("glClampColorARB"); 10521 } 10522 } 10523 10524 static void shader_glsl_invalidate_contexts_program(struct wined3d_device *device, 10525 const struct glsl_shader_prog_link *program) 10526 { 10527 const struct glsl_context_data *ctx_data; 10528 struct wined3d_context *context; 10529 unsigned int i; 10530 10531 for (i = 0; i < device->context_count; ++i) 10532 { 10533 context = device->contexts[i]; 10534 ctx_data = context->shader_backend_data; 10535 10536 if (ctx_data->glsl_program == program) 10537 shader_glsl_invalidate_current_program(context); 10538 } 10539 } 10540 10541 static void shader_glsl_destroy(struct wined3d_shader *shader) 10542 { 10543 struct glsl_shader_private *shader_data = shader->backend_data; 10544 struct wined3d_device *device = shader->device; 10545 struct shader_glsl_priv *priv = device->shader_priv; 10546 const struct wined3d_gl_info *gl_info; 10547 const struct list *linked_programs; 10548 struct wined3d_context *context; 10549 10550 if (!shader_data || !shader_data->num_gl_shaders) 10551 { 10552 heap_free(shader_data); 10553 shader->backend_data = NULL; 10554 return; 10555 } 10556 10557 context = context_acquire(device, NULL, 0); 10558 gl_info = context->gl_info; 10559 10560 TRACE("Deleting linked programs.\n"); 10561 linked_programs = &shader->linked_programs; 10562 if (linked_programs->next) 10563 { 10564 struct glsl_shader_prog_link *entry, *entry2; 10565 UINT i; 10566 10567 switch (shader->reg_maps.shader_version.type) 10568 { 10569 case WINED3D_SHADER_TYPE_PIXEL: 10570 { 10571 struct glsl_ps_compiled_shader *gl_shaders = shader_data->gl_shaders.ps; 10572 10573 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10574 { 10575 TRACE("Deleting pixel shader %u.\n", gl_shaders[i].id); 10576 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10577 checkGLcall("glDeleteShader"); 10578 } 10579 heap_free(shader_data->gl_shaders.ps); 10580 10581 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10582 struct glsl_shader_prog_link, ps.shader_entry) 10583 { 10584 shader_glsl_invalidate_contexts_program(device, entry); 10585 delete_glsl_program_entry(priv, gl_info, entry); 10586 } 10587 10588 break; 10589 } 10590 10591 case WINED3D_SHADER_TYPE_VERTEX: 10592 { 10593 struct glsl_vs_compiled_shader *gl_shaders = shader_data->gl_shaders.vs; 10594 10595 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10596 { 10597 TRACE("Deleting vertex shader %u.\n", gl_shaders[i].id); 10598 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10599 checkGLcall("glDeleteShader"); 10600 } 10601 heap_free(shader_data->gl_shaders.vs); 10602 10603 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10604 struct glsl_shader_prog_link, vs.shader_entry) 10605 { 10606 shader_glsl_invalidate_contexts_program(device, entry); 10607 delete_glsl_program_entry(priv, gl_info, entry); 10608 } 10609 10610 break; 10611 } 10612 10613 case WINED3D_SHADER_TYPE_HULL: 10614 { 10615 struct glsl_hs_compiled_shader *gl_shaders = shader_data->gl_shaders.hs; 10616 10617 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10618 { 10619 TRACE("Deleting hull shader %u.\n", gl_shaders[i].id); 10620 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10621 checkGLcall("glDeleteShader"); 10622 } 10623 heap_free(shader_data->gl_shaders.hs); 10624 10625 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10626 struct glsl_shader_prog_link, hs.shader_entry) 10627 { 10628 shader_glsl_invalidate_contexts_program(device, entry); 10629 delete_glsl_program_entry(priv, gl_info, entry); 10630 } 10631 10632 break; 10633 } 10634 10635 case WINED3D_SHADER_TYPE_DOMAIN: 10636 { 10637 struct glsl_ds_compiled_shader *gl_shaders = shader_data->gl_shaders.ds; 10638 10639 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10640 { 10641 TRACE("Deleting domain shader %u.\n", gl_shaders[i].id); 10642 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10643 checkGLcall("glDeleteShader"); 10644 } 10645 heap_free(shader_data->gl_shaders.ds); 10646 10647 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10648 struct glsl_shader_prog_link, ds.shader_entry) 10649 { 10650 shader_glsl_invalidate_contexts_program(device, entry); 10651 delete_glsl_program_entry(priv, gl_info, entry); 10652 } 10653 10654 break; 10655 } 10656 10657 case WINED3D_SHADER_TYPE_GEOMETRY: 10658 { 10659 struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs; 10660 10661 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10662 { 10663 TRACE("Deleting geometry shader %u.\n", gl_shaders[i].id); 10664 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10665 checkGLcall("glDeleteShader"); 10666 } 10667 heap_free(shader_data->gl_shaders.gs); 10668 10669 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10670 struct glsl_shader_prog_link, gs.shader_entry) 10671 { 10672 shader_glsl_invalidate_contexts_program(device, entry); 10673 delete_glsl_program_entry(priv, gl_info, entry); 10674 } 10675 10676 break; 10677 } 10678 10679 case WINED3D_SHADER_TYPE_COMPUTE: 10680 { 10681 struct glsl_cs_compiled_shader *gl_shaders = shader_data->gl_shaders.cs; 10682 10683 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10684 { 10685 TRACE("Deleting compute shader %u.\n", gl_shaders[i].id); 10686 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10687 checkGLcall("glDeleteShader"); 10688 } 10689 heap_free(shader_data->gl_shaders.cs); 10690 10691 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10692 struct glsl_shader_prog_link, cs.shader_entry) 10693 { 10694 shader_glsl_invalidate_contexts_program(device, entry); 10695 delete_glsl_program_entry(priv, gl_info, entry); 10696 } 10697 10698 break; 10699 } 10700 10701 default: 10702 ERR("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type); 10703 break; 10704 } 10705 } 10706 10707 heap_free(shader->backend_data); 10708 shader->backend_data = NULL; 10709 10710 context_release(context); 10711 } 10712 10713 static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry) 10714 { 10715 const struct glsl_program_key *k = key; 10716 const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry, 10717 const struct glsl_shader_prog_link, program_lookup_entry); 10718 10719 if (k->vs_id > prog->vs.id) return 1; 10720 else if (k->vs_id < prog->vs.id) return -1; 10721 10722 if (k->gs_id > prog->gs.id) return 1; 10723 else if (k->gs_id < prog->gs.id) return -1; 10724 10725 if (k->ps_id > prog->ps.id) return 1; 10726 else if (k->ps_id < prog->ps.id) return -1; 10727 10728 if (k->hs_id > prog->hs.id) return 1; 10729 else if (k->hs_id < prog->hs.id) return -1; 10730 10731 if (k->ds_id > prog->ds.id) return 1; 10732 else if (k->ds_id < prog->ds.id) return -1; 10733 10734 if (k->cs_id > prog->cs.id) return 1; 10735 else if (k->cs_id < prog->cs.id) return -1; 10736 10737 return 0; 10738 } 10739 10740 static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count) 10741 { 10742 SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) 10743 + constant_count * sizeof(*heap->contained) 10744 + constant_count * sizeof(*heap->positions); 10745 void *mem; 10746 10747 if (!(mem = heap_alloc(size))) 10748 { 10749 ERR("Failed to allocate memory\n"); 10750 return FALSE; 10751 } 10752 10753 heap->entries = mem; 10754 heap->entries[1].version = 0; 10755 heap->contained = (BOOL *)(heap->entries + constant_count + 1); 10756 memset(heap->contained, 0, constant_count * sizeof(*heap->contained)); 10757 heap->positions = (unsigned int *)(heap->contained + constant_count); 10758 heap->size = 1; 10759 10760 return TRUE; 10761 } 10762 10763 static void constant_heap_free(struct constant_heap *heap) 10764 { 10765 heap_free(heap->entries); 10766 } 10767 10768 static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe, 10769 const struct fragment_pipeline *fragment_pipe) 10770 { 10771 SIZE_T stack_size = wined3d_log2i(max(WINED3D_MAX_VS_CONSTS_F, WINED3D_MAX_PS_CONSTS_F)) + 1; 10772 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; 10773 struct fragment_caps fragment_caps; 10774 void *vertex_priv, *fragment_priv; 10775 struct shader_glsl_priv *priv; 10776 10777 if (!(priv = heap_alloc_zero(sizeof(*priv)))) 10778 return E_OUTOFMEMORY; 10779 10780 string_buffer_list_init(&priv->string_buffers); 10781 10782 if (!(vertex_priv = vertex_pipe->vp_alloc(&glsl_shader_backend, priv))) 10783 { 10784 ERR("Failed to initialize vertex pipe.\n"); 10785 heap_free(priv); 10786 return E_FAIL; 10787 } 10788 10789 if (!(fragment_priv = fragment_pipe->alloc_private(&glsl_shader_backend, priv))) 10790 { 10791 ERR("Failed to initialize fragment pipe.\n"); 10792 vertex_pipe->vp_free(device); 10793 heap_free(priv); 10794 return E_FAIL; 10795 } 10796 10797 if (!string_buffer_init(&priv->shader_buffer)) 10798 { 10799 ERR("Failed to initialize shader buffer.\n"); 10800 goto fail; 10801 } 10802 10803 if (!(priv->stack = heap_calloc(stack_size, sizeof(*priv->stack)))) 10804 { 10805 ERR("Failed to allocate memory.\n"); 10806 goto fail; 10807 } 10808 10809 if (!constant_heap_init(&priv->vconst_heap, WINED3D_MAX_VS_CONSTS_F)) 10810 { 10811 ERR("Failed to initialize vertex shader constant heap\n"); 10812 goto fail; 10813 } 10814 10815 if (!constant_heap_init(&priv->pconst_heap, WINED3D_MAX_PS_CONSTS_F)) 10816 { 10817 ERR("Failed to initialize pixel shader constant heap\n"); 10818 goto fail; 10819 } 10820 10821 wine_rb_init(&priv->program_lookup, glsl_program_key_compare); 10822 10823 priv->next_constant_version = 1; 10824 priv->vertex_pipe = vertex_pipe; 10825 priv->fragment_pipe = fragment_pipe; 10826 fragment_pipe->get_caps(gl_info, &fragment_caps); 10827 priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL; 10828 priv->legacy_lighting = device->wined3d->flags & WINED3D_LEGACY_FFP_LIGHTING; 10829 10830 device->vertex_priv = vertex_priv; 10831 device->fragment_priv = fragment_priv; 10832 device->shader_priv = priv; 10833 10834 return WINED3D_OK; 10835 10836 fail: 10837 constant_heap_free(&priv->pconst_heap); 10838 constant_heap_free(&priv->vconst_heap); 10839 heap_free(priv->stack); 10840 string_buffer_free(&priv->shader_buffer); 10841 fragment_pipe->free_private(device); 10842 vertex_pipe->vp_free(device); 10843 heap_free(priv); 10844 return E_OUTOFMEMORY; 10845 } 10846 10847 /* Context activation is done by the caller. */ 10848 static void shader_glsl_free(struct wined3d_device *device) 10849 { 10850 struct shader_glsl_priv *priv = device->shader_priv; 10851 10852 wine_rb_destroy(&priv->program_lookup, NULL, NULL); 10853 constant_heap_free(&priv->pconst_heap); 10854 constant_heap_free(&priv->vconst_heap); 10855 heap_free(priv->stack); 10856 string_buffer_list_cleanup(&priv->string_buffers); 10857 string_buffer_free(&priv->shader_buffer); 10858 priv->fragment_pipe->free_private(device); 10859 priv->vertex_pipe->vp_free(device); 10860 10861 heap_free(device->shader_priv); 10862 device->shader_priv = NULL; 10863 } 10864 10865 static BOOL shader_glsl_allocate_context_data(struct wined3d_context *context) 10866 { 10867 struct glsl_context_data *ctx_data; 10868 10869 if (!(ctx_data = heap_alloc_zero(sizeof(*ctx_data)))) 10870 return FALSE; 10871 ctx_data->vertex_color_clamp = GL_FIXED_ONLY_ARB; 10872 context->shader_backend_data = ctx_data; 10873 return TRUE; 10874 } 10875 10876 static void shader_glsl_free_context_data(struct wined3d_context *context) 10877 { 10878 heap_free(context->shader_backend_data); 10879 } 10880 10881 static void shader_glsl_init_context_state(struct wined3d_context *context) 10882 { 10883 const struct wined3d_gl_info *gl_info = context->gl_info; 10884 10885 gl_info->gl_ops.gl.p_glEnable(GL_PROGRAM_POINT_SIZE); 10886 checkGLcall("GL_PROGRAM_POINT_SIZE"); 10887 } 10888 10889 static unsigned int shader_glsl_get_shader_model(const struct wined3d_gl_info *gl_info) 10890 { 10891 BOOL shader_model_4 = gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50) 10892 && gl_info->supported[WINED3D_GL_VERSION_3_2] 10893 && gl_info->supported[ARB_SAMPLER_OBJECTS] 10894 && gl_info->supported[ARB_SHADER_BIT_ENCODING] 10895 && gl_info->supported[ARB_TEXTURE_SWIZZLE]; 10896 10897 if (shader_model_4 10898 && gl_info->supported[ARB_COMPUTE_SHADER] 10899 && gl_info->supported[ARB_CULL_DISTANCE] 10900 && gl_info->supported[ARB_DERIVATIVE_CONTROL] 10901 && gl_info->supported[ARB_DRAW_INDIRECT] 10902 && gl_info->supported[ARB_GPU_SHADER5] 10903 && gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS] 10904 && gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE] 10905 && gl_info->supported[ARB_SHADER_IMAGE_SIZE] 10906 && gl_info->supported[ARB_SHADING_LANGUAGE_PACKING] 10907 && gl_info->supported[ARB_TESSELLATION_SHADER] 10908 && gl_info->supported[ARB_TEXTURE_COMPRESSION_BPTC] 10909 && gl_info->supported[ARB_TEXTURE_GATHER] 10910 && gl_info->supported[ARB_TRANSFORM_FEEDBACK3]) 10911 return 5; 10912 10913 if (shader_model_4) 10914 return 4; 10915 10916 /* Support for texldd and texldl instructions in pixel shaders is required 10917 * for SM3. */ 10918 if (shader_glsl_has_core_grad(gl_info) || gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 10919 return 3; 10920 10921 return 2; 10922 } 10923 10924 static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps) 10925 { 10926 unsigned int shader_model = shader_glsl_get_shader_model(gl_info); 10927 10928 TRACE("Shader model %u.\n", shader_model); 10929 10930 caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model); 10931 caps->hs_version = min(wined3d_settings.max_sm_hs, shader_model); 10932 caps->ds_version = min(wined3d_settings.max_sm_ds, shader_model); 10933 caps->gs_version = min(wined3d_settings.max_sm_gs, shader_model); 10934 caps->ps_version = min(wined3d_settings.max_sm_ps, shader_model); 10935 caps->cs_version = min(wined3d_settings.max_sm_cs, shader_model); 10936 10937 caps->vs_version = gl_info->supported[ARB_VERTEX_SHADER] ? caps->vs_version : 0; 10938 caps->ps_version = gl_info->supported[ARB_FRAGMENT_SHADER] ? caps->ps_version : 0; 10939 10940 caps->vs_uniform_count = min(WINED3D_MAX_VS_CONSTS_F, gl_info->limits.glsl_vs_float_constants); 10941 caps->ps_uniform_count = min(WINED3D_MAX_PS_CONSTS_F, gl_info->limits.glsl_ps_float_constants); 10942 caps->varying_count = gl_info->limits.glsl_varyings; 10943 10944 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the 10945 * Direct3D minimum requirement. 10946 * 10947 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude" 10948 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here? 10949 * 10950 * The problem is that the refrast clamps temporary results in the shader to 10951 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here, 10952 * then applications may miss the clamping behavior. On the other hand, if it is smaller, 10953 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't 10954 * offer a way to query this. 10955 */ 10956 if (shader_model >= 4) 10957 caps->ps_1x_max_value = FLT_MAX; 10958 else 10959 caps->ps_1x_max_value = 1024.0f; 10960 10961 /* Ideally we'd only set caps like sRGB writes here if supported by both 10962 * the shader backend and the fragment pipe, but we can get called before 10963 * shader_glsl_alloc(). */ 10964 caps->wined3d_caps = WINED3D_SHADER_CAP_VS_CLIPPING 10965 | WINED3D_SHADER_CAP_SRGB_WRITE; 10966 } 10967 10968 static BOOL shader_glsl_color_fixup_supported(struct color_fixup_desc fixup) 10969 { 10970 /* We support everything except YUV conversions. */ 10971 return !is_complex_fixup(fixup); 10972 } 10973 10974 static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = 10975 { 10976 /* WINED3DSIH_ABS */ shader_glsl_map2gl, 10977 /* WINED3DSIH_ADD */ shader_glsl_binop, 10978 /* WINED3DSIH_AND */ shader_glsl_binop, 10979 /* WINED3DSIH_ATOMIC_AND */ shader_glsl_atomic, 10980 /* WINED3DSIH_ATOMIC_CMP_STORE */ shader_glsl_atomic, 10981 /* WINED3DSIH_ATOMIC_IADD */ shader_glsl_atomic, 10982 /* WINED3DSIH_ATOMIC_IMAX */ shader_glsl_atomic, 10983 /* WINED3DSIH_ATOMIC_IMIN */ shader_glsl_atomic, 10984 /* WINED3DSIH_ATOMIC_OR */ shader_glsl_atomic, 10985 /* WINED3DSIH_ATOMIC_UMAX */ shader_glsl_atomic, 10986 /* WINED3DSIH_ATOMIC_UMIN */ shader_glsl_atomic, 10987 /* WINED3DSIH_ATOMIC_XOR */ shader_glsl_atomic, 10988 /* WINED3DSIH_BEM */ shader_glsl_bem, 10989 /* WINED3DSIH_BFI */ shader_glsl_bitwise_op, 10990 /* WINED3DSIH_BFREV */ shader_glsl_map2gl, 10991 /* WINED3DSIH_BREAK */ shader_glsl_break, 10992 /* WINED3DSIH_BREAKC */ shader_glsl_breakc, 10993 /* WINED3DSIH_BREAKP */ shader_glsl_conditional_op, 10994 /* WINED3DSIH_BUFINFO */ shader_glsl_bufinfo, 10995 /* WINED3DSIH_CALL */ shader_glsl_call, 10996 /* WINED3DSIH_CALLNZ */ shader_glsl_callnz, 10997 /* WINED3DSIH_CASE */ shader_glsl_case, 10998 /* WINED3DSIH_CMP */ shader_glsl_conditional_move, 10999 /* WINED3DSIH_CND */ shader_glsl_cnd, 11000 /* WINED3DSIH_CONTINUE */ shader_glsl_continue, 11001 /* WINED3DSIH_CONTINUEP */ shader_glsl_conditional_op, 11002 /* WINED3DSIH_COUNTBITS */ shader_glsl_map2gl, 11003 /* WINED3DSIH_CRS */ shader_glsl_cross, 11004 /* WINED3DSIH_CUT */ shader_glsl_cut, 11005 /* WINED3DSIH_CUT_STREAM */ shader_glsl_cut, 11006 /* WINED3DSIH_DCL */ shader_glsl_nop, 11007 /* WINED3DSIH_DCL_CONSTANT_BUFFER */ shader_glsl_nop, 11008 /* WINED3DSIH_DCL_FUNCTION_BODY */ NULL, 11009 /* WINED3DSIH_DCL_FUNCTION_TABLE */ NULL, 11010 /* WINED3DSIH_DCL_GLOBAL_FLAGS */ shader_glsl_nop, 11011 /* WINED3DSIH_DCL_GS_INSTANCES */ shader_glsl_nop, 11012 /* WINED3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT */ shader_glsl_nop, 11013 /* WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ shader_glsl_nop, 11014 /* WINED3DSIH_DCL_HS_MAX_TESSFACTOR */ shader_glsl_nop, 11015 /* WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ shader_glsl_nop, 11016 /* WINED3DSIH_DCL_INDEX_RANGE */ shader_glsl_nop, 11017 /* WINED3DSIH_DCL_INDEXABLE_TEMP */ shader_glsl_nop, 11018 /* WINED3DSIH_DCL_INPUT */ shader_glsl_nop, 11019 /* WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ shader_glsl_nop, 11020 /* WINED3DSIH_DCL_INPUT_PRIMITIVE */ shader_glsl_nop, 11021 /* WINED3DSIH_DCL_INPUT_PS */ shader_glsl_nop, 11022 /* WINED3DSIH_DCL_INPUT_PS_SGV */ NULL, 11023 /* WINED3DSIH_DCL_INPUT_PS_SIV */ NULL, 11024 /* WINED3DSIH_DCL_INPUT_SGV */ shader_glsl_nop, 11025 /* WINED3DSIH_DCL_INPUT_SIV */ shader_glsl_nop, 11026 /* WINED3DSIH_DCL_INTERFACE */ NULL, 11027 /* WINED3DSIH_DCL_OUTPUT */ shader_glsl_nop, 11028 /* WINED3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT */ shader_glsl_nop, 11029 /* WINED3DSIH_DCL_OUTPUT_SIV */ shader_glsl_nop, 11030 /* WINED3DSIH_DCL_OUTPUT_TOPOLOGY */ shader_glsl_nop, 11031 /* WINED3DSIH_DCL_RESOURCE_RAW */ shader_glsl_nop, 11032 /* WINED3DSIH_DCL_RESOURCE_STRUCTURED */ shader_glsl_nop, 11033 /* WINED3DSIH_DCL_SAMPLER */ shader_glsl_nop, 11034 /* WINED3DSIH_DCL_STREAM */ NULL, 11035 /* WINED3DSIH_DCL_TEMPS */ shader_glsl_nop, 11036 /* WINED3DSIH_DCL_TESSELLATOR_DOMAIN */ shader_glsl_nop, 11037 /* WINED3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ shader_glsl_nop, 11038 /* WINED3DSIH_DCL_TESSELLATOR_PARTITIONING */ shader_glsl_nop, 11039 /* WINED3DSIH_DCL_TGSM_RAW */ shader_glsl_nop, 11040 /* WINED3DSIH_DCL_TGSM_STRUCTURED */ shader_glsl_nop, 11041 /* WINED3DSIH_DCL_THREAD_GROUP */ shader_glsl_nop, 11042 /* WINED3DSIH_DCL_UAV_RAW */ shader_glsl_nop, 11043 /* WINED3DSIH_DCL_UAV_STRUCTURED */ shader_glsl_nop, 11044 /* WINED3DSIH_DCL_UAV_TYPED */ shader_glsl_nop, 11045 /* WINED3DSIH_DCL_VERTICES_OUT */ shader_glsl_nop, 11046 /* WINED3DSIH_DEF */ shader_glsl_nop, 11047 /* WINED3DSIH_DEFAULT */ shader_glsl_default, 11048 /* WINED3DSIH_DEFB */ shader_glsl_nop, 11049 /* WINED3DSIH_DEFI */ shader_glsl_nop, 11050 /* WINED3DSIH_DIV */ shader_glsl_binop, 11051 /* WINED3DSIH_DP2 */ shader_glsl_dot, 11052 /* WINED3DSIH_DP2ADD */ shader_glsl_dp2add, 11053 /* WINED3DSIH_DP3 */ shader_glsl_dot, 11054 /* WINED3DSIH_DP4 */ shader_glsl_dot, 11055 /* WINED3DSIH_DST */ shader_glsl_dst, 11056 /* WINED3DSIH_DSX */ shader_glsl_map2gl, 11057 /* WINED3DSIH_DSX_COARSE */ shader_glsl_map2gl, 11058 /* WINED3DSIH_DSX_FINE */ shader_glsl_map2gl, 11059 /* WINED3DSIH_DSY */ shader_glsl_map2gl, 11060 /* WINED3DSIH_DSY_COARSE */ shader_glsl_map2gl, 11061 /* WINED3DSIH_DSY_FINE */ shader_glsl_map2gl, 11062 /* WINED3DSIH_EVAL_SAMPLE_INDEX */ NULL, 11063 /* WINED3DSIH_ELSE */ shader_glsl_else, 11064 /* WINED3DSIH_EMIT */ shader_glsl_emit, 11065 /* WINED3DSIH_EMIT_STREAM */ shader_glsl_emit, 11066 /* WINED3DSIH_ENDIF */ shader_glsl_end, 11067 /* WINED3DSIH_ENDLOOP */ shader_glsl_end, 11068 /* WINED3DSIH_ENDREP */ shader_glsl_end, 11069 /* WINED3DSIH_ENDSWITCH */ shader_glsl_end, 11070 /* WINED3DSIH_EQ */ shader_glsl_relop, 11071 /* WINED3DSIH_EXP */ shader_glsl_scalar_op, 11072 /* WINED3DSIH_EXPP */ shader_glsl_expp, 11073 /* WINED3DSIH_F16TOF32 */ shader_glsl_float16, 11074 /* WINED3DSIH_F32TOF16 */ shader_glsl_float16, 11075 /* WINED3DSIH_FCALL */ NULL, 11076 /* WINED3DSIH_FIRSTBIT_HI */ shader_glsl_map2gl, 11077 /* WINED3DSIH_FIRSTBIT_LO */ shader_glsl_map2gl, 11078 /* WINED3DSIH_FIRSTBIT_SHI */ shader_glsl_map2gl, 11079 /* WINED3DSIH_FRC */ shader_glsl_map2gl, 11080 /* WINED3DSIH_FTOI */ shader_glsl_to_int, 11081 /* WINED3DSIH_FTOU */ shader_glsl_to_uint, 11082 /* WINED3DSIH_GATHER4 */ shader_glsl_gather4, 11083 /* WINED3DSIH_GATHER4_C */ shader_glsl_gather4, 11084 /* WINED3DSIH_GATHER4_PO */ shader_glsl_gather4, 11085 /* WINED3DSIH_GATHER4_PO_C */ shader_glsl_gather4, 11086 /* WINED3DSIH_GE */ shader_glsl_relop, 11087 /* WINED3DSIH_HS_CONTROL_POINT_PHASE */ shader_glsl_nop, 11088 /* WINED3DSIH_HS_DECLS */ shader_glsl_nop, 11089 /* WINED3DSIH_HS_FORK_PHASE */ shader_glsl_nop, 11090 /* WINED3DSIH_HS_JOIN_PHASE */ shader_glsl_nop, 11091 /* WINED3DSIH_IADD */ shader_glsl_binop, 11092 /* WINED3DSIH_IBFE */ shader_glsl_bitwise_op, 11093 /* WINED3DSIH_IEQ */ shader_glsl_relop, 11094 /* WINED3DSIH_IF */ shader_glsl_if, 11095 /* WINED3DSIH_IFC */ shader_glsl_ifc, 11096 /* WINED3DSIH_IGE */ shader_glsl_relop, 11097 /* WINED3DSIH_ILT */ shader_glsl_relop, 11098 /* WINED3DSIH_IMAD */ shader_glsl_mad, 11099 /* WINED3DSIH_IMAX */ shader_glsl_map2gl, 11100 /* WINED3DSIH_IMIN */ shader_glsl_map2gl, 11101 /* WINED3DSIH_IMM_ATOMIC_ALLOC */ shader_glsl_uav_counter, 11102 /* WINED3DSIH_IMM_ATOMIC_AND */ shader_glsl_atomic, 11103 /* WINED3DSIH_IMM_ATOMIC_CMP_EXCH */ shader_glsl_atomic, 11104 /* WINED3DSIH_IMM_ATOMIC_CONSUME */ shader_glsl_uav_counter, 11105 /* WINED3DSIH_IMM_ATOMIC_EXCH */ shader_glsl_atomic, 11106 /* WINED3DSIH_IMM_ATOMIC_IADD */ shader_glsl_atomic, 11107 /* WINED3DSIH_IMM_ATOMIC_IMAX */ shader_glsl_atomic, 11108 /* WINED3DSIH_IMM_ATOMIC_IMIN */ shader_glsl_atomic, 11109 /* WINED3DSIH_IMM_ATOMIC_OR */ shader_glsl_atomic, 11110 /* WINED3DSIH_IMM_ATOMIC_UMAX */ shader_glsl_atomic, 11111 /* WINED3DSIH_IMM_ATOMIC_UMIN */ shader_glsl_atomic, 11112 /* WINED3DSIH_IMM_ATOMIC_XOR */ shader_glsl_atomic, 11113 /* WINED3DSIH_IMUL */ shader_glsl_mul_extended, 11114 /* WINED3DSIH_INE */ shader_glsl_relop, 11115 /* WINED3DSIH_INEG */ shader_glsl_unary_op, 11116 /* WINED3DSIH_ISHL */ shader_glsl_binop, 11117 /* WINED3DSIH_ISHR */ shader_glsl_binop, 11118 /* WINED3DSIH_ITOF */ shader_glsl_to_float, 11119 /* WINED3DSIH_LABEL */ shader_glsl_label, 11120 /* WINED3DSIH_LD */ shader_glsl_ld, 11121 /* WINED3DSIH_LD2DMS */ shader_glsl_ld, 11122 /* WINED3DSIH_LD_RAW */ shader_glsl_ld_raw_structured, 11123 /* WINED3DSIH_LD_STRUCTURED */ shader_glsl_ld_raw_structured, 11124 /* WINED3DSIH_LD_UAV_TYPED */ shader_glsl_ld_uav, 11125 /* WINED3DSIH_LIT */ shader_glsl_lit, 11126 /* WINED3DSIH_LOD */ NULL, 11127 /* WINED3DSIH_LOG */ shader_glsl_scalar_op, 11128 /* WINED3DSIH_LOGP */ shader_glsl_scalar_op, 11129 /* WINED3DSIH_LOOP */ shader_glsl_loop, 11130 /* WINED3DSIH_LRP */ shader_glsl_lrp, 11131 /* WINED3DSIH_LT */ shader_glsl_relop, 11132 /* WINED3DSIH_M3x2 */ shader_glsl_mnxn, 11133 /* WINED3DSIH_M3x3 */ shader_glsl_mnxn, 11134 /* WINED3DSIH_M3x4 */ shader_glsl_mnxn, 11135 /* WINED3DSIH_M4x3 */ shader_glsl_mnxn, 11136 /* WINED3DSIH_M4x4 */ shader_glsl_mnxn, 11137 /* WINED3DSIH_MAD */ shader_glsl_mad, 11138 /* WINED3DSIH_MAX */ shader_glsl_map2gl, 11139 /* WINED3DSIH_MIN */ shader_glsl_map2gl, 11140 /* WINED3DSIH_MOV */ shader_glsl_mov, 11141 /* WINED3DSIH_MOVA */ shader_glsl_mov, 11142 /* WINED3DSIH_MOVC */ shader_glsl_conditional_move, 11143 /* WINED3DSIH_MUL */ shader_glsl_binop, 11144 /* WINED3DSIH_NE */ shader_glsl_relop, 11145 /* WINED3DSIH_NOP */ shader_glsl_nop, 11146 /* WINED3DSIH_NOT */ shader_glsl_unary_op, 11147 /* WINED3DSIH_NRM */ shader_glsl_nrm, 11148 /* WINED3DSIH_OR */ shader_glsl_binop, 11149 /* WINED3DSIH_PHASE */ shader_glsl_nop, 11150 /* WINED3DSIH_POW */ shader_glsl_pow, 11151 /* WINED3DSIH_RCP */ shader_glsl_scalar_op, 11152 /* WINED3DSIH_REP */ shader_glsl_rep, 11153 /* WINED3DSIH_RESINFO */ shader_glsl_resinfo, 11154 /* WINED3DSIH_RET */ shader_glsl_ret, 11155 /* WINED3DSIH_RETP */ shader_glsl_conditional_op, 11156 /* WINED3DSIH_ROUND_NE */ shader_glsl_map2gl, 11157 /* WINED3DSIH_ROUND_NI */ shader_glsl_map2gl, 11158 /* WINED3DSIH_ROUND_PI */ shader_glsl_map2gl, 11159 /* WINED3DSIH_ROUND_Z */ shader_glsl_map2gl, 11160 /* WINED3DSIH_RSQ */ shader_glsl_scalar_op, 11161 /* WINED3DSIH_SAMPLE */ shader_glsl_sample, 11162 /* WINED3DSIH_SAMPLE_B */ shader_glsl_sample, 11163 /* WINED3DSIH_SAMPLE_C */ shader_glsl_sample_c, 11164 /* WINED3DSIH_SAMPLE_C_LZ */ shader_glsl_sample_c, 11165 /* WINED3DSIH_SAMPLE_GRAD */ shader_glsl_sample, 11166 /* WINED3DSIH_SAMPLE_INFO */ shader_glsl_sample_info, 11167 /* WINED3DSIH_SAMPLE_LOD */ shader_glsl_sample, 11168 /* WINED3DSIH_SAMPLE_POS */ NULL, 11169 /* WINED3DSIH_SETP */ NULL, 11170 /* WINED3DSIH_SGE */ shader_glsl_compare, 11171 /* WINED3DSIH_SGN */ shader_glsl_sgn, 11172 /* WINED3DSIH_SINCOS */ shader_glsl_sincos, 11173 /* WINED3DSIH_SLT */ shader_glsl_compare, 11174 /* WINED3DSIH_SQRT */ shader_glsl_map2gl, 11175 /* WINED3DSIH_STORE_RAW */ shader_glsl_store_raw_structured, 11176 /* WINED3DSIH_STORE_STRUCTURED */ shader_glsl_store_raw_structured, 11177 /* WINED3DSIH_STORE_UAV_TYPED */ shader_glsl_store_uav, 11178 /* WINED3DSIH_SUB */ shader_glsl_binop, 11179 /* WINED3DSIH_SWAPC */ shader_glsl_swapc, 11180 /* WINED3DSIH_SWITCH */ shader_glsl_switch, 11181 /* WINED3DSIH_SYNC */ shader_glsl_sync, 11182 /* WINED3DSIH_TEX */ shader_glsl_tex, 11183 /* WINED3DSIH_TEXBEM */ shader_glsl_texbem, 11184 /* WINED3DSIH_TEXBEML */ shader_glsl_texbem, 11185 /* WINED3DSIH_TEXCOORD */ shader_glsl_texcoord, 11186 /* WINED3DSIH_TEXDEPTH */ shader_glsl_texdepth, 11187 /* WINED3DSIH_TEXDP3 */ shader_glsl_texdp3, 11188 /* WINED3DSIH_TEXDP3TEX */ shader_glsl_texdp3tex, 11189 /* WINED3DSIH_TEXKILL */ shader_glsl_texkill, 11190 /* WINED3DSIH_TEXLDD */ shader_glsl_texldd, 11191 /* WINED3DSIH_TEXLDL */ shader_glsl_texldl, 11192 /* WINED3DSIH_TEXM3x2DEPTH */ shader_glsl_texm3x2depth, 11193 /* WINED3DSIH_TEXM3x2PAD */ shader_glsl_texm3x2pad, 11194 /* WINED3DSIH_TEXM3x2TEX */ shader_glsl_texm3x2tex, 11195 /* WINED3DSIH_TEXM3x3 */ shader_glsl_texm3x3, 11196 /* WINED3DSIH_TEXM3x3DIFF */ NULL, 11197 /* WINED3DSIH_TEXM3x3PAD */ shader_glsl_texm3x3pad, 11198 /* WINED3DSIH_TEXM3x3SPEC */ shader_glsl_texm3x3spec, 11199 /* WINED3DSIH_TEXM3x3TEX */ shader_glsl_texm3x3tex, 11200 /* WINED3DSIH_TEXM3x3VSPEC */ shader_glsl_texm3x3vspec, 11201 /* WINED3DSIH_TEXREG2AR */ shader_glsl_texreg2ar, 11202 /* WINED3DSIH_TEXREG2GB */ shader_glsl_texreg2gb, 11203 /* WINED3DSIH_TEXREG2RGB */ shader_glsl_texreg2rgb, 11204 /* WINED3DSIH_UBFE */ shader_glsl_bitwise_op, 11205 /* WINED3DSIH_UDIV */ shader_glsl_udiv, 11206 /* WINED3DSIH_UGE */ shader_glsl_relop, 11207 /* WINED3DSIH_ULT */ shader_glsl_relop, 11208 /* WINED3DSIH_UMAX */ shader_glsl_map2gl, 11209 /* WINED3DSIH_UMIN */ shader_glsl_map2gl, 11210 /* WINED3DSIH_UMUL */ shader_glsl_mul_extended, 11211 /* WINED3DSIH_USHR */ shader_glsl_binop, 11212 /* WINED3DSIH_UTOF */ shader_glsl_to_float, 11213 /* WINED3DSIH_XOR */ shader_glsl_binop, 11214 }; 11215 11216 static void shader_glsl_handle_instruction(const struct wined3d_shader_instruction *ins) { 11217 SHADER_HANDLER hw_fct; 11218 11219 /* Select handler */ 11220 hw_fct = shader_glsl_instruction_handler_table[ins->handler_idx]; 11221 11222 /* Unhandled opcode */ 11223 if (!hw_fct) 11224 { 11225 FIXME("Backend can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 11226 return; 11227 } 11228 hw_fct(ins); 11229 11230 shader_glsl_add_instruction_modifiers(ins); 11231 } 11232 11233 static BOOL shader_glsl_has_ffp_proj_control(void *shader_priv) 11234 { 11235 struct shader_glsl_priv *priv = shader_priv; 11236 11237 return priv->ffp_proj_control; 11238 } 11239 11240 const struct wined3d_shader_backend_ops glsl_shader_backend = 11241 { 11242 shader_glsl_handle_instruction, 11243 shader_glsl_precompile, 11244 shader_glsl_select, 11245 shader_glsl_select_compute, 11246 shader_glsl_disable, 11247 shader_glsl_update_float_vertex_constants, 11248 shader_glsl_update_float_pixel_constants, 11249 shader_glsl_load_constants, 11250 shader_glsl_destroy, 11251 shader_glsl_alloc, 11252 shader_glsl_free, 11253 shader_glsl_allocate_context_data, 11254 shader_glsl_free_context_data, 11255 shader_glsl_init_context_state, 11256 shader_glsl_get_caps, 11257 shader_glsl_color_fixup_supported, 11258 shader_glsl_has_ffp_proj_control, 11259 }; 11260 11261 static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {} 11262 11263 static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps) 11264 { 11265 caps->xyzrhw = TRUE; 11266 caps->emulated_flatshading = !needs_legacy_glsl_syntax(gl_info); 11267 caps->ffp_generic_attributes = TRUE; 11268 caps->max_active_lights = MAX_ACTIVE_LIGHTS; 11269 caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS; 11270 caps->max_vertex_blend_matrix_index = MAX_VERTEX_INDEX_BLENDS - 1; 11271 caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN 11272 | WINED3DVTXPCAPS_MATERIALSOURCE7 11273 | WINED3DVTXPCAPS_VERTEXFOG 11274 | WINED3DVTXPCAPS_DIRECTIONALLIGHTS 11275 | WINED3DVTXPCAPS_POSITIONALLIGHTS 11276 | WINED3DVTXPCAPS_LOCALVIEWER 11277 | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP; 11278 caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 8; /* 8 texture coordinates. */ 11279 caps->max_user_clip_planes = gl_info->limits.user_clip_distances; 11280 caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE; 11281 } 11282 11283 static DWORD glsl_vertex_pipe_vp_get_emul_mask(const struct wined3d_gl_info *gl_info) 11284 { 11285 if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) 11286 return GL_EXT_EMUL_ARB_MULTITEXTURE; 11287 return 0; 11288 } 11289 11290 static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) 11291 { 11292 struct shader_glsl_priv *priv; 11293 11294 if (shader_backend == &glsl_shader_backend) 11295 { 11296 priv = shader_priv; 11297 wine_rb_init(&priv->ffp_vertex_shaders, wined3d_ffp_vertex_program_key_compare); 11298 return priv; 11299 } 11300 11301 FIXME("GLSL vertex pipe without GLSL shader backend not implemented.\n"); 11302 11303 return NULL; 11304 } 11305 11306 static void shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context) 11307 { 11308 struct glsl_ffp_vertex_shader *shader = WINE_RB_ENTRY_VALUE(entry, 11309 struct glsl_ffp_vertex_shader, desc.entry); 11310 struct glsl_shader_prog_link *program, *program2; 11311 struct glsl_ffp_destroy_ctx *ctx = context; 11312 11313 LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs, 11314 struct glsl_shader_prog_link, vs.shader_entry) 11315 { 11316 delete_glsl_program_entry(ctx->priv, ctx->gl_info, program); 11317 } 11318 ctx->gl_info->gl_ops.ext.p_glDeleteShader(shader->id); 11319 heap_free(shader); 11320 } 11321 11322 /* Context activation is done by the caller. */ 11323 static void glsl_vertex_pipe_vp_free(struct wined3d_device *device) 11324 { 11325 struct shader_glsl_priv *priv = device->vertex_priv; 11326 struct glsl_ffp_destroy_ctx ctx; 11327 11328 ctx.priv = priv; 11329 ctx.gl_info = &device->adapter->gl_info; 11330 wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx); 11331 } 11332 11333 static void glsl_vertex_pipe_nop(struct wined3d_context *context, 11334 const struct wined3d_state *state, DWORD state_id) {} 11335 11336 static void glsl_vertex_pipe_shader(struct wined3d_context *context, 11337 const struct wined3d_state *state, DWORD state_id) 11338 { 11339 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11340 } 11341 11342 static void glsl_vertex_pipe_vdecl(struct wined3d_context *context, 11343 const struct wined3d_state *state, DWORD state_id) 11344 { 11345 const struct wined3d_gl_info *gl_info = context->gl_info; 11346 BOOL normal = !!(context->stream_info.use_map & (1u << WINED3D_FFP_NORMAL)); 11347 const BOOL legacy_clip_planes = needs_legacy_glsl_syntax(gl_info); 11348 BOOL transformed = context->stream_info.position_transformed; 11349 BOOL wasrhw = context->last_was_rhw; 11350 unsigned int i; 11351 11352 context->last_was_rhw = transformed; 11353 11354 /* If the vertex declaration contains a transformed position attribute, 11355 * the draw uses the fixed function vertex pipeline regardless of any 11356 * vertex shader set by the application. */ 11357 if (transformed != wasrhw 11358 || context->stream_info.swizzle_map != context->last_swizzle_map) 11359 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11360 11361 context->last_swizzle_map = context->stream_info.swizzle_map; 11362 11363 if (!use_vs(state)) 11364 { 11365 if (context->last_was_vshader) 11366 { 11367 if (legacy_clip_planes) 11368 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 11369 clipplane(context, state, STATE_CLIPPLANE(i)); 11370 else 11371 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11372 } 11373 11374 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 11375 11376 /* Because of settings->texcoords, we have to regenerate the vertex 11377 * shader on a vdecl change if there aren't enough varyings to just 11378 * always output all the texture coordinates. */ 11379 if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info) 11380 || normal != context->last_was_normal) 11381 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11382 11383 if (use_ps(state) 11384 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.major == 1 11385 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3) 11386 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11387 } 11388 else 11389 { 11390 if (!context->last_was_vshader) 11391 { 11392 /* Vertex shader clipping ignores the view matrix. Update all clip planes. */ 11393 if (legacy_clip_planes) 11394 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 11395 clipplane(context, state, STATE_CLIPPLANE(i)); 11396 else 11397 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11398 } 11399 } 11400 11401 context->last_was_vshader = use_vs(state); 11402 context->last_was_normal = normal; 11403 } 11404 11405 static void glsl_vertex_pipe_vs(struct wined3d_context *context, 11406 const struct wined3d_state *state, DWORD state_id) 11407 { 11408 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11409 /* Different vertex shaders potentially require a different vertex attributes setup. */ 11410 if (!isStateDirty(context, STATE_VDECL)) 11411 context_apply_state(context, state, STATE_VDECL); 11412 } 11413 11414 static void glsl_vertex_pipe_hs(struct wined3d_context *context, 11415 const struct wined3d_state *state, DWORD state_id) 11416 { 11417 /* In Direct3D tessellator options (e.g. output primitive type, primitive 11418 * winding) are defined in Hull Shaders, while in GLSL those are 11419 * specified in Tessellation Evaluation Shaders. */ 11420 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; 11421 11422 if (state->shader[WINED3D_SHADER_TYPE_VERTEX]) 11423 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11424 } 11425 11426 static void glsl_vertex_pipe_geometry_shader(struct wined3d_context *context, 11427 const struct wined3d_state *state, DWORD state_id) 11428 { 11429 struct glsl_context_data *ctx_data = context->shader_backend_data; 11430 BOOL rasterization_disabled; 11431 11432 rasterization_disabled = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]); 11433 if (ctx_data->rasterization_disabled != rasterization_disabled) 11434 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11435 ctx_data->rasterization_disabled = rasterization_disabled; 11436 11437 if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) 11438 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; 11439 else if (state->shader[WINED3D_SHADER_TYPE_VERTEX] 11440 && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4) 11441 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11442 } 11443 11444 static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context, 11445 const struct wined3d_state *state, DWORD state_id) 11446 { 11447 if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) 11448 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_GEOMETRY; 11449 else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) 11450 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; 11451 else if (state->shader[WINED3D_SHADER_TYPE_VERTEX] 11452 && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4) 11453 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11454 } 11455 11456 static void glsl_vertex_pipe_world(struct wined3d_context *context, 11457 const struct wined3d_state *state, DWORD state_id) 11458 { 11459 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW; 11460 } 11461 11462 static void glsl_vertex_pipe_vertexblend(struct wined3d_context *context, 11463 const struct wined3d_state *state, DWORD state_id) 11464 { 11465 int i = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)); 11466 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i); 11467 } 11468 11469 static void glsl_vertex_pipe_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 11470 { 11471 const struct wined3d_gl_info *gl_info = context->gl_info; 11472 unsigned int k; 11473 11474 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW 11475 | WINED3D_SHADER_CONST_FFP_LIGHTS 11476 | WINED3D_SHADER_CONST_FFP_VERTEXBLEND; 11477 11478 if (needs_legacy_glsl_syntax(gl_info)) 11479 { 11480 for (k = 0; k < gl_info->limits.user_clip_distances; ++k) 11481 { 11482 if (!isStateDirty(context, STATE_CLIPPLANE(k))) 11483 clipplane(context, state, STATE_CLIPPLANE(k)); 11484 } 11485 } 11486 else 11487 { 11488 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11489 } 11490 } 11491 11492 static void glsl_vertex_pipe_projection(struct wined3d_context *context, 11493 const struct wined3d_state *state, DWORD state_id) 11494 { 11495 /* Table fog behavior depends on the projection matrix. */ 11496 if (state->render_states[WINED3D_RS_FOGENABLE] 11497 && state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE) 11498 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11499 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PROJ; 11500 } 11501 11502 static void glsl_vertex_pipe_viewport(struct wined3d_context *context, 11503 const struct wined3d_state *state, DWORD state_id) 11504 { 11505 if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION))) 11506 glsl_vertex_pipe_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); 11507 if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)) 11508 && state->render_states[WINED3D_RS_POINTSCALEENABLE]) 11509 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 11510 context->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 11511 } 11512 11513 static void glsl_vertex_pipe_texmatrix(struct wined3d_context *context, 11514 const struct wined3d_state *state, DWORD state_id) 11515 { 11516 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 11517 } 11518 11519 static void glsl_vertex_pipe_texmatrix_np2(struct wined3d_context *context, 11520 const struct wined3d_state *state, DWORD state_id) 11521 { 11522 DWORD sampler = state_id - STATE_SAMPLER(0); 11523 const struct wined3d_texture *texture = state->textures[sampler]; 11524 BOOL np2; 11525 11526 if (!texture) 11527 return; 11528 11529 if (sampler >= MAX_TEXTURES) 11530 return; 11531 11532 if ((np2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT)) 11533 || context->lastWasPow2Texture & (1u << sampler)) 11534 { 11535 if (np2) 11536 context->lastWasPow2Texture |= 1u << sampler; 11537 else 11538 context->lastWasPow2Texture &= ~(1u << sampler); 11539 11540 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 11541 } 11542 } 11543 11544 static void glsl_vertex_pipe_material(struct wined3d_context *context, 11545 const struct wined3d_state *state, DWORD state_id) 11546 { 11547 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MATERIAL; 11548 } 11549 11550 static void glsl_vertex_pipe_light(struct wined3d_context *context, 11551 const struct wined3d_state *state, DWORD state_id) 11552 { 11553 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_LIGHTS; 11554 } 11555 11556 static void glsl_vertex_pipe_pointsize(struct wined3d_context *context, 11557 const struct wined3d_state *state, DWORD state_id) 11558 { 11559 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 11560 } 11561 11562 static void glsl_vertex_pipe_pointscale(struct wined3d_context *context, 11563 const struct wined3d_state *state, DWORD state_id) 11564 { 11565 if (!use_vs(state)) 11566 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 11567 } 11568 11569 static void glsl_vertex_pointsprite_core(struct wined3d_context *context, 11570 const struct wined3d_state *state, DWORD state_id) 11571 { 11572 static unsigned int once; 11573 11574 if (state->gl_primitive_type == GL_POINTS && !state->render_states[WINED3D_RS_POINTSPRITEENABLE] && !once++) 11575 FIXME("Non-point sprite points not supported in core profile.\n"); 11576 } 11577 11578 static void glsl_vertex_pipe_shademode(struct wined3d_context *context, 11579 const struct wined3d_state *state, DWORD state_id) 11580 { 11581 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11582 } 11583 11584 static void glsl_vertex_pipe_clip_plane(struct wined3d_context *context, 11585 const struct wined3d_state *state, DWORD state_id) 11586 { 11587 const struct wined3d_gl_info *gl_info = context->gl_info; 11588 UINT index = state_id - STATE_CLIPPLANE(0); 11589 11590 if (index >= gl_info->limits.user_clip_distances) 11591 return; 11592 11593 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11594 } 11595 11596 static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = 11597 { 11598 {STATE_VDECL, {STATE_VDECL, glsl_vertex_pipe_vdecl }, WINED3D_GL_EXT_NONE }, 11599 {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_vertex_pipe_vs }, WINED3D_GL_EXT_NONE }, 11600 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), glsl_vertex_pipe_hs }, WINED3D_GL_EXT_NONE }, 11601 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), glsl_vertex_pipe_geometry_shader}, WINED3D_GL_EXT_NONE }, 11602 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_vertex_pipe_pixel_shader}, WINED3D_GL_EXT_NONE }, 11603 {STATE_MATERIAL, {STATE_RENDER(WINED3D_RS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11604 {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_vertex_pipe_material}, WINED3D_GL_EXT_NONE }, 11605 /* Clip planes */ 11606 {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11607 {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE }, 11608 {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11609 {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE }, 11610 {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11611 {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE }, 11612 {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11613 {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE }, 11614 {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11615 {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE }, 11616 {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11617 {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE }, 11618 {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11619 {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE }, 11620 {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11621 {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE }, 11622 /* Lights */ 11623 {STATE_LIGHT_TYPE, {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11624 {STATE_ACTIVELIGHT(0), {STATE_ACTIVELIGHT(0), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11625 {STATE_ACTIVELIGHT(1), {STATE_ACTIVELIGHT(1), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11626 {STATE_ACTIVELIGHT(2), {STATE_ACTIVELIGHT(2), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11627 {STATE_ACTIVELIGHT(3), {STATE_ACTIVELIGHT(3), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11628 {STATE_ACTIVELIGHT(4), {STATE_ACTIVELIGHT(4), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11629 {STATE_ACTIVELIGHT(5), {STATE_ACTIVELIGHT(5), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11630 {STATE_ACTIVELIGHT(6), {STATE_ACTIVELIGHT(6), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11631 {STATE_ACTIVELIGHT(7), {STATE_ACTIVELIGHT(7), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11632 /* Viewport */ 11633 {STATE_VIEWPORT, {STATE_VIEWPORT, glsl_vertex_pipe_viewport}, WINED3D_GL_EXT_NONE }, 11634 /* Transform states */ 11635 {STATE_TRANSFORM(WINED3D_TS_VIEW), {STATE_TRANSFORM(WINED3D_TS_VIEW), glsl_vertex_pipe_view }, WINED3D_GL_EXT_NONE }, 11636 {STATE_TRANSFORM(WINED3D_TS_PROJECTION), {STATE_TRANSFORM(WINED3D_TS_PROJECTION), glsl_vertex_pipe_projection}, WINED3D_GL_EXT_NONE }, 11637 {STATE_TRANSFORM(WINED3D_TS_TEXTURE0), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11638 {STATE_TRANSFORM(WINED3D_TS_TEXTURE1), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11639 {STATE_TRANSFORM(WINED3D_TS_TEXTURE2), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11640 {STATE_TRANSFORM(WINED3D_TS_TEXTURE3), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11641 {STATE_TRANSFORM(WINED3D_TS_TEXTURE4), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11642 {STATE_TRANSFORM(WINED3D_TS_TEXTURE5), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11643 {STATE_TRANSFORM(WINED3D_TS_TEXTURE6), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11644 {STATE_TRANSFORM(WINED3D_TS_TEXTURE7), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11645 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), glsl_vertex_pipe_world }, WINED3D_GL_EXT_NONE }, 11646 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11647 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11648 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11649 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11650 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11651 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11652 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11653 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11654 {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11655 {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11656 {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11657 {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11658 {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11659 {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11660 {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11661 {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11662 {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11663 {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11664 {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11665 {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11666 {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11667 {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11668 {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11669 {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11670 /* Fog */ 11671 {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, 11672 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11673 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11674 {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11675 {STATE_RENDER(WINED3D_RS_CLIPPING), {STATE_RENDER(WINED3D_RS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, 11676 {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE), {STATE_RENDER(WINED3D_RS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE }, 11677 {STATE_RENDER(WINED3D_RS_LIGHTING), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11678 {STATE_RENDER(WINED3D_RS_AMBIENT), {STATE_RENDER(WINED3D_RS_AMBIENT), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11679 {STATE_RENDER(WINED3D_RS_COLORVERTEX), {STATE_RENDER(WINED3D_RS_COLORVERTEX), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, 11680 {STATE_RENDER(WINED3D_RS_LOCALVIEWER), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11681 {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11682 {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11683 {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11684 {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11685 {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11686 {STATE_RENDER(WINED3D_RS_VERTEXBLEND), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11687 {STATE_RENDER(WINED3D_RS_POINTSIZE), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, 11688 {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), glsl_vertex_pipe_pointsize}, WINED3D_GL_EXT_NONE }, 11689 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, 11690 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_LEGACY_CONTEXT }, 11691 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_vertex_pointsprite_core}, WINED3D_GL_EXT_NONE }, 11692 {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), glsl_vertex_pipe_pointscale}, WINED3D_GL_EXT_NONE }, 11693 {STATE_RENDER(WINED3D_RS_POINTSCALE_A), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11694 {STATE_RENDER(WINED3D_RS_POINTSCALE_B), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11695 {STATE_RENDER(WINED3D_RS_POINTSCALE_C), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11696 {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, 11697 {STATE_RENDER(WINED3D_RS_TWEENFACTOR), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11698 {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11699 /* NP2 texture matrix fixups. They are not needed if 11700 * GL_ARB_texture_non_power_of_two is supported. Otherwise, register 11701 * glsl_vertex_pipe_texmatrix(), which takes care of updating the texture 11702 * matrix. */ 11703 {STATE_SAMPLER(0), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11704 {STATE_SAMPLER(0), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11705 {STATE_SAMPLER(0), {STATE_SAMPLER(0), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11706 {STATE_SAMPLER(1), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11707 {STATE_SAMPLER(1), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11708 {STATE_SAMPLER(1), {STATE_SAMPLER(1), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11709 {STATE_SAMPLER(2), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11710 {STATE_SAMPLER(2), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11711 {STATE_SAMPLER(2), {STATE_SAMPLER(2), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11712 {STATE_SAMPLER(3), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11713 {STATE_SAMPLER(3), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11714 {STATE_SAMPLER(3), {STATE_SAMPLER(3), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11715 {STATE_SAMPLER(4), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11716 {STATE_SAMPLER(4), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11717 {STATE_SAMPLER(4), {STATE_SAMPLER(4), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11718 {STATE_SAMPLER(5), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11719 {STATE_SAMPLER(5), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11720 {STATE_SAMPLER(5), {STATE_SAMPLER(5), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11721 {STATE_SAMPLER(6), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11722 {STATE_SAMPLER(6), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11723 {STATE_SAMPLER(6), {STATE_SAMPLER(6), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11724 {STATE_SAMPLER(7), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11725 {STATE_SAMPLER(7), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11726 {STATE_SAMPLER(7), {STATE_SAMPLER(7), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11727 {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, 11728 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_vertex_pipe_shademode}, WINED3D_GLSL_130 }, 11729 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_vertex_pipe_nop }, WINED3D_GL_EXT_NONE }, 11730 {0 /* Terminate */, {0, NULL }, WINED3D_GL_EXT_NONE }, 11731 }; 11732 11733 /* TODO: 11734 * - Implement vertex tweening. */ 11735 const struct wined3d_vertex_pipe_ops glsl_vertex_pipe = 11736 { 11737 glsl_vertex_pipe_vp_enable, 11738 glsl_vertex_pipe_vp_get_caps, 11739 glsl_vertex_pipe_vp_get_emul_mask, 11740 glsl_vertex_pipe_vp_alloc, 11741 glsl_vertex_pipe_vp_free, 11742 glsl_vertex_pipe_vp_states, 11743 }; 11744 11745 static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable) 11746 { 11747 /* Nothing to do. */ 11748 } 11749 11750 static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) 11751 { 11752 caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL 11753 | WINED3D_FRAGMENT_CAP_SRGB_WRITE 11754 | WINED3D_FRAGMENT_CAP_COLOR_KEY; 11755 caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP 11756 | WINED3DPMISCCAPS_PERSTAGECONSTANT; 11757 caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE 11758 | WINED3DTEXOPCAPS_SELECTARG1 11759 | WINED3DTEXOPCAPS_SELECTARG2 11760 | WINED3DTEXOPCAPS_MODULATE4X 11761 | WINED3DTEXOPCAPS_MODULATE2X 11762 | WINED3DTEXOPCAPS_MODULATE 11763 | WINED3DTEXOPCAPS_ADDSIGNED2X 11764 | WINED3DTEXOPCAPS_ADDSIGNED 11765 | WINED3DTEXOPCAPS_ADD 11766 | WINED3DTEXOPCAPS_SUBTRACT 11767 | WINED3DTEXOPCAPS_ADDSMOOTH 11768 | WINED3DTEXOPCAPS_BLENDCURRENTALPHA 11769 | WINED3DTEXOPCAPS_BLENDFACTORALPHA 11770 | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA 11771 | WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA 11772 | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM 11773 | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 11774 | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 11775 | WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 11776 | WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 11777 | WINED3DTEXOPCAPS_DOTPRODUCT3 11778 | WINED3DTEXOPCAPS_MULTIPLYADD 11779 | WINED3DTEXOPCAPS_LERP 11780 | WINED3DTEXOPCAPS_BUMPENVMAP 11781 | WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE; 11782 caps->MaxTextureBlendStages = MAX_TEXTURES; 11783 caps->MaxSimultaneousTextures = min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_TEXTURES); 11784 } 11785 11786 static DWORD glsl_fragment_pipe_get_emul_mask(const struct wined3d_gl_info *gl_info) 11787 { 11788 if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) 11789 return GL_EXT_EMUL_ARB_MULTITEXTURE; 11790 return 0; 11791 } 11792 11793 static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) 11794 { 11795 struct shader_glsl_priv *priv; 11796 11797 if (shader_backend == &glsl_shader_backend) 11798 { 11799 priv = shader_priv; 11800 wine_rb_init(&priv->ffp_fragment_shaders, wined3d_ffp_frag_program_key_compare); 11801 return priv; 11802 } 11803 11804 FIXME("GLSL fragment pipe without GLSL shader backend not implemented.\n"); 11805 11806 return NULL; 11807 } 11808 11809 static void shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry *entry, void *context) 11810 { 11811 struct glsl_ffp_fragment_shader *shader = WINE_RB_ENTRY_VALUE(entry, 11812 struct glsl_ffp_fragment_shader, entry.entry); 11813 struct glsl_shader_prog_link *program, *program2; 11814 struct glsl_ffp_destroy_ctx *ctx = context; 11815 11816 LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs, 11817 struct glsl_shader_prog_link, ps.shader_entry) 11818 { 11819 delete_glsl_program_entry(ctx->priv, ctx->gl_info, program); 11820 } 11821 ctx->gl_info->gl_ops.ext.p_glDeleteShader(shader->id); 11822 heap_free(shader); 11823 } 11824 11825 /* Context activation is done by the caller. */ 11826 static void glsl_fragment_pipe_free(struct wined3d_device *device) 11827 { 11828 struct shader_glsl_priv *priv = device->fragment_priv; 11829 struct glsl_ffp_destroy_ctx ctx; 11830 11831 ctx.priv = priv; 11832 ctx.gl_info = &device->adapter->gl_info; 11833 wine_rb_destroy(&priv->ffp_fragment_shaders, shader_glsl_free_ffp_fragment_shader, &ctx); 11834 } 11835 11836 static void glsl_fragment_pipe_shader(struct wined3d_context *context, 11837 const struct wined3d_state *state, DWORD state_id) 11838 { 11839 context->last_was_pshader = use_ps(state); 11840 11841 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11842 } 11843 11844 static void glsl_fragment_pipe_fogparams(struct wined3d_context *context, 11845 const struct wined3d_state *state, DWORD state_id) 11846 { 11847 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG; 11848 } 11849 11850 static void glsl_fragment_pipe_fog(struct wined3d_context *context, 11851 const struct wined3d_state *state, DWORD state_id) 11852 { 11853 BOOL use_vshader = use_vs(state); 11854 enum fogsource new_source; 11855 DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART]; 11856 DWORD fogend = state->render_states[WINED3D_RS_FOGEND]; 11857 11858 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11859 11860 if (!state->render_states[WINED3D_RS_FOGENABLE]) 11861 return; 11862 11863 if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE) 11864 { 11865 if (use_vshader) 11866 new_source = FOGSOURCE_VS; 11867 else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->stream_info.position_transformed) 11868 new_source = FOGSOURCE_COORD; 11869 else 11870 new_source = FOGSOURCE_FFP; 11871 } 11872 else 11873 { 11874 new_source = FOGSOURCE_FFP; 11875 } 11876 11877 if (new_source != context->fog_source || fogstart == fogend) 11878 { 11879 context->fog_source = new_source; 11880 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG; 11881 } 11882 } 11883 11884 static void glsl_fragment_pipe_vdecl(struct wined3d_context *context, 11885 const struct wined3d_state *state, DWORD state_id) 11886 { 11887 /* Because of settings->texcoords_initialized and args->texcoords_initialized. */ 11888 if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info)) 11889 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11890 11891 if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_FOGENABLE))) 11892 glsl_fragment_pipe_fog(context, state, state_id); 11893 } 11894 11895 static void glsl_fragment_pipe_vs(struct wined3d_context *context, 11896 const struct wined3d_state *state, DWORD state_id) 11897 { 11898 /* Because of settings->texcoords_initialized and args->texcoords_initialized. */ 11899 if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info)) 11900 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11901 } 11902 11903 static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context, 11904 const struct wined3d_state *state, DWORD state_id) 11905 { 11906 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11907 } 11908 11909 static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context, 11910 const struct wined3d_state *state, DWORD state_id) 11911 { 11912 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS; 11913 } 11914 11915 static void glsl_fragment_pipe_alpha_test_func(struct wined3d_context *context, 11916 const struct wined3d_state *state, DWORD state_id) 11917 { 11918 const struct wined3d_gl_info *gl_info = context->gl_info; 11919 GLint func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]); 11920 float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f; 11921 11922 if (func) 11923 { 11924 gl_info->gl_ops.gl.p_glAlphaFunc(func, ref); 11925 checkGLcall("glAlphaFunc"); 11926 } 11927 } 11928 11929 static void glsl_fragment_pipe_core_alpha_test(struct wined3d_context *context, 11930 const struct wined3d_state *state, DWORD state_id) 11931 { 11932 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11933 } 11934 11935 static void glsl_fragment_pipe_alpha_test(struct wined3d_context *context, 11936 const struct wined3d_state *state, DWORD state_id) 11937 { 11938 const struct wined3d_gl_info *gl_info = context->gl_info; 11939 11940 if (state->render_states[WINED3D_RS_ALPHATESTENABLE]) 11941 { 11942 gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST); 11943 checkGLcall("glEnable(GL_ALPHA_TEST)"); 11944 } 11945 else 11946 { 11947 gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); 11948 checkGLcall("glDisable(GL_ALPHA_TEST)"); 11949 } 11950 } 11951 11952 static void glsl_fragment_pipe_core_alpha_test_ref(struct wined3d_context *context, 11953 const struct wined3d_state *state, DWORD state_id) 11954 { 11955 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST; 11956 } 11957 11958 static void glsl_fragment_pipe_color_key(struct wined3d_context *context, 11959 const struct wined3d_state *state, DWORD state_id) 11960 { 11961 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY; 11962 } 11963 11964 static void glsl_fragment_pipe_shademode(struct wined3d_context *context, 11965 const struct wined3d_state *state, DWORD state_id) 11966 { 11967 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11968 } 11969 11970 static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] = 11971 { 11972 {STATE_VDECL, {STATE_VDECL, glsl_fragment_pipe_vdecl }, WINED3D_GL_EXT_NONE }, 11973 {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_fragment_pipe_vs }, WINED3D_GL_EXT_NONE }, 11974 {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11975 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11976 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11977 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11978 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11979 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11980 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11981 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11982 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11983 {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11984 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11985 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11986 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11987 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11988 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11989 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11990 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11991 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11992 {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11993 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11994 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11995 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11996 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11997 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11998 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11999 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12000 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12001 {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12002 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12003 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12004 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12005 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12006 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12007 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12008 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12009 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12010 {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12011 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12012 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12013 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12014 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12015 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12016 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12017 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12018 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12019 {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12020 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12021 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12022 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12023 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12024 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12025 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12026 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12027 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12028 {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12029 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12030 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12031 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12032 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12033 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12034 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12035 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12036 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12037 {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12038 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12039 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12040 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12041 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12042 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12043 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12044 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12045 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12046 {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12047 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE }, 12048 {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), glsl_fragment_pipe_alpha_test_func }, WINED3D_GL_LEGACY_CONTEXT}, 12049 {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, 12050 {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), NULL }, WINED3D_GL_LEGACY_CONTEXT}, 12051 {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAREF), glsl_fragment_pipe_core_alpha_test_ref }, WINED3D_GL_EXT_NONE }, 12052 {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_alpha_test }, WINED3D_GL_LEGACY_CONTEXT}, 12053 {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_core_alpha_test }, WINED3D_GL_EXT_NONE }, 12054 {STATE_RENDER(WINED3D_RS_COLORKEYENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12055 {STATE_COLOR_KEY, { STATE_COLOR_KEY, glsl_fragment_pipe_color_key }, WINED3D_GL_EXT_NONE }, 12056 {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_fragment_pipe_fog }, WINED3D_GL_EXT_NONE }, 12057 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 12058 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 12059 {STATE_RENDER(WINED3D_RS_FOGSTART), {STATE_RENDER(WINED3D_RS_FOGSTART), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE }, 12060 {STATE_RENDER(WINED3D_RS_FOGEND), {STATE_RENDER(WINED3D_RS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, 12061 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), state_srgbwrite }, ARB_FRAMEBUFFER_SRGB}, 12062 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 12063 {STATE_RENDER(WINED3D_RS_FOGCOLOR), {STATE_RENDER(WINED3D_RS_FOGCOLOR), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE }, 12064 {STATE_RENDER(WINED3D_RS_FOGDENSITY), {STATE_RENDER(WINED3D_RS_FOGDENSITY), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE }, 12065 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_fragment_pipe_shader }, ARB_POINT_SPRITE }, 12066 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_fragment_pipe_shader }, WINED3D_GL_VERSION_2_0}, 12067 {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 }, 12068 {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 }, 12069 {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 }, 12070 {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 }, 12071 {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 }, 12072 {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 }, 12073 {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 }, 12074 {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 }, 12075 {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12076 {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12077 {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12078 {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12079 {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12080 {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12081 {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12082 {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12083 {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 12084 {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE }, 12085 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_fragment_pipe_shademode }, WINED3D_GLSL_130 }, 12086 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE }, 12087 {0 /* Terminate */, {0, 0 }, WINED3D_GL_EXT_NONE }, 12088 }; 12089 12090 static BOOL glsl_fragment_pipe_alloc_context_data(struct wined3d_context *context) 12091 { 12092 return TRUE; 12093 } 12094 12095 static void glsl_fragment_pipe_free_context_data(struct wined3d_context *context) 12096 { 12097 } 12098 12099 const struct fragment_pipeline glsl_fragment_pipe = 12100 { 12101 glsl_fragment_pipe_enable, 12102 glsl_fragment_pipe_get_caps, 12103 glsl_fragment_pipe_get_emul_mask, 12104 glsl_fragment_pipe_alloc, 12105 glsl_fragment_pipe_free, 12106 glsl_fragment_pipe_alloc_context_data, 12107 glsl_fragment_pipe_free_context_data, 12108 shader_glsl_color_fixup_supported, 12109 glsl_fragment_pipe_state_template, 12110 }; 12111 12112 struct glsl_blitter_args 12113 { 12114 GLenum texture_type; 12115 struct color_fixup_desc fixup; 12116 unsigned short padding; 12117 }; 12118 12119 struct glsl_blitter_program 12120 { 12121 struct wine_rb_entry entry; 12122 struct glsl_blitter_args args; 12123 GLuint id; 12124 }; 12125 12126 struct wined3d_glsl_blitter 12127 { 12128 struct wined3d_blitter blitter; 12129 struct wined3d_string_buffer_list string_buffers; 12130 struct wine_rb_tree programs; 12131 GLuint palette_texture; 12132 }; 12133 12134 static int glsl_blitter_args_compare(const void *key, const struct wine_rb_entry *entry) 12135 { 12136 const struct glsl_blitter_args *a = key; 12137 const struct glsl_blitter_args *b = &WINE_RB_ENTRY_VALUE(entry, const struct glsl_blitter_program, entry)->args; 12138 12139 return memcmp(a, b, sizeof(*a)); 12140 } 12141 12142 /* Context activation is done by the caller. */ 12143 static void glsl_free_blitter_program(struct wine_rb_entry *entry, void *ctx) 12144 { 12145 struct glsl_blitter_program *program = WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry); 12146 struct wined3d_context *context = ctx; 12147 const struct wined3d_gl_info *gl_info = context->gl_info; 12148 12149 GL_EXTCALL(glDeleteProgram(program->id)); 12150 checkGLcall("glDeleteProgram()"); 12151 heap_free(program); 12152 } 12153 12154 /* Context activation is done by the caller. */ 12155 static void glsl_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context) 12156 { 12157 const struct wined3d_gl_info *gl_info = context->gl_info; 12158 struct wined3d_glsl_blitter *glsl_blitter; 12159 struct wined3d_blitter *next; 12160 12161 if ((next = blitter->next)) 12162 next->ops->blitter_destroy(next, context); 12163 12164 glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter); 12165 12166 if (glsl_blitter->palette_texture) 12167 gl_info->gl_ops.gl.p_glDeleteTextures(1, &glsl_blitter->palette_texture); 12168 12169 wine_rb_destroy(&glsl_blitter->programs, glsl_free_blitter_program, context); 12170 string_buffer_list_cleanup(&glsl_blitter->string_buffers); 12171 12172 heap_free(glsl_blitter); 12173 } 12174 12175 static void glsl_blitter_generate_p8_shader(struct wined3d_string_buffer *buffer, 12176 const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, 12177 const char *output, const char *tex_type, const char *swizzle) 12178 { 12179 shader_addline(buffer, "uniform sampler1D sampler_palette;\n"); 12180 shader_addline(buffer, "\nvoid main()\n{\n"); 12181 /* The alpha-component contains the palette index. */ 12182 shader_addline(buffer, " float index = texture%s(sampler, out_texcoord.%s).%c;\n", 12183 needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle, 12184 gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x'); 12185 /* Scale the index by 255/256 and add a bias of 0.5 in order to sample in 12186 * the middle. */ 12187 shader_addline(buffer, " index = (index * 255.0 + 0.5) / 256.0;\n"); 12188 shader_addline(buffer, " %s = texture%s(sampler_palette, index);\n", 12189 output, needs_legacy_glsl_syntax(gl_info) ? "1D" : ""); 12190 shader_addline(buffer, "}\n"); 12191 } 12192 12193 static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer, 12194 const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, 12195 const char *tex_type) 12196 { 12197 enum complex_fixup complex_fixup = get_complex_fixup(args->fixup); 12198 char chroma, luminance; 12199 const char *tex; 12200 12201 /* The YUY2 and UYVY formats contain two pixels packed into a 32 bit 12202 * macropixel, giving effectively 16 bits per pixel. The color consists of 12203 * a luminance(Y) and two chroma(U and V) values. Each macropixel has two 12204 * luminance values, one for each single pixel it contains, and one U and 12205 * one V value shared between both pixels. 12206 * 12207 * The data is loaded into an A8L8 texture. With YUY2, the luminance 12208 * component contains the luminance and alpha the chroma. With UYVY it is 12209 * vice versa. Thus take the format into account when generating the read 12210 * swizzles 12211 * 12212 * Reading the Y value is straightforward - just sample the texture. The 12213 * hardware takes care of filtering in the horizontal and vertical 12214 * direction. 12215 * 12216 * Reading the U and V values is harder. We have to avoid filtering 12217 * horizontally, because that would mix the U and V values of one pixel or 12218 * two adjacent pixels. Thus floor the texture coordinate and add 0.5 to 12219 * get an unfiltered read, regardless of the filtering setting. Vertical 12220 * filtering works automatically though - the U and V values of two rows 12221 * are mixed nicely. 12222 * 12223 * Apart of avoiding filtering issues, the code has to know which value it 12224 * just read, and where it can find the other one. To determine this, it 12225 * checks if it sampled an even or odd pixel, and shifts the 2nd read 12226 * accordingly. 12227 * 12228 * Handling horizontal filtering of U and V values requires reading a 2nd 12229 * pair of pixels, extracting U and V and mixing them. This is not 12230 * implemented yet. 12231 * 12232 * An alternative implementation idea is to load the texture as A8R8G8B8 12233 * texture, with width / 2. This way one read gives all 3 values, finding 12234 * U and V is easy in an unfiltered situation. Finding the luminance on 12235 * the other hand requires finding out if it is an odd or even pixel. The 12236 * real drawback of this approach is filtering. This would have to be 12237 * emulated completely in the shader, reading up two 2 packed pixels in up 12238 * to 2 rows and interpolating both horizontally and vertically. Beyond 12239 * that it would require adjustments to the texture handling code to deal 12240 * with the width scaling. */ 12241 12242 if (complex_fixup == COMPLEX_FIXUP_UYVY) 12243 { 12244 chroma = 'x'; 12245 luminance = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'y'; 12246 } 12247 else 12248 { 12249 chroma = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'y'; 12250 luminance = 'x'; 12251 } 12252 12253 tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : ""; 12254 12255 /* First we have to read the chroma values. This means we need at least 12256 * two pixels (no filtering), or 4 pixels (with filtering). To get the 12257 * unmodified chroma, we have to rid ourselves of the filtering when we 12258 * sample the texture. */ 12259 shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); 12260 /* We must not allow filtering between pixel x and x+1, this would mix U 12261 * and V. Vertical filtering is ok. However, bear in mind that the pixel 12262 * center is at 0.5, so add 0.5. */ 12263 shader_addline(buffer, " texcoord.x = (floor(texcoord.x * size.x) + 0.5) / size.x;\n"); 12264 shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, chroma); 12265 12266 /* Multiply the x coordinate by 0.5 and get the fraction. This gives 0.25 12267 * and 0.75 for the even and odd pixels respectively. */ 12268 /* Put the value into either of the chroma values. */ 12269 shader_addline(buffer, " bool even = fract(texcoord.x * size.x * 0.5) < 0.5;\n"); 12270 shader_addline(buffer, " if (even)\n"); 12271 shader_addline(buffer, " chroma.y = luminance;\n"); 12272 shader_addline(buffer, " else\n"); 12273 shader_addline(buffer, " chroma.x = luminance;\n"); 12274 12275 /* Sample pixel 2. If we read an even pixel, sample the pixel right to the 12276 * current one. Otherwise, sample the left pixel. */ 12277 shader_addline(buffer, " texcoord.x += even ? 1.0 / size.x : -1.0 / size.x;\n"); 12278 shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, chroma); 12279 12280 /* Put the value into the other chroma. */ 12281 shader_addline(buffer, " if (even)\n"); 12282 shader_addline(buffer, " chroma.x = luminance;\n"); 12283 shader_addline(buffer, " else\n"); 12284 shader_addline(buffer, " chroma.y = luminance;\n"); 12285 12286 /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of 12287 * the current one and lerp the two U and V values. */ 12288 12289 /* This gives the correctly filtered luminance value. */ 12290 shader_addline(buffer, " luminance = texture%s(sampler, out_texcoord.xy).%c;\n", tex, luminance); 12291 } 12292 12293 static void gen_yv12_read(struct wined3d_string_buffer *buffer, 12294 const struct wined3d_gl_info *gl_info, const char *tex_type) 12295 { 12296 char component = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x'; 12297 const char *tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : ""; 12298 12299 /* YV12 surfaces contain a WxH sized luminance plane, followed by a 12300 * (W/2)x(H/2) V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So 12301 * the effective bitdepth is 12 bits per pixel. Since the U and V planes 12302 * have only half the pitch of the luminance plane, the packing into the 12303 * gl texture is a bit unfortunate. If the whole texture is interpreted as 12304 * luminance data it looks approximately like this: 12305 * 12306 * +----------------------------------+---- 12307 * | | 12308 * | | 12309 * | | 12310 * | | 12311 * | | 2 12312 * | LUMINANCE | - 12313 * | | 3 12314 * | | 12315 * | | 12316 * | | 12317 * | | 12318 * +----------------+-----------------+---- 12319 * | | | 12320 * | V even rows | V odd rows | 12321 * | | | 1 12322 * +----------------+------------------ - 12323 * | | | 3 12324 * | U even rows | U odd rows | 12325 * | | | 12326 * +----------------+-----------------+---- 12327 * | | | 12328 * | 0.5 | 0.5 | 12329 * 12330 * So it appears as if there are 4 chroma images, but in fact the odd rows 12331 * in the chroma images are in the same row as the even ones. So it is 12332 * kinda tricky to read. */ 12333 12334 /* First sample the chroma values. */ 12335 shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); 12336 /* The chroma planes have only half the width. */ 12337 shader_addline(buffer, " texcoord.x *= 0.5;\n"); 12338 12339 /* The first value is between 2/3 and 5/6 of the texture's height, so 12340 * scale+bias the coordinate. Also read the right side of the image when 12341 * reading odd lines. 12342 * 12343 * Don't forget to clamp the y values in into the range, otherwise we'll 12344 * get filtering bleeding. */ 12345 12346 /* Read odd lines from the right side (add 0.5 to the x coordinate). */ 12347 shader_addline(buffer, " if (fract(floor(texcoord.y * size.y) * 0.5 + 1.0 / 6.0) >= 0.5)\n"); 12348 shader_addline(buffer, " texcoord.x += 0.5;\n"); 12349 12350 /* Clamp, keep the half pixel origin in mind. */ 12351 shader_addline(buffer, " texcoord.y = clamp(2.0 / 3.0 + texcoord.y / 6.0, " 12352 "2.0 / 3.0 + 0.5 / size.y, 5.0 / 6.0 - 0.5 / size.y);\n"); 12353 12354 shader_addline(buffer, " chroma.x = texture%s(sampler, texcoord.xy).%c;\n", tex, component); 12355 12356 /* The other chroma value is 1/6th of the texture lower, from 5/6th to 12357 * 6/6th No need to clamp because we're just reusing the already clamped 12358 * value from above. */ 12359 shader_addline(buffer, " texcoord.y += 1.0 / 6.0;\n"); 12360 shader_addline(buffer, " chroma.y = texture%s(sampler, texcoord.xy).%c;\n", tex, component); 12361 12362 /* Sample the luminance value. It is in the top 2/3rd of the texture, so 12363 * scale the y coordinate. Clamp the y coordinate to prevent the chroma 12364 * values from bleeding into the sampled luminance values due to 12365 * filtering. */ 12366 shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); 12367 /* Multiply the y coordinate by 2/3 and clamp it. */ 12368 shader_addline(buffer, " texcoord.y = min(texcoord.y * 2.0 / 3.0, 2.0 / 3.0 - 0.5 / size.y);\n"); 12369 shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, component); 12370 } 12371 12372 static void gen_nv12_read(struct wined3d_string_buffer *buffer, 12373 const struct wined3d_gl_info *gl_info, const char *tex_type) 12374 { 12375 char component = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x'; 12376 const char *tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : ""; 12377 12378 /* NV12 surfaces contain a WxH sized luminance plane, followed by a 12379 * (W/2)x(H/2) sized plane where each component is an UV pair. So the 12380 * effective bitdepth is 12 bits per pixel. If the whole texture is 12381 * interpreted as luminance data it looks approximately like this: 12382 * 12383 * +----------------------------------+---- 12384 * | | 12385 * | | 12386 * | | 12387 * | | 12388 * | | 2 12389 * | LUMINANCE | - 12390 * | | 3 12391 * | | 12392 * | | 12393 * | | 12394 * | | 12395 * +----------------------------------+---- 12396 * |UVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUV| 12397 * |UVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUV| 12398 * | | 1 12399 * | | - 12400 * | | 3 12401 * | | 12402 * | | 12403 * +----------------------------------+---- */ 12404 12405 /* First sample the chroma values. */ 12406 shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); 12407 /* We only have half the number of chroma pixels. */ 12408 shader_addline(buffer, " texcoord.x *= 0.5;\n"); 12409 shader_addline(buffer, " texcoord.y = (texcoord.y + 2.0) / 3.0;\n"); 12410 12411 /* We must not allow filtering horizontally, this would mix U and V. 12412 * Vertical filtering is ok. However, bear in mind that the pixel center 12413 * is at 0.5, so add 0.5. */ 12414 12415 /* Convert to non-normalised coordinates so we can find the individual 12416 * pixel. */ 12417 shader_addline(buffer, " texcoord.x = floor(texcoord.x * size.x);\n"); 12418 /* Multiply by 2 since chroma components are stored in UV pixel pairs, add 12419 * 0.5 to hit the center of the pixel. Then convert back to normalised 12420 * coordinates. */ 12421 shader_addline(buffer, " texcoord.x = (texcoord.x * 2.0 + 0.5) / size.x;\n"); 12422 /* Clamp, keep the half pixel origin in mind. */ 12423 shader_addline(buffer, " texcoord.y = max(texcoord.y, 2.0 / 3.0 + 0.5 / size.y);\n"); 12424 12425 shader_addline(buffer, " chroma.y = texture%s(sampler, texcoord.xy).%c;\n", tex, component); 12426 /* Add 1.0 / size.x to sample the adjacent texel. */ 12427 shader_addline(buffer, " texcoord.x += 1.0 / size.x;\n"); 12428 shader_addline(buffer, " chroma.x = texture%s(sampler, texcoord.xy).%c;\n", tex, component); 12429 12430 /* Sample the luminance value. It is in the top 2/3rd of the texture, so 12431 * scale the y coordinate. Clamp the y coordinate to prevent the chroma 12432 * values from bleeding into the sampled luminance values due to 12433 * filtering. */ 12434 shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); 12435 /* Multiply the y coordinate by 2/3 and clamp it. */ 12436 shader_addline(buffer, " texcoord.y = min(texcoord.y * 2.0 / 3.0, 2.0 / 3.0 - 0.5 / size.y);\n"); 12437 shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, component); 12438 } 12439 12440 static void glsl_blitter_generate_yuv_shader(struct wined3d_string_buffer *buffer, 12441 const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, 12442 const char *output, const char *tex_type, const char *swizzle) 12443 { 12444 enum complex_fixup complex_fixup = get_complex_fixup(args->fixup); 12445 12446 shader_addline(buffer, "const vec4 yuv_coef = vec4(1.403, -0.344, -0.714, 1.770);\n"); 12447 shader_addline(buffer, "float luminance;\n"); 12448 shader_addline(buffer, "vec2 texcoord;\n"); 12449 shader_addline(buffer, "vec2 chroma;\n"); 12450 shader_addline(buffer, "uniform vec2 size;\n"); 12451 12452 shader_addline(buffer, "\nvoid main()\n{\n"); 12453 12454 switch (complex_fixup) 12455 { 12456 case COMPLEX_FIXUP_UYVY: 12457 case COMPLEX_FIXUP_YUY2: 12458 gen_packed_yuv_read(buffer, gl_info, args, tex_type); 12459 break; 12460 12461 case COMPLEX_FIXUP_YV12: 12462 gen_yv12_read(buffer, gl_info, tex_type); 12463 break; 12464 12465 case COMPLEX_FIXUP_NV12: 12466 gen_nv12_read(buffer, gl_info, tex_type); 12467 break; 12468 12469 default: 12470 FIXME("Unsupported fixup %#x.\n", complex_fixup); 12471 string_buffer_free(buffer); 12472 return; 12473 } 12474 12475 /* Calculate the final result. Formula is taken from 12476 * http://www.fourcc.org/fccyvrgb.php. Note that the chroma 12477 * ranges from -0.5 to 0.5. */ 12478 shader_addline(buffer, "\n chroma.xy -= 0.5;\n"); 12479 12480 shader_addline(buffer, " %s.x = luminance + chroma.x * yuv_coef.x;\n", output); 12481 shader_addline(buffer, " %s.y = luminance + chroma.y * yuv_coef.y + chroma.x * yuv_coef.z;\n", output); 12482 shader_addline(buffer, " %s.z = luminance + chroma.y * yuv_coef.w;\n", output); 12483 12484 shader_addline(buffer, "}\n"); 12485 } 12486 12487 static void glsl_blitter_generate_plain_shader(struct wined3d_string_buffer *buffer, 12488 const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, 12489 const char *output, const char *tex_type, const char *swizzle) 12490 { 12491 shader_addline(buffer, "\nvoid main()\n{\n"); 12492 shader_addline(buffer, " %s = texture%s(sampler, out_texcoord.%s);\n", 12493 output, needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle); 12494 shader_glsl_color_correction_ext(buffer, output, WINED3DSP_WRITEMASK_ALL, args->fixup); 12495 shader_addline(buffer, "}\n"); 12496 } 12497 12498 /* Context activation is done by the caller. */ 12499 static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter, 12500 const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args) 12501 { 12502 static const struct 12503 { 12504 GLenum texture_target; 12505 const char texture_type[7]; 12506 const char texcoord_swizzle[4]; 12507 } 12508 texture_data[] = 12509 { 12510 {GL_TEXTURE_2D, "2D", "xy"}, 12511 {GL_TEXTURE_CUBE_MAP, "Cube", "xyz"}, 12512 {GL_TEXTURE_RECTANGLE_ARB, "2DRect", "xy"}, 12513 }; 12514 static const char vshader_main[] = 12515 "\n" 12516 "void main()\n" 12517 "{\n" 12518 " gl_Position = vec4(pos, 0.0, 1.0);\n" 12519 " out_texcoord = texcoord;\n" 12520 "}\n"; 12521 enum complex_fixup complex_fixup = get_complex_fixup(args->fixup); 12522 struct wined3d_string_buffer *buffer, *output; 12523 GLuint program, vshader_id, fshader_id; 12524 const char *tex_type, *swizzle, *ptr; 12525 unsigned int i; 12526 GLint loc; 12527 12528 for (i = 0; i < ARRAY_SIZE(texture_data); ++i) 12529 { 12530 if (args->texture_type == texture_data[i].texture_target) 12531 { 12532 tex_type = texture_data[i].texture_type; 12533 swizzle = texture_data[i].texcoord_swizzle; 12534 break; 12535 } 12536 } 12537 if (i == ARRAY_SIZE(texture_data)) 12538 { 12539 FIXME("Unsupported texture type %#x.\n", args->texture_type); 12540 return 0; 12541 } 12542 12543 program = GL_EXTCALL(glCreateProgram()); 12544 12545 vshader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 12546 12547 buffer = string_buffer_get(&blitter->string_buffers); 12548 shader_glsl_add_version_declaration(buffer, gl_info); 12549 shader_addline(buffer, "%s vec2 pos;\n", get_attribute_keyword(gl_info)); 12550 shader_addline(buffer, "%s vec3 texcoord;\n", get_attribute_keyword(gl_info)); 12551 declare_out_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n"); 12552 shader_addline(buffer, vshader_main); 12553 12554 ptr = buffer->buffer; 12555 GL_EXTCALL(glShaderSource(vshader_id, 1, &ptr, NULL)); 12556 GL_EXTCALL(glAttachShader(program, vshader_id)); 12557 GL_EXTCALL(glDeleteShader(vshader_id)); 12558 12559 fshader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); 12560 12561 string_buffer_clear(buffer); 12562 shader_glsl_add_version_declaration(buffer, gl_info); 12563 shader_addline(buffer, "uniform sampler%s sampler;\n", tex_type); 12564 declare_in_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n"); 12565 if (!needs_legacy_glsl_syntax(gl_info)) 12566 shader_addline(buffer, "out vec4 ps_out[1];\n"); 12567 12568 output = string_buffer_get(&blitter->string_buffers); 12569 string_buffer_sprintf(output, "%s[0]", get_fragment_output(gl_info)); 12570 12571 switch (complex_fixup) 12572 { 12573 case COMPLEX_FIXUP_P8: 12574 glsl_blitter_generate_p8_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle); 12575 break; 12576 case COMPLEX_FIXUP_YUY2: 12577 case COMPLEX_FIXUP_UYVY: 12578 case COMPLEX_FIXUP_YV12: 12579 case COMPLEX_FIXUP_NV12: 12580 glsl_blitter_generate_yuv_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle); 12581 break; 12582 case COMPLEX_FIXUP_NONE: 12583 glsl_blitter_generate_plain_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle); 12584 } 12585 12586 string_buffer_release(&blitter->string_buffers, output); 12587 12588 ptr = buffer->buffer; 12589 GL_EXTCALL(glShaderSource(fshader_id, 1, &ptr, NULL)); 12590 string_buffer_release(&blitter->string_buffers, buffer); 12591 GL_EXTCALL(glAttachShader(program, fshader_id)); 12592 GL_EXTCALL(glDeleteShader(fshader_id)); 12593 12594 GL_EXTCALL(glBindAttribLocation(program, 0, "pos")); 12595 GL_EXTCALL(glBindAttribLocation(program, 1, "texcoord")); 12596 12597 if (!needs_legacy_glsl_syntax(gl_info)) 12598 GL_EXTCALL(glBindFragDataLocation(program, 0, "ps_out")); 12599 12600 GL_EXTCALL(glCompileShader(vshader_id)); 12601 print_glsl_info_log(gl_info, vshader_id, FALSE); 12602 GL_EXTCALL(glCompileShader(fshader_id)); 12603 print_glsl_info_log(gl_info, fshader_id, FALSE); 12604 GL_EXTCALL(glLinkProgram(program)); 12605 shader_glsl_validate_link(gl_info, program); 12606 12607 GL_EXTCALL(glUseProgram(program)); 12608 loc = GL_EXTCALL(glGetUniformLocation(program, "sampler")); 12609 GL_EXTCALL(glUniform1i(loc, 0)); 12610 if (complex_fixup == COMPLEX_FIXUP_P8) 12611 { 12612 loc = GL_EXTCALL(glGetUniformLocation(program, "sampler_palette")); 12613 GL_EXTCALL(glUniform1i(loc, 1)); 12614 } 12615 12616 return program; 12617 } 12618 12619 /* Context activation is done by the caller. */ 12620 static void glsl_blitter_upload_palette(struct wined3d_glsl_blitter *blitter, 12621 struct wined3d_context *context, const struct wined3d_texture *texture) 12622 { 12623 const struct wined3d_gl_info *gl_info = context->gl_info; 12624 const struct wined3d_palette *palette; 12625 12626 palette = texture->swapchain ? texture->swapchain->palette : NULL; 12627 12628 if (!blitter->palette_texture) 12629 gl_info->gl_ops.gl.p_glGenTextures(1, &blitter->palette_texture); 12630 12631 context_active_texture(context, gl_info, 1); 12632 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, blitter->palette_texture); 12633 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 12634 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 12635 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 12636 12637 if (palette) 12638 { 12639 gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_BGRA, 12640 GL_UNSIGNED_INT_8_8_8_8_REV, palette->colors); 12641 } 12642 else 12643 { 12644 static const DWORD black; 12645 12646 FIXME("P8 texture loaded without a palette.\n"); 12647 gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 1, 0, GL_BGRA, 12648 GL_UNSIGNED_INT_8_8_8_8_REV, &black); 12649 } 12650 12651 context_active_texture(context, gl_info, 0); 12652 } 12653 12654 /* Context activation is done by the caller. */ 12655 static struct glsl_blitter_program *glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter, 12656 struct wined3d_context *context, const struct wined3d_texture *texture) 12657 { 12658 const struct wined3d_gl_info *gl_info = context->gl_info; 12659 struct glsl_blitter_program *program; 12660 struct glsl_blitter_args args; 12661 struct wine_rb_entry *entry; 12662 12663 memset(&args, 0, sizeof(args)); 12664 args.texture_type = texture->target; 12665 args.fixup = texture->resource.format->color_fixup; 12666 12667 if ((entry = wine_rb_get(&blitter->programs, &args))) 12668 return WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry); 12669 12670 if (!(program = heap_alloc(sizeof(*program)))) 12671 { 12672 ERR("Failed to allocate blitter program memory.\n"); 12673 return NULL; 12674 } 12675 12676 program->args = args; 12677 if (!(program->id = glsl_blitter_generate_program(blitter, gl_info, &args))) 12678 { 12679 WARN("Failed to generate blitter program.\n"); 12680 heap_free(program); 12681 return NULL; 12682 } 12683 12684 if (wine_rb_put(&blitter->programs, &program->args, &program->entry) == -1) 12685 { 12686 ERR("Failed to store blitter program.\n"); 12687 GL_EXTCALL(glDeleteProgram(program->id)); 12688 heap_free(program); 12689 return NULL; 12690 } 12691 12692 return program; 12693 } 12694 12695 static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_context *context, 12696 const struct wined3d_texture *src_texture, DWORD src_location, 12697 const struct wined3d_texture *dst_texture, DWORD dst_location) 12698 { 12699 const struct wined3d_resource *src_resource = &src_texture->resource; 12700 const struct wined3d_resource *dst_resource = &dst_texture->resource; 12701 const struct wined3d_format *src_format = src_resource->format; 12702 const struct wined3d_format *dst_format = dst_resource->format; 12703 BOOL decompress; 12704 12705 if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id) 12706 { 12707 if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) 12708 blit_op = WINED3D_BLIT_OP_DEPTH_BLIT; 12709 else 12710 blit_op = WINED3D_BLIT_OP_COLOR_BLIT; 12711 } 12712 12713 if (blit_op != WINED3D_BLIT_OP_COLOR_BLIT) 12714 { 12715 TRACE("Unsupported blit_op %#x.\n", blit_op); 12716 return FALSE; 12717 } 12718 12719 if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) 12720 return FALSE; 12721 12722 if (src_texture->target == GL_TEXTURE_2D_MULTISAMPLE 12723 || dst_texture->target == GL_TEXTURE_2D_MULTISAMPLE 12724 || src_texture->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY 12725 || dst_texture->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) 12726 { 12727 TRACE("Multi-sample textures not supported.\n"); 12728 return FALSE; 12729 } 12730 12731 /* We don't necessarily want to blit from resources without 12732 * WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress 12733 * compressed textures. */ 12734 decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) 12735 && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED); 12736 if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) 12737 { 12738 TRACE("Source or destination resource does not have GPU access.\n"); 12739 return FALSE; 12740 } 12741 12742 if (!is_identity_fixup(dst_format->color_fixup) 12743 && (dst_format->id != src_format->id || dst_location != WINED3D_LOCATION_DRAWABLE)) 12744 { 12745 TRACE("Destination fixups are not supported.\n"); 12746 return FALSE; 12747 } 12748 12749 TRACE("Returning supported.\n"); 12750 return TRUE; 12751 } 12752 12753 static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, 12754 struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, 12755 DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, 12756 unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, 12757 const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) 12758 { 12759 struct wined3d_device *device = dst_texture->resource.device; 12760 const struct wined3d_gl_info *gl_info = context->gl_info; 12761 struct wined3d_texture *staging_texture = NULL; 12762 struct wined3d_glsl_blitter *glsl_blitter; 12763 struct glsl_blitter_program *program; 12764 struct wined3d_blitter *next; 12765 unsigned int src_level; 12766 GLint location; 12767 RECT s, d; 12768 12769 TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " 12770 "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", 12771 blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), 12772 wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), 12773 wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); 12774 12775 if (!glsl_blitter_supported(op, context, src_texture, src_location, dst_texture, dst_location)) 12776 { 12777 if (!(next = blitter->next)) 12778 { 12779 ERR("No blitter to handle blit op %#x.\n", op); 12780 return dst_location; 12781 } 12782 12783 TRACE("Forwarding to blitter %p.\n", next); 12784 return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, 12785 src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); 12786 } 12787 12788 glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter); 12789 12790 if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) 12791 { 12792 struct wined3d_resource_desc desc; 12793 struct wined3d_box upload_box; 12794 HRESULT hr; 12795 12796 TRACE("Source texture is not GPU accessible, creating a staging texture.\n"); 12797 12798 src_level = src_sub_resource_idx % src_texture->level_count; 12799 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 12800 desc.format = src_texture->resource.format->id; 12801 desc.multisample_type = src_texture->resource.multisample_type; 12802 desc.multisample_quality = src_texture->resource.multisample_quality; 12803 desc.usage = WINED3DUSAGE_PRIVATE; 12804 desc.access = WINED3D_RESOURCE_ACCESS_GPU; 12805 desc.width = wined3d_texture_get_level_width(src_texture, src_level); 12806 desc.height = wined3d_texture_get_level_height(src_texture, src_level); 12807 desc.depth = 1; 12808 desc.size = 0; 12809 12810 if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0, 12811 NULL, NULL, &wined3d_null_parent_ops, &staging_texture))) 12812 { 12813 ERR("Failed to create staging texture, hr %#x.\n", hr); 12814 return dst_location; 12815 } 12816 12817 wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth); 12818 wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0, 12819 src_texture, src_sub_resource_idx, &upload_box); 12820 12821 src_texture = staging_texture; 12822 src_sub_resource_idx = 0; 12823 } 12824 else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO 12825 && (src_texture->sub_resources[src_sub_resource_idx].locations 12826 & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE 12827 && !wined3d_resource_is_offscreen(&src_texture->resource)) 12828 { 12829 12830 /* Without FBO blits transferring from the drawable to the texture is 12831 * expensive, because we have to flip the data in sysmem. Since we can 12832 * flip in the blitter, we don't actually need that flip anyway. So we 12833 * use the surface's texture as scratch texture, and flip the source 12834 * rectangle instead. */ 12835 texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context); 12836 12837 s = *src_rect; 12838 src_level = src_sub_resource_idx % src_texture->level_count; 12839 s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top; 12840 s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom; 12841 src_rect = &s; 12842 } 12843 else 12844 { 12845 wined3d_texture_load(src_texture, context, FALSE); 12846 } 12847 12848 context_apply_blit_state(context, device); 12849 12850 if (dst_location == WINED3D_LOCATION_DRAWABLE) 12851 { 12852 d = *dst_rect; 12853 wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d); 12854 dst_rect = &d; 12855 } 12856 12857 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) 12858 { 12859 GLenum buffer; 12860 12861 if (dst_location == WINED3D_LOCATION_DRAWABLE) 12862 { 12863 TRACE("Destination texture %p is onscreen.\n", dst_texture); 12864 buffer = wined3d_texture_get_gl_buffer(dst_texture); 12865 } 12866 else 12867 { 12868 TRACE("Destination texture %p is offscreen.\n", dst_texture); 12869 buffer = GL_COLOR_ATTACHMENT0; 12870 } 12871 context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, 12872 &dst_texture->resource, dst_sub_resource_idx, NULL, 0, dst_location); 12873 context_set_draw_buffer(context, buffer); 12874 context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); 12875 context_invalidate_state(context, STATE_FRAMEBUFFER); 12876 } 12877 12878 if (!(program = glsl_blitter_get_program(glsl_blitter, context, src_texture))) 12879 { 12880 ERR("Failed to get blitter program.\n"); 12881 return dst_location; 12882 } 12883 GL_EXTCALL(glUseProgram(program->id)); 12884 switch (get_complex_fixup(program->args.fixup)) 12885 { 12886 case COMPLEX_FIXUP_P8: 12887 glsl_blitter_upload_palette(glsl_blitter, context, src_texture); 12888 break; 12889 12890 case COMPLEX_FIXUP_YUY2: 12891 case COMPLEX_FIXUP_UYVY: 12892 case COMPLEX_FIXUP_YV12: 12893 case COMPLEX_FIXUP_NV12: 12894 src_level = src_sub_resource_idx % src_texture->level_count; 12895 location = GL_EXTCALL(glGetUniformLocation(program->id, "size")); 12896 GL_EXTCALL(glUniform2f(location, wined3d_texture_get_level_pow2_width(src_texture, src_level), 12897 wined3d_texture_get_level_pow2_height(src_texture, src_level))); 12898 break; 12899 12900 default: 12901 break; 12902 } 12903 context_draw_shaded_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter); 12904 GL_EXTCALL(glUseProgram(0)); 12905 12906 if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture)) 12907 gl_info->gl_ops.gl.p_glFlush(); 12908 12909 if (staging_texture) 12910 wined3d_texture_decref(staging_texture); 12911 12912 return dst_location; 12913 } 12914 12915 static void glsl_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device, 12916 unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, 12917 const RECT *draw_rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) 12918 { 12919 struct wined3d_blitter *next; 12920 12921 if ((next = blitter->next)) 12922 next->ops->blitter_clear(next, device, rt_count, fb, rect_count, 12923 clear_rects, draw_rect, flags, color, depth, stencil); 12924 } 12925 12926 static const struct wined3d_blitter_ops glsl_blitter_ops = 12927 { 12928 glsl_blitter_destroy, 12929 glsl_blitter_clear, 12930 glsl_blitter_blit, 12931 }; 12932 12933 struct wined3d_blitter *wined3d_glsl_blitter_create(struct wined3d_blitter **next, 12934 const struct wined3d_device *device) 12935 { 12936 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; 12937 struct wined3d_glsl_blitter *blitter; 12938 12939 if (device->shader_backend != &glsl_shader_backend) 12940 return NULL; 12941 12942 if (!gl_info->supported[ARB_VERTEX_SHADER] || !gl_info->supported[ARB_FRAGMENT_SHADER]) 12943 return NULL; 12944 12945 if (!(blitter = heap_alloc(sizeof(*blitter)))) 12946 { 12947 ERR("Failed to allocate blitter.\n"); 12948 return NULL; 12949 } 12950 12951 TRACE("Created blitter %p.\n", blitter); 12952 12953 blitter->blitter.ops = &glsl_blitter_ops; 12954 blitter->blitter.next = *next; 12955 string_buffer_list_init(&blitter->string_buffers); 12956 wine_rb_init(&blitter->programs, glsl_blitter_args_compare); 12957 blitter->palette_texture = 0; 12958 *next = &blitter->blitter; 12959 12960 return *next; 12961 } 12962