From 2014141a253a791fc9c79aae3c8ef3c35b73e658 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 29 May 2013 09:45:35 +0200 Subject: [PATCH] wined3d: Add support for GLSL based fixed function vertex shaders. --- dlls/wined3d/directx.c | 10 +- dlls/wined3d/glsl_shader.c | 541 ++++++++++++++++++++++++++++++++++++++++- dlls/wined3d/state.c | 41 ++-- dlls/wined3d/utils.c | 96 ++++++++ dlls/wined3d/wined3d_private.h | 83 +++++++ 5 files changed, 738 insertions(+), 33 deletions(-) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 3ef5eeb4550..d3083221ad0 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2316,6 +2316,14 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info * return select_card_fallback_nvidia(gl_info); } +static const struct wined3d_vertex_pipe_ops *select_vertex_implementation(const struct wined3d_gl_info *gl_info, + const struct wined3d_shader_backend_ops *shader_backend_ops) +{ + if (shader_backend_ops == &glsl_shader_backend) + return &glsl_vertex_pipe; + return &ffp_vertex_pipe; +} + static const struct fragment_pipeline *select_fragment_implementation(const struct wined3d_gl_info *gl_info, const struct wined3d_shader_backend_ops *shader_backend_ops) { @@ -2843,7 +2851,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) checkGLcall("extension detection"); adapter->shader_backend = select_shader_backend(gl_info); - adapter->vertex_pipe = &ffp_vertex_pipe; + adapter->vertex_pipe = select_vertex_implementation(gl_info, adapter->shader_backend); adapter->fragment_pipe = select_fragment_implementation(gl_info, adapter->shader_backend); adapter->blitter = select_blit_implementation(gl_info, adapter->shader_backend); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 88162295893..60a904a57f0 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -99,6 +99,7 @@ struct shader_glsl_priv { const struct wined3d_vertex_pipe_ops *vertex_pipe; const struct fragment_pipeline *fragment_pipe; + struct wine_rb_tree ffp_vertex_shaders; struct wine_rb_tree ffp_fragment_shaders; BOOL ffp_proj_control; }; @@ -188,6 +189,13 @@ struct glsl_shader_private UINT num_gl_shaders, shader_array_size; }; +struct glsl_ffp_vertex_shader +{ + struct wined3d_ffp_vs_desc desc; + GLhandleARB id; + struct list linked_programs; +}; + struct glsl_ffp_fragment_shader { struct ffp_frag_desc entry; @@ -195,6 +203,12 @@ struct glsl_ffp_fragment_shader struct list linked_programs; }; +struct glsl_ffp_destroy_ctx +{ + struct shader_glsl_priv *priv; + const struct wined3d_gl_info *gl_info; +}; + static const char *debug_gl_shader_type(GLenum type) { switch (type) @@ -4789,6 +4803,223 @@ static GLhandleARB find_glsl_geometry_shader(const struct wined3d_context *conte return ret; } +static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, const char *material) +{ + switch (mcs) + { + case WINED3D_MCS_MATERIAL: + return material; + case WINED3D_MCS_COLOR1: + return "gl_Color"; + case WINED3D_MCS_COLOR2: + return "gl_SecondaryColor"; + default: + ERR("Invalid material color source %#x.\n", mcs); + return ""; + } +} + +static void shader_glsl_ffp_vertex_lighting(struct wined3d_shader_buffer *buffer, + const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info) +{ + const char *diffuse, *specular, *emission, *ambient; + enum wined3d_light_type light_type; + unsigned int i; + + if (!settings->lighting) + { + shader_addline(buffer, "gl_FrontColor = gl_Color;\n"); + shader_addline(buffer, "gl_FrontSecondaryColor = gl_SecondaryColor;\n"); + return; + } + + shader_addline(buffer, "vec3 ambient = gl_LightModel.ambient.xyz;\n"); + shader_addline(buffer, "vec3 diffuse = vec3(0.0);\n"); + shader_addline(buffer, "vec4 specular = vec4(0.0);\n"); + shader_addline(buffer, "vec3 dir, dst, half;\n"); + shader_addline(buffer, "float att, t;\n"); + + ambient = shader_glsl_ffp_mcs(settings->ambient_source, "gl_FrontMaterial.ambient"); + diffuse = shader_glsl_ffp_mcs(settings->diffuse_source, "gl_FrontMaterial.diffuse"); + specular = shader_glsl_ffp_mcs(settings->specular_source, "gl_FrontMaterial.specular"); + emission = shader_glsl_ffp_mcs(settings->emission_source, "gl_FrontMaterial.emission"); + + for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) + { + + light_type = (settings->light_type >> WINED3D_FFP_LIGHT_TYPE_SHIFT(i)) & WINED3D_FFP_LIGHT_TYPE_MASK; + switch (light_type) + { + case WINED3D_LIGHT_POINT: + shader_addline(buffer, "dir = gl_LightSource[%u].position.xyz - ec_pos.xyz;\n", i); + shader_addline(buffer, "dst.z = dot(dir, dir);\n"); + shader_addline(buffer, "dst.y = sqrt(dst.z);\n"); + shader_addline(buffer, "dst.x = 1.0;\n"); + shader_addline(buffer, "att = dot(dst.xyz, vec3(gl_LightSource[%u].constantAttenuation," + " gl_LightSource[%u].linearAttenuation, gl_LightSource[%u].quadraticAttenuation));\n", i, i, i); + shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz / att;\n", i); + if (!settings->normal) + break; + shader_addline(buffer, "dir = normalize(dir);\n"); + shader_addline(buffer, "diffuse += (max(0.0, dot(dir, normal))" + " * gl_LightSource[%u].diffuse.xyz) / att;\n", i); + if (settings->localviewer) + shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n"); + else + shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, 1.0)));\n"); + shader_addline(buffer, "if (t > 0.0) specular += (pow(t, gl_FrontMaterial.shininess)" + " * gl_LightSource[%u].specular) / att;\n", i); + break; + + case WINED3D_LIGHT_SPOT: + shader_addline(buffer, "dir = gl_LightSource[%u].position.xyz - ec_pos.xyz;\n", i); + shader_addline(buffer, "dst.z = dot(dir, dir);\n"); + shader_addline(buffer, "dst.y = sqrt(dst.z);\n"); + shader_addline(buffer, "dst.x = 1.0;\n"); + shader_addline(buffer, "dir = normalize(dir);\n"); + shader_addline(buffer, "t = dot(-dir, normalize(gl_LightSource[%u].spotDirection));\n", i); + shader_addline(buffer, "if (t < gl_LightSource[%u].spotCosCutoff) att = 0.0;\n", i); + shader_addline(buffer, "else att = pow(t, gl_LightSource[%u].spotExponent)" + " / dot(dst.xyz, vec3(gl_LightSource[%u].constantAttenuation," + " gl_LightSource[%u].linearAttenuation, gl_LightSource[%u].quadraticAttenuation));\n", + i, i, i, i); + shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz * att;\n", i); + if (!settings->normal) + break; + shader_addline(buffer, "diffuse += (max(0.0, dot(dir, normal))" + " * gl_LightSource[%u].diffuse.xyz) * att;\n", i); + if (settings->localviewer) + shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n"); + else + shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, 1.0)));\n"); + shader_addline(buffer, "if (t > 0.0) specular += (pow(t, gl_FrontMaterial.shininess)" + " * gl_LightSource[%u].specular) * att;\n", i); + break; + + case WINED3D_LIGHT_DIRECTIONAL: + shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz;\n", i); + if (!settings->normal) + break; + shader_addline(buffer, "dir = normalize(gl_LightSource[%u].position.xyz);\n", i); + shader_addline(buffer, "diffuse += max(0.0, dot(dir, normal)) * gl_LightSource[%u].diffuse.xyz;\n", i); + shader_addline(buffer, "t = dot(normal, gl_LightSource[%u].halfVector.xyz);\n", i); + shader_addline(buffer, "if (t > 0.0) specular += pow(t, gl_FrontMaterial.shininess)" + " * gl_LightSource[%u].specular;\n", i); + break; + + default: + if (light_type) + FIXME("Unhandled light type %#x.\n", light_type); + continue; + } + } + + shader_addline(buffer, "gl_FrontColor.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n", + ambient, diffuse, emission); + shader_addline(buffer, "gl_FrontColor.w = %s.w;\n", diffuse); + shader_addline(buffer, "gl_FrontSecondaryColor = %s * specular;\n", specular); +} + +/* Context activation is done by the caller. */ +static GLhandleARB shader_glsl_generate_ffp_vertex_shader(struct wined3d_shader_buffer *buffer, + const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info) +{ + GLhandleARB shader_obj; + unsigned int i; + + shader_buffer_clear(buffer); + + shader_addline(buffer, "#version 120\n"); + shader_addline(buffer, "\n"); + shader_addline(buffer, "void main()\n{\n"); + shader_addline(buffer, "float m;\n"); + shader_addline(buffer, "vec3 r;\n"); + + shader_addline(buffer, "vec4 ec_pos = gl_ModelViewMatrix * gl_Vertex;\n"); + shader_addline(buffer, "gl_Position = gl_ProjectionMatrix * ec_pos;\n"); + shader_addline(buffer, "gl_ClipVertex = ec_pos;\n"); + shader_addline(buffer, "ec_pos /= ec_pos.w;\n"); + + if (!settings->normal) + shader_addline(buffer, "vec3 normal = vec3(0.0);\n"); + else if (settings->normalize) + shader_addline(buffer, "vec3 normal = normalize(gl_NormalMatrix * gl_Normal);\n"); + else + shader_addline(buffer, "vec3 normal = gl_NormalMatrix * gl_Normal;\n"); + + shader_glsl_ffp_vertex_lighting(buffer, settings, gl_info); + + for (i = 0; i < MAX_TEXTURES; ++i) + { + switch (settings->texgen[i] << WINED3D_FFP_TCI_SHIFT) + { + case WINED3DTSS_TCI_PASSTHRU: + if (settings->texcoords & (1 << i)) + shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * gl_MultiTexCoord%d;\n", + i, i, i); + break; + + case WINED3DTSS_TCI_CAMERASPACENORMAL: + shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * vec4(normal, 1.0);\n", i, i); + break; + + case WINED3DTSS_TCI_CAMERASPACEPOSITION: + shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * ec_pos;\n", i, i); + break; + + case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: + shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u]" + " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i); + break; + + case WINED3DTSS_TCI_SPHEREMAP: + shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n"); + shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n"); + shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u]" + " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);", i, i); + break; + + default: + ERR("Unhandled texgen %#x.\n", settings->texgen[i]); + break; + } + } + + switch (settings->fog_mode) + { + case WINED3D_FFP_VS_FOG_OFF: + break; + + case WINED3D_FFP_VS_FOG_FOGCOORD: + shader_addline(buffer, "gl_FogFragCoord = gl_SecondaryColor.w * 255.0;\n"); + break; + + case WINED3D_FFP_VS_FOG_RANGE: + shader_addline(buffer, "gl_FogFragCoord = length(ec_pos.xyz);\n"); + break; + + case WINED3D_FFP_VS_FOG_DEPTH: + shader_addline(buffer, "gl_FogFragCoord = ec_pos.z;\n"); + break; + + default: + ERR("Unhandled fog mode %#x.\n", settings->fog_mode); + break; + } + + shader_addline(buffer, "gl_PointSize = gl_Point.size / sqrt(gl_Point.distanceConstantAttenuation" + " + gl_Point.distanceLinearAttenuation * length(ec_pos.xyz)" + " + gl_Point.distanceQuadraticAttenuation * dot(ec_pos.xyz, ec_pos.xyz));\n"); + shader_addline(buffer, "gl_PointSize = clamp(gl_PointSize, gl_Point.sizeMin, gl_Point.sizeMax);\n"); + + shader_addline(buffer, "}\n"); + + shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + shader_glsl_compile(gl_info, shader_obj, buffer->buffer); + + return shader_obj; +} + static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_shader_buffer *buffer, DWORD argnum, unsigned int stage, DWORD arg) { @@ -5399,6 +5630,27 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf return shader_obj; } +static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv *priv, + const struct wined3d_gl_info *gl_info, const struct wined3d_ffp_vs_settings *settings) +{ + struct glsl_ffp_vertex_shader *shader; + const struct wine_rb_entry *entry; + + if ((entry = wine_rb_get(&priv->ffp_vertex_shaders, settings))) + return WINE_RB_ENTRY_VALUE(entry, struct glsl_ffp_vertex_shader, desc.entry); + + if (!(shader = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader)))) + return NULL; + + shader->desc.settings = *settings; + shader->id = shader_glsl_generate_ffp_vertex_shader(&priv->shader_buffer, settings, gl_info); + list_init(&shader->linked_programs); + if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1) + ERR("Failed to insert ffp vertex shader.\n"); + + return shader; +} + static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info, const struct ffp_frag_settings *args) { @@ -5495,7 +5747,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const struct ps_compile_args ps_compile_args; struct vs_compile_args vs_compile_args; GLhandleARB vs_id, gs_id, ps_id; - struct list *ps_list; + struct list *ps_list, *vs_list; struct wined3d_device *device = context->swapchain->device; if (use_vs(state)) @@ -5503,12 +5755,25 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const vshader = state->vertex_shader; find_vs_compile_args(state, vshader, &vs_compile_args); vs_id = find_glsl_vshader(context, &priv->shader_buffer, vshader, &vs_compile_args); + vs_list = &vshader->linked_programs; if ((gshader = state->geometry_shader)) gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, gshader); else gs_id = 0; } + else if (priv->vertex_pipe == &glsl_vertex_pipe) + { + struct glsl_ffp_vertex_shader *ffp_shader; + struct wined3d_ffp_vs_settings settings; + + wined3d_ffp_get_vs_settings(state, &device->stream_info, &settings); + ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings); + vs_id = ffp_shader->id; + vs_list = &ffp_shader->linked_programs; + + gs_id = 0; + } else { vs_id = 0; @@ -5563,6 +5828,15 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const priv->glsl_program = entry; /* Attach GLSL vshader */ + if (vs_id) + { + TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, programId); + GL_EXTCALL(glAttachObjectARB(programId, vs_id)); + checkGLcall("glAttachObjectARB"); + + list_add_head(vs_list, &entry->vs.shader_entry); + } + if (vshader) { WORD map = vshader->reg_maps.input_registers; @@ -5577,10 +5851,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const */ GL_EXTCALL(glDeleteObjectARB(reorder_shader_id)); - TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, programId); - GL_EXTCALL(glAttachObjectARB(programId, vs_id)); - checkGLcall("glAttachObjectARB"); - /* Bind vertex attributes to a corresponding index number to match * the same index numbers as ARB_vertex_programs (makes loading * vertex attributes simpler). With this method, we can use the @@ -5598,8 +5868,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name)); } checkGLcall("glBindAttribLocationARB"); - - list_add_head(&vshader->linked_programs, &entry->vs.shader_entry); } if (gshader) @@ -6376,6 +6644,259 @@ const struct wined3d_shader_backend_ops glsl_shader_backend = shader_glsl_has_ffp_proj_control, }; +static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) +{ + if (enable) + gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); + else + gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); + checkGLcall("GL_VERTEX_PROGRAM_POINT_SIZE_ARB"); +} + +static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps) +{ + caps->max_active_lights = gl_info->limits.lights; + caps->max_vertex_blend_matrices = 0; + caps->max_vertex_blend_matrix_index = 0; + caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN + | WINED3DVTXPCAPS_MATERIALSOURCE7 + | WINED3DVTXPCAPS_VERTEXFOG + | WINED3DVTXPCAPS_DIRECTIONALLIGHTS + | WINED3DVTXPCAPS_POSITIONALLIGHTS + | WINED3DVTXPCAPS_LOCALVIEWER + | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP; + caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 8; /* 8 texture coordinates. */ + caps->max_user_clip_planes = gl_info->limits.clipplanes; + caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE; +} + +static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) +{ + struct shader_glsl_priv *priv; + + if (shader_backend == &glsl_shader_backend) + { + priv = shader_priv; + + if (wine_rb_init(&priv->ffp_vertex_shaders, &wined3d_ffp_vertex_program_rb_functions) == -1) + { + ERR("Failed to initialize rbtree.\n"); + return NULL; + } + + return priv; + } + + FIXME("GLSL vertex pipe without GLSL shader backend not implemented.\n"); + + return NULL; +} + +static void shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context) +{ + struct glsl_ffp_vertex_shader *shader = WINE_RB_ENTRY_VALUE(entry, + struct glsl_ffp_vertex_shader, desc.entry); + struct glsl_shader_prog_link *program, *program2; + struct glsl_ffp_destroy_ctx *ctx = context; + + LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs, + struct glsl_shader_prog_link, vs.shader_entry) + { + delete_glsl_program_entry(ctx->priv, ctx->gl_info, program); + } + ctx->gl_info->gl_ops.ext.p_glDeleteObjectARB(shader->id); + HeapFree(GetProcessHeap(), 0, shader); +} + +/* Context activation is done by the caller. */ +static void glsl_vertex_pipe_vp_free(struct wined3d_device *device) +{ + struct shader_glsl_priv *priv = device->vertex_priv; + struct glsl_ffp_destroy_ctx ctx; + + ctx.priv = priv; + ctx.gl_info = &device->adapter->gl_info; + wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx); +} + +static void glsl_vertex_pipe_shader(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) +{ + context->select_shader = 1; +} + +static void glsl_vertex_pipe_light(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) +{ + light(context, state, state_id); + context->select_shader = 1; +} + +static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = +{ + {STATE_VDECL, {STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE }, + {STATE_VSHADER, {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_MATERIAL, {STATE_RENDER(WINED3D_RS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), state_specularenable }, WINED3D_GL_EXT_NONE }, + /* Clip planes */ + {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(8), {STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(9), {STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(10), {STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(11), {STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(12), {STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(13), {STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(14), {STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(15), {STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(16), {STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(17), {STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(18), {STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(19), {STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(20), {STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(21), {STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(22), {STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(23), {STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(24), {STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(25), {STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(26), {STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(27), {STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(28), {STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(29), {STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(30), {STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE }, + {STATE_CLIPPLANE(31), {STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE }, + /* Lights */ + {STATE_ACTIVELIGHT(0), {STATE_ACTIVELIGHT(0), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(1), {STATE_ACTIVELIGHT(1), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(2), {STATE_ACTIVELIGHT(2), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(3), {STATE_ACTIVELIGHT(3), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(4), {STATE_ACTIVELIGHT(4), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(5), {STATE_ACTIVELIGHT(5), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(6), {STATE_ACTIVELIGHT(6), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + {STATE_ACTIVELIGHT(7), {STATE_ACTIVELIGHT(7), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, + /* Viewport */ + {STATE_VIEWPORT, {STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE }, + /* Transform states */ + {STATE_TRANSFORM(WINED3D_TS_VIEW), {STATE_TRANSFORM(WINED3D_TS_VIEW), transform_view }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_PROJECTION), {STATE_TRANSFORM(WINED3D_TS_PROJECTION), transform_projection }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE0), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE1), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE2), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE3), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE4), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE5), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE6), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_TEXTURE7), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), transform_world }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + /* Fog */ + {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_CLIPPING), {STATE_RENDER(WINED3D_RS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE), {STATE_RENDER(WINED3D_RS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_LIGHTING), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_AMBIENT), {STATE_RENDER(WINED3D_RS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_COLORVERTEX), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_LOCALVIEWER), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_VERTEXBLEND), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSIZE), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS }, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, + {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSCALE_A), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSCALE_B), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSCALE_C), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, ARB_POINT_PARAMETERS }, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, EXT_POINT_PARAMETERS }, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_TWEENFACTOR), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE), {STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + /* Samplers for NP2 texture matrix adjustions. They are not needed if + * GL_ARB_texture_non_power_of_two is supported, so register a NULL state + * handler in that case to get the vertex part of sampler() skipped (VTF + * is handled in the misc states). Otherwise, register + * sampler_texmatrix(), which takes care of updating the texture matrix. */ + {STATE_SAMPLER(0), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(0), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(0), {STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(1), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(1), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(1), {STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(2), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(2), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(2), {STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(3), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(3), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(3), {STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(4), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(4), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(4), {STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(5), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(5), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(5), {STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(6), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(6), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(6), {STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(7), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + {STATE_SAMPLER(7), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, + {STATE_SAMPLER(7), {STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, {0, NULL }, WINED3D_GL_EXT_NONE }, +}; + +/* TODO: + * - This currently depends on GL fixed function functions to set things + * like light parameters. Ideally we'd use regular uniforms for that. + * - In part because of the previous point, much of this is modelled after + * GL fixed function, and has much of the same limitations. For example, + * D3D spot lights are slightly different from GL spot lights. + * - We can now implement drawing transformed vertices using the GLSL pipe, + * instead of using the immediate mode fallback. + * - Similarly, we don't need the fallback for certain combinations of + * material sources anymore. + * - Implement vertex blending and vertex tweening. + * - Handle WINED3D_TSS_TEXCOORD_INDEX in the shader, instead of duplicating + * attribute arrays in load_tex_coords(). + * - Per-vertex point sizes. */ +const struct wined3d_vertex_pipe_ops glsl_vertex_pipe = +{ + glsl_vertex_pipe_vp_enable, + glsl_vertex_pipe_vp_get_caps, + glsl_vertex_pipe_vp_alloc, + glsl_vertex_pipe_vp_free, + glsl_vertex_pipe_vp_states, +}; + static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable) { /* Nothing to do. */ @@ -6437,12 +6958,6 @@ static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *s return NULL; } -struct glsl_ffp_destroy_ctx -{ - struct shader_glsl_priv *priv; - const struct wined3d_gl_info *gl_info; -}; - static void shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry *entry, void *context) { struct glsl_ffp_fragment_shader *shader = WINE_RB_ENTRY_VALUE(entry, diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 05c49a5be86..eddff66cc04 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -271,7 +271,7 @@ static void state_zfunc(struct wined3d_context *context, const struct wined3d_st checkGLcall("glDepthFunc"); } -static void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; float col[4]; @@ -587,7 +587,7 @@ static void shaderconstant(struct wined3d_context *context, const struct wined3d context->load_constants = 1; } -static void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; DWORD enable = 0xffffffff; @@ -654,7 +654,7 @@ static void state_clipping(struct wined3d_context *context, const struct wined3d checkGLcall("clip plane disable"); } -static void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR) @@ -950,7 +950,7 @@ static void state_stencilwrite(struct wined3d_context *context, const struct win checkGLcall("glStencilMask"); } -static void state_fog_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_fog_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -1431,7 +1431,7 @@ static void state_normalize(struct wined3d_context *context, const struct wined3 } } -static void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { union { DWORD d; @@ -1451,7 +1451,7 @@ static void state_psizemin_w(struct wined3d_context *context, const struct wined } -static void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; union @@ -1474,7 +1474,7 @@ static void state_psizemin_ext(struct wined3d_context *context, const struct win checkGLcall("glPointParameterfEXT(...)"); } -static void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; union @@ -1497,7 +1497,7 @@ static void state_psizemin_arb(struct wined3d_context *context, const struct win checkGLcall("glPointParameterfARB(...)"); } -static void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; /* TODO: Group this with the viewport */ @@ -1672,7 +1672,7 @@ static void state_lastpixel(struct wined3d_context *context, const struct wined3 } } -static void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { static BOOL warned; @@ -1685,7 +1685,7 @@ static void state_pointsprite_w(struct wined3d_context *context, const struct wi } } -static void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -3295,7 +3295,7 @@ void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *st } } -static void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { DWORD texUnit = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); const struct wined3d_device *device = context->swapchain->device; @@ -3599,7 +3599,7 @@ static void tex_bumpenvlscale(struct wined3d_context *context, const struct wine context->load_constants = 1; } -static void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const DWORD sampler = state_id - STATE_SAMPLER(0); const struct wined3d_texture *texture = state->textures[sampler]; @@ -3763,7 +3763,7 @@ static void shader_bumpenvmat(struct wined3d_context *context, const struct wine context->load_constants = 1; } -static void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -3791,7 +3791,7 @@ static void transform_world(struct wined3d_context *context, const struct wined3 } } -static void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; UINT index = state_id - STATE_CLIPPLANE(0); @@ -3919,7 +3919,7 @@ static void state_vertexblend(struct wined3d_context *context, const struct wine } } -static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_light_info *light = NULL; @@ -3978,7 +3978,7 @@ static void transform_view(struct wined3d_context *context, const struct wined3d } } -static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -4536,7 +4536,7 @@ static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d streamsrc(context, state, STATE_STREAMSRC); } -static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_device *device = context->swapchain->device; const struct wined3d_gl_info *gl_info = context->gl_info; @@ -4698,10 +4698,13 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine vp.width, vp.height); } + if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE))) + state_pscale(context, state, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)); + checkGLcall("glViewport"); } -static void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION))) transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); @@ -4711,7 +4714,7 @@ static void viewport_vertexpart(struct wined3d_context *context, const struct wi context->load_constants = 1; } -static void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; UINT Index = state_id - STATE_ACTIVELIGHT(0); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 004ee00018b..59b91ecbfd5 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -3521,6 +3521,102 @@ const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions = ffp_frag_program_key_compare, }; +void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si, + struct wined3d_ffp_vs_settings *settings) +{ + unsigned int coord_idx, i; + + if (si->position_transformed) + { + memset(settings, 0, sizeof(*settings)); + + if (!state->render_states[WINED3D_RS_FOGENABLE]) + settings->fog_mode = WINED3D_FFP_VS_FOG_OFF; + else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE) + settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH; + else + settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD; + + for (i = 0; i < MAX_TEXTURES; ++i) + { + coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; + if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx)))) + settings->texcoords |= 1 << i; + settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT) + & WINED3D_FFP_TCI_MASK; + } + return; + } + + settings->normal = !!(si->use_map & (1 << WINED3D_FFP_NORMAL)); + settings->normalize = settings->normal && state->render_states[WINED3D_RS_NORMALIZENORMALS]; + settings->lighting = !!state->render_states[WINED3D_RS_LIGHTING]; + settings->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER]; + + if (state->render_states[WINED3D_RS_COLORVERTEX] && (si->use_map & (1 << WINED3D_FFP_DIFFUSE))) + { + settings->diffuse_source = state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE]; + settings->emission_source = state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE]; + settings->ambient_source = state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE]; + settings->specular_source = state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE]; + } + else + { + settings->diffuse_source = WINED3D_MCS_MATERIAL; + settings->emission_source = WINED3D_MCS_MATERIAL; + settings->ambient_source = WINED3D_MCS_MATERIAL; + settings->specular_source = WINED3D_MCS_MATERIAL; + } + + settings->texcoords = 0; + for (i = 0; i < MAX_TEXTURES; ++i) + { + coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; + if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx)))) + settings->texcoords |= 1 << i; + settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT) + & WINED3D_FFP_TCI_MASK; + } + + settings->light_type = 0; + for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) + { + if (state->lights[i]) + settings->light_type |= (state->lights[i]->OriginalParms.type + & WINED3D_FFP_LIGHT_TYPE_MASK) << WINED3D_FFP_LIGHT_TYPE_SHIFT(i); + } + + if (!state->render_states[WINED3D_RS_FOGENABLE]) + settings->fog_mode = WINED3D_FFP_VS_FOG_OFF; + else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE) + settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH; + else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE) + settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD; + else if (state->render_states[WINED3D_RS_RANGEFOGENABLE]) + settings->fog_mode = WINED3D_FFP_VS_FOG_RANGE; + else + settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH; + + settings->padding = 0; +} + +static int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb_entry *entry) +{ + const struct wined3d_ffp_vs_settings *ka = key; + const struct wined3d_ffp_vs_settings *kb = &WINE_RB_ENTRY_VALUE(entry, + const struct wined3d_ffp_vs_desc, entry)->settings; + + return memcmp(ka, kb, sizeof(*ka)); +} + +const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions = +{ + wined3d_rb_alloc, + wined3d_rb_realloc, + wined3d_rb_free, + wined3d_ffp_vertex_program_key_compare, +}; + UINT wined3d_log2i(UINT32 x) { static const UINT l[] = diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 8d6f8453308..5cbd63ac918 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1214,6 +1214,7 @@ extern const struct fragment_pipeline glsl_fragment_pipe DECLSPEC_HIDDEN; extern const struct wined3d_vertex_pipe_ops none_vertex_pipe DECLSPEC_HIDDEN; extern const struct wined3d_vertex_pipe_ops ffp_vertex_pipe DECLSPEC_HIDDEN; +extern const struct wined3d_vertex_pipe_ops glsl_vertex_pipe DECLSPEC_HIDDEN; /* "Base" state table */ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs, @@ -1680,6 +1681,7 @@ struct ffp_frag_desc }; extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECLSPEC_HIDDEN; +extern const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions DECLSPEC_HIDDEN; extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN; void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state, @@ -1689,6 +1691,48 @@ const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *frag void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc) DECLSPEC_HIDDEN; void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect) DECLSPEC_HIDDEN; +enum wined3d_ffp_vs_fog_mode +{ + WINED3D_FFP_VS_FOG_OFF = 0, + WINED3D_FFP_VS_FOG_FOGCOORD = 1, + WINED3D_FFP_VS_FOG_DEPTH = 2, + WINED3D_FFP_VS_FOG_RANGE = 3, +}; + +#define WINED3D_FFP_TCI_SHIFT 16 +#define WINED3D_FFP_TCI_MASK 0xff + +#define WINED3D_FFP_LIGHT_TYPE_SHIFT(idx) (3 * (idx)) +#define WINED3D_FFP_LIGHT_TYPE_MASK 0x7 + +struct wined3d_ffp_vs_settings +{ + DWORD light_type : 24; /* MAX_ACTIVE_LIGHTS, 8 * 3 */ + DWORD diffuse_source : 2; + DWORD emission_source : 2; + DWORD ambient_source : 2; + DWORD specular_source : 2; + + DWORD normal : 1; + DWORD normalize : 1; + DWORD lighting : 1; + DWORD localviewer : 1; + DWORD fog_mode : 2; + DWORD texcoords : 8; /* MAX_TEXTURES */ + DWORD padding : 18; + + BYTE texgen[MAX_TEXTURES]; +}; + +struct wined3d_ffp_vs_desc +{ + struct wine_rb_entry entry; + struct wined3d_ffp_vs_settings settings; +}; + +void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si, + struct wined3d_ffp_vs_settings *settings) DECLSPEC_HIDDEN; + struct wined3d { LONG ref; @@ -2567,6 +2611,45 @@ void state_fog_fragpart(struct wined3d_context *context, void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void sampler_texmatrix(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_specularenable(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void transform_world(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void transform_view(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void transform_projection(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void transform_texture(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_ambient(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void viewport_vertexpart(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_clipping(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void light(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_fog_vertexpart(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void vertexdeclaration(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void clipplane(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_psizemin_w(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_psizemin_ext(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_psizemin_arb(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_pointsprite_w(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_pointsprite(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_pscale(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; + BOOL getColorBits(const struct wined3d_format *format, BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize) DECLSPEC_HIDDEN; BOOL getDepthStencilBits(const struct wined3d_format *format, -- 2.11.4.GIT