static void wined3d_sampler_init(struct wined3d_sampler *sampler, struct wined3d_device *device, const struct wined3d_sampler_desc *desc, void *parent) { const struct wined3d_gl_info *gl_info; struct wined3d_context *context; sampler->refcount = 1; sampler->device = device; sampler->parent = parent; sampler->desc = *desc; context = context_acquire(device, NULL); gl_info = context->gl_info; GL_EXTCALL(glGenSamplers(1, &sampler->name)); GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_WRAP_S, gl_info->wrap_lookup[desc->address_u - WINED3D_TADDRESS_WRAP])); GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_WRAP_T, gl_info->wrap_lookup[desc->address_v - WINED3D_TADDRESS_WRAP])); GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_WRAP_R, gl_info->wrap_lookup[desc->address_w - WINED3D_TADDRESS_WRAP])); GL_EXTCALL(glSamplerParameterfv(sampler->name, GL_TEXTURE_BORDER_COLOR, &desc->border_color[0])); GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_MAG_FILTER, wined3d_gl_mag_filter(desc->mag_filter))); GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_MIN_FILTER, wined3d_gl_min_mip_filter(desc->min_filter, desc->mip_filter))); GL_EXTCALL(glSamplerParameterf(sampler->name, GL_TEXTURE_LOD_BIAS, desc->lod_bias)); GL_EXTCALL(glSamplerParameterf(sampler->name, GL_TEXTURE_MIN_LOD, desc->min_lod)); GL_EXTCALL(glSamplerParameterf(sampler->name, GL_TEXTURE_MAX_LOD, desc->max_lod)); if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_MAX_ANISOTROPY_EXT, desc->max_anisotropy)); if (desc->compare) GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE)); GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_COMPARE_FUNC, wined3d_gl_compare_func(desc->comparison_func))); if ((context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) && gl_info->supported[EXT_TEXTURE_SRGB_DECODE] && !desc->srgb_decode) GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)); checkGLcall("sampler creation"); TRACE("Created sampler %u.\n", sampler->name); context_release(context); }
/* GL locking is done by the caller (state handler) */ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1], const struct wined3d_gl_info *gl_info) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; GLenum textureDimensions = This->baseTexture.target; DWORD state; BOOL cond_np2 = IWineD3DBaseTexture_IsCondNP2(iface); DWORD aniso; struct gl_texture *gl_tex; TRACE("iface %p, samplerStates %p\n", iface, samplerStates); if(This->baseTexture.is_srgb) { gl_tex = &This->baseTexture.texture_srgb; } else { gl_tex = &This->baseTexture.texture_rgb; } /* This function relies on the correct texture being bound and loaded. */ if(samplerStates[WINED3DSAMP_ADDRESSU] != gl_tex->states[WINED3DTEXSTA_ADDRESSU]) { state = samplerStates[WINED3DSAMP_ADDRESSU]; apply_wrap(gl_info, textureDimensions, state, GL_TEXTURE_WRAP_S, cond_np2); gl_tex->states[WINED3DTEXSTA_ADDRESSU] = state; } if(samplerStates[WINED3DSAMP_ADDRESSV] != gl_tex->states[WINED3DTEXSTA_ADDRESSV]) { state = samplerStates[WINED3DSAMP_ADDRESSV]; apply_wrap(gl_info, textureDimensions, state, GL_TEXTURE_WRAP_T, cond_np2); gl_tex->states[WINED3DTEXSTA_ADDRESSV] = state; } if(samplerStates[WINED3DSAMP_ADDRESSW] != gl_tex->states[WINED3DTEXSTA_ADDRESSW]) { state = samplerStates[WINED3DSAMP_ADDRESSW]; apply_wrap(gl_info, textureDimensions, state, GL_TEXTURE_WRAP_R, cond_np2); gl_tex->states[WINED3DTEXSTA_ADDRESSW] = state; } if(samplerStates[WINED3DSAMP_BORDERCOLOR] != gl_tex->states[WINED3DTEXSTA_BORDERCOLOR]) { float col[4]; state = samplerStates[WINED3DSAMP_BORDERCOLOR]; D3DCOLORTOGLFLOAT4(state, col); TRACE("Setting border color for %u to %x\n", textureDimensions, state); glTexParameterfv(textureDimensions, GL_TEXTURE_BORDER_COLOR, &col[0]); checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)"); gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = state; } if(samplerStates[WINED3DSAMP_MAGFILTER] != gl_tex->states[WINED3DTEXSTA_MAGFILTER]) { GLint glValue; state = samplerStates[WINED3DSAMP_MAGFILTER]; if (state > WINED3DTEXF_ANISOTROPIC) { FIXME("Unrecognized or unsupported MAGFILTER* value %d\n", state); } glValue = wined3d_gl_mag_filter(This->baseTexture.magLookup, min(max(state, WINED3DTEXF_POINT), WINED3DTEXF_LINEAR)); TRACE("ValueMAG=%d setting MAGFILTER to %x\n", state, glValue); glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue); gl_tex->states[WINED3DTEXSTA_MAGFILTER] = state; } if((samplerStates[WINED3DSAMP_MINFILTER] != gl_tex->states[WINED3DTEXSTA_MINFILTER] || samplerStates[WINED3DSAMP_MIPFILTER] != gl_tex->states[WINED3DTEXSTA_MIPFILTER] || samplerStates[WINED3DSAMP_MAXMIPLEVEL] != gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL])) { GLint glValue; gl_tex->states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER]; gl_tex->states[WINED3DTEXSTA_MINFILTER] = samplerStates[WINED3DSAMP_MINFILTER]; gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = samplerStates[WINED3DSAMP_MAXMIPLEVEL]; if (gl_tex->states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC || gl_tex->states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_ANISOTROPIC) { FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d D3DSAMP_MIPFILTER value %d\n", gl_tex->states[WINED3DTEXSTA_MINFILTER], gl_tex->states[WINED3DTEXSTA_MIPFILTER]); } glValue = wined3d_gl_min_mip_filter(This->baseTexture.minMipLookup, min(max(samplerStates[WINED3DSAMP_MINFILTER], WINED3DTEXF_POINT), WINED3DTEXF_LINEAR), min(max(samplerStates[WINED3DSAMP_MIPFILTER], WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)); TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", samplerStates[WINED3DSAMP_MINFILTER], samplerStates[WINED3DSAMP_MIPFILTER], glValue); glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue); checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ..."); if (!cond_np2) { if (gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) glValue = This->baseTexture.LOD; else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.level_count) glValue = This->baseTexture.level_count - 1; else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < This->baseTexture.LOD) /* baseTexture.LOD is already clamped in the setter */ glValue = This->baseTexture.LOD; else glValue = gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL]; /* Note that D3DSAMP_MAXMIPLEVEL specifies the biggest mipmap(default 0), while * GL_TEXTURE_MAX_LEVEL specifies the smallest mimap used(default 1000). * So D3DSAMP_MAXMIPLEVEL is the same as GL_TEXTURE_BASE_LEVEL. */ glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, glValue); } } if ((gl_tex->states[WINED3DTEXSTA_MAGFILTER] != WINED3DTEXF_ANISOTROPIC && gl_tex->states[WINED3DTEXSTA_MINFILTER] != WINED3DTEXF_ANISOTROPIC && gl_tex->states[WINED3DTEXSTA_MIPFILTER] != WINED3DTEXF_ANISOTROPIC) || cond_np2) { aniso = 1; } else { aniso = samplerStates[WINED3DSAMP_MAXANISOTROPY]; } if (gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] != aniso) { if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) { glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); checkGLcall("glTexParameteri(GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso)"); } else { WARN("Anisotropic filtering not supported.\n"); } gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso; } if (!(This->resource.format->Flags & WINED3DFMT_FLAG_SHADOW) != !gl_tex->states[WINED3DTEXSTA_SHADOW]) { if (This->resource.format->Flags & WINED3DFMT_FLAG_SHADOW) { glTexParameteri(textureDimensions, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB)"); gl_tex->states[WINED3DTEXSTA_SHADOW] = TRUE; } else { glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE)"); gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE; } } }
/* Context activation is done by the caller (state handler). */ void wined3d_texture_apply_state_changes(struct wined3d_texture *texture, const DWORD sampler_states[WINED3D_HIGHEST_SAMPLER_STATE + 1], const struct wined3d_gl_info *gl_info) { BOOL cond_np2 = texture->flags & WINED3D_TEXTURE_COND_NP2; GLenum target = texture->target; struct gl_texture *gl_tex; DWORD state; DWORD aniso; TRACE("texture %p, sampler_states %p.\n", texture, sampler_states); gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, texture->flags & WINED3D_TEXTURE_IS_SRGB); /* This function relies on the correct texture being bound and loaded. */ if (sampler_states[WINED3D_SAMP_ADDRESS_U] != gl_tex->states[WINED3DTEXSTA_ADDRESSU]) { state = sampler_states[WINED3D_SAMP_ADDRESS_U]; apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_S, cond_np2); gl_tex->states[WINED3DTEXSTA_ADDRESSU] = state; } if (sampler_states[WINED3D_SAMP_ADDRESS_V] != gl_tex->states[WINED3DTEXSTA_ADDRESSV]) { state = sampler_states[WINED3D_SAMP_ADDRESS_V]; apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_T, cond_np2); gl_tex->states[WINED3DTEXSTA_ADDRESSV] = state; } if (sampler_states[WINED3D_SAMP_ADDRESS_W] != gl_tex->states[WINED3DTEXSTA_ADDRESSW]) { state = sampler_states[WINED3D_SAMP_ADDRESS_W]; apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_R, cond_np2); gl_tex->states[WINED3DTEXSTA_ADDRESSW] = state; } if (sampler_states[WINED3D_SAMP_BORDER_COLOR] != gl_tex->states[WINED3DTEXSTA_BORDERCOLOR]) { float col[4]; state = sampler_states[WINED3D_SAMP_BORDER_COLOR]; D3DCOLORTOGLFLOAT4(state, col); TRACE("Setting border color for %#x to %#x.\n", target, state); gl_info->gl_ops.gl.p_glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, &col[0]); checkGLcall("glTexParameterfv(..., GL_TEXTURE_BORDER_COLOR, ...)"); gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = state; } if (sampler_states[WINED3D_SAMP_MAG_FILTER] != gl_tex->states[WINED3DTEXSTA_MAGFILTER]) { GLint gl_value; state = sampler_states[WINED3D_SAMP_MAG_FILTER]; if (state > WINED3D_TEXF_ANISOTROPIC) FIXME("Unrecognized or unsupported MAGFILTER* value %d.\n", state); gl_value = wined3d_gl_mag_filter(texture->mag_lookup, min(max(state, WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR)); TRACE("ValueMAG=%#x setting MAGFILTER to %#x.\n", state, gl_value); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, gl_value); gl_tex->states[WINED3DTEXSTA_MAGFILTER] = state; } if ((sampler_states[WINED3D_SAMP_MIN_FILTER] != gl_tex->states[WINED3DTEXSTA_MINFILTER] || sampler_states[WINED3D_SAMP_MIP_FILTER] != gl_tex->states[WINED3DTEXSTA_MIPFILTER] || sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL] != gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL])) { GLint gl_value; gl_tex->states[WINED3DTEXSTA_MIPFILTER] = sampler_states[WINED3D_SAMP_MIP_FILTER]; gl_tex->states[WINED3DTEXSTA_MINFILTER] = sampler_states[WINED3D_SAMP_MIN_FILTER]; gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL]; if (gl_tex->states[WINED3DTEXSTA_MINFILTER] > WINED3D_TEXF_ANISOTROPIC || gl_tex->states[WINED3DTEXSTA_MIPFILTER] > WINED3D_TEXF_ANISOTROPIC) { FIXME("Unrecognized or unsupported MIN_FILTER value %#x MIP_FILTER value %#x.\n", gl_tex->states[WINED3DTEXSTA_MINFILTER], gl_tex->states[WINED3DTEXSTA_MIPFILTER]); } gl_value = wined3d_gl_min_mip_filter(texture->min_mip_lookup, min(max(sampler_states[WINED3D_SAMP_MIN_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR), min(max(sampler_states[WINED3D_SAMP_MIP_FILTER], WINED3D_TEXF_NONE), WINED3D_TEXF_LINEAR)); TRACE("ValueMIN=%#x, ValueMIP=%#x, setting MINFILTER to %#x.\n", sampler_states[WINED3D_SAMP_MIN_FILTER], sampler_states[WINED3D_SAMP_MIP_FILTER], gl_value); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, gl_value); checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ..."); if (!cond_np2) { if (gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3D_TEXF_NONE) gl_value = texture->lod; else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= texture->level_count) gl_value = texture->level_count - 1; else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < texture->lod) /* texture->lod is already clamped in the setter. */ gl_value = texture->lod; else gl_value = gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL]; /* Note that WINED3D_SAMP_MAX_MIP_LEVEL specifies the largest mipmap * (default 0), while GL_TEXTURE_MAX_LEVEL specifies the smallest * mimap used (default 1000). So WINED3D_SAMP_MAX_MIP_LEVEL * corresponds to GL_TEXTURE_BASE_LEVEL. */ gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, gl_value); } } if ((gl_tex->states[WINED3DTEXSTA_MAGFILTER] != WINED3D_TEXF_ANISOTROPIC && gl_tex->states[WINED3DTEXSTA_MINFILTER] != WINED3D_TEXF_ANISOTROPIC && gl_tex->states[WINED3DTEXSTA_MIPFILTER] != WINED3D_TEXF_ANISOTROPIC) || cond_np2) aniso = 1; else aniso = sampler_states[WINED3D_SAMP_MAX_ANISOTROPY]; if (gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] != aniso) { if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); checkGLcall("glTexParameteri(GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso)"); } else { WARN("Anisotropic filtering not supported.\n"); } gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso; } /* These should always be the same unless EXT_texture_sRGB_decode is supported. */ if (sampler_states[WINED3D_SAMP_SRGB_TEXTURE] != gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE]) { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, sampler_states[WINED3D_SAMP_SRGB_TEXTURE] ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT); checkGLcall("glTexParameteri(GL_TEXTURE_SRGB_DECODE_EXT)"); gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = sampler_states[WINED3D_SAMP_SRGB_TEXTURE]; } if (!(texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW) != !gl_tex->states[WINED3DTEXSTA_SHADOW]) { if (texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW) { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); checkGLcall("glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB)"); gl_tex->states[WINED3DTEXSTA_SHADOW] = TRUE; } else { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); checkGLcall("glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE)"); gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE; } } }