+
+void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args) {
+ args->fog_src = stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
+ args->swizzle_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.swizzle_map;
+}
+
+static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
+ const DWORD use_map) {
+ if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE;
+ return stored->fog_src == new->fog_src;
+}
+
+GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
+{
+ UINT i;
+ DWORD new_size = shader->shader_array_size;
+ struct vs_compiled_shader *new_array;
+ DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
+
+ /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
+ * so a linear search is more performant than a hashmap or a binary search
+ * (cache coherency etc)
+ */
+ for(i = 0; i < shader->num_gl_shaders; i++) {
+ if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) {
+ return shader->gl_shaders[i].prgId;
+ }
+ }
+
+ TRACE("No matching GL shader found, compiling a new shader\n");
+
+ if(shader->shader_array_size == shader->num_gl_shaders) {
+ if(shader->gl_shaders) {
+ new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
+ new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
+ new_size * sizeof(*shader->gl_shaders));
+ } else {
+ new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
+ new_size = 1;
+ }
+
+ if(!new_array) {
+ ERR("Out of memory\n");
+ return 0;
+ }
+ shader->gl_shaders = new_array;
+ shader->shader_array_size = new_size;
+ }
+
+ shader->gl_shaders[shader->num_gl_shaders].args = *args;
+ shader->gl_shaders[shader->num_gl_shaders].prgId = vertexshader_compile(shader, args);
+ return shader->gl_shaders[shader->num_gl_shaders++].prgId;
+}