static void wined3d_shader_resource_view_create_texture_view(struct wined3d_shader_resource_view *view, const struct wined3d_shader_resource_view_desc *desc, struct wined3d_texture *texture, const struct wined3d_format *view_format) { const struct wined3d_gl_info *gl_info; struct wined3d_context *context; struct gl_texture *gl_texture; context = context_acquire(texture->resource.device, NULL); gl_info = context->gl_info; if (!gl_info->supported[ARB_TEXTURE_VIEW]) { context_release(context); FIXME("OpenGL implementation does not support texture views.\n"); return; } wined3d_texture_prepare_texture(texture, context, FALSE); gl_texture = wined3d_texture_get_gl_texture(texture, FALSE); gl_info->gl_ops.gl.p_glGenTextures(1, &view->object); GL_EXTCALL(glTextureView(view->object, view->target, gl_texture->name, view_format->glInternal, desc->u.texture.level_idx, desc->u.texture.level_count, desc->u.texture.layer_idx, desc->u.texture.layer_count)); checkGLcall("Create texture view"); context_release(context); }
/* Do not call while under the GL lock. */ static void texture2d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb) { UINT sub_count = texture->level_count * texture->layer_count; struct wined3d_device *device = texture->resource.device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context = NULL; struct gl_texture *gl_tex; BOOL srgb_mode; UINT i; TRACE("texture %p, srgb %#x.\n", texture, srgb); srgb_mode = texture_srgb_mode(texture, srgb); gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, srgb_mode); if (!device->isInDraw) { /* No danger of recursive calls, context_acquire() sets isInDraw to TRUE * when loading offscreen render targets into the texture. */ context = context_acquire(device, NULL); } if (texture->resource.format->id == WINED3DFMT_P8_UINT || texture->resource.format->id == WINED3DFMT_P8_UINT_A8_UNORM) { for (i = 0; i < sub_count; ++i) { struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]); if (palette9_changed(surface)) { TRACE("Reloading surface %p because the d3d8/9 palette was changed.\n", surface); /* TODO: This is not necessarily needed with hw palettized texture support. */ surface_load_location(surface, SFLAG_INSYSMEM, NULL); /* Make sure the texture is reloaded because of the palette * change, this kills performance though :( */ surface_modify_location(surface, SFLAG_INTEXTURE, FALSE); } } } if (gl_tex->dirty) { /* Reload the surfaces if the texture is marked dirty. */ for (i = 0; i < sub_count; ++i) { surface_load(surface_from_resource(texture->sub_resources[i]), srgb_mode); } } else { TRACE("Texture %p not dirty, nothing to do.\n", texture); } /* No longer dirty. */ gl_tex->dirty = FALSE; if (context) context_release(context); }
/* Context activation is done by the caller. */ static HRESULT texture2d_bind(struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info, BOOL srgb) { BOOL set_gl_texture_desc; HRESULT hr; TRACE("texture %p, gl_info %p, srgb %#x.\n", texture, gl_info, srgb); hr = wined3d_texture_bind(texture, gl_info, srgb, &set_gl_texture_desc); if (set_gl_texture_desc && SUCCEEDED(hr)) { UINT sub_count = texture->level_count * texture->layer_count; BOOL srgb_tex = !gl_info->supported[EXT_TEXTURE_SRGB_DECODE] && (texture->flags & WINED3D_TEXTURE_IS_SRGB); struct gl_texture *gl_tex; UINT i; gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, srgb_tex); for (i = 0; i < sub_count; ++i) { struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]); surface_set_texture_name(surface, gl_tex->name, srgb_tex); } /* Conditinal non power of two textures use a different clamping * default. If we're using the GL_WINE_normalized_texrect partial * driver emulation, we're dealing with a GL_TEXTURE_2D texture which * has the address mode set to repeat - something that prevents us * from hitting the accelerated codepath. Thus manually set the GL * state. The same applies to filtering. Even if the texture has only * one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW * fallback on macos. */ if (texture->flags & WINED3D_TEXTURE_COND_NP2) { GLenum target = texture->target; ENTER_GL(); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGLcall("glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)"); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGLcall("glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)"); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGLcall("glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)"); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGLcall("glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)"); LEAVE_GL(); gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3DTADDRESS_CLAMP; gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3DTADDRESS_CLAMP; gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE; } } return hr; }
/* Do not call while under the GL lock. */ static void texture2d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb) { UINT sub_count = texture->level_count * texture->layer_count; struct wined3d_device *device = texture->resource.device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context = NULL; struct gl_texture *gl_tex; BOOL srgb_mode; UINT i; TRACE("texture %p, srgb %#x.\n", texture, srgb); srgb_mode = texture_srgb_mode(texture, srgb); gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, srgb_mode); if (!device->isInDraw) { /* No danger of recursive calls, context_acquire() sets isInDraw to TRUE * when loading offscreen render targets into the texture. */ context = context_acquire(device, NULL); } if (gl_tex->dirty) { /* Reload the surfaces if the texture is marked dirty. */ for (i = 0; i < sub_count; ++i) { surface_load(surface_from_resource(texture->sub_resources[i]), srgb_mode); } } else { TRACE("Texture %p not dirty, nothing to do.\n", texture); } /* No longer dirty. */ gl_tex->dirty = FALSE; if (context) context_release(context); }
static void texture_apply_base_level(struct wined3d_texture *texture, const struct wined3d_sampler_desc *desc, const struct wined3d_gl_info *gl_info) { struct gl_texture *gl_tex; unsigned int base_level; if (texture->flags & WINED3D_TEXTURE_COND_NP2) base_level = 0; else if (desc->mip_filter == WINED3D_TEXF_NONE) base_level = texture->lod; else base_level = min(max(desc->mip_base_level, texture->lod), texture->level_count - 1); gl_tex = wined3d_texture_get_gl_texture(texture, texture->flags & WINED3D_TEXTURE_IS_SRGB); if (base_level != gl_tex->base_level) { /* Note that WINED3D_SAMP_MAX_MIP_LEVEL specifies the largest mipmap * (default 0), while GL_TEXTURE_MAX_LEVEL specifies the smallest * mipmap used (default 1000). So WINED3D_SAMP_MAX_MIP_LEVEL * corresponds to GL_TEXTURE_BASE_LEVEL. */ gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, base_level); gl_tex->base_level = base_level; } }
void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) { struct wined3d_texture *texture = texture_from_resource(view->resource); unsigned int i, j, layer_count, level_count, base_level, max_level; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; struct gl_texture *gl_tex; DWORD location; BOOL srgb; TRACE("view %p.\n", view); context = context_acquire(view->resource->device, NULL, 0); gl_info = context->gl_info; layer_count = view->desc.u.texture.layer_count; level_count = view->desc.u.texture.level_count; base_level = view->desc.u.texture.level_idx; max_level = base_level + level_count - 1; srgb = !!(texture->flags & WINED3D_TEXTURE_IS_SRGB); location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; for (i = 0; i < layer_count; ++i) wined3d_texture_load_location(texture, i * level_count + base_level, context, location); if (view->gl_view.name) { shader_resource_view_bind_and_dirtify(view, context); } else { wined3d_texture_bind_and_dirtify(texture, context, srgb); gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, base_level); gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, max_level); } if (gl_info->supported[ARB_SAMPLER_OBJECTS]) GL_EXTCALL(glBindSampler(context->active_texture, 0)); gl_tex = wined3d_texture_get_gl_texture(texture, srgb); if (context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) { gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); gl_tex->sampler_desc.srgb_decode = FALSE; } gl_info->fbo_ops.glGenerateMipmap(texture->target); checkGLcall("glGenerateMipMap()"); for (i = 0; i < layer_count; ++i) { for (j = base_level + 1; j <= max_level; ++j) { wined3d_texture_validate_location(texture, i * level_count + j, location); wined3d_texture_invalidate_location(texture, i * level_count + j, ~location); } } if (!view->gl_view.name) { gl_tex->base_level = base_level; gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1); } context_release(context); }
/* 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; } } }
/* Context activation is done by the caller. */ static HRESULT wined3d_texture_bind(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb, BOOL *set_surface_desc) { const struct wined3d_gl_info *gl_info = context->gl_info; struct gl_texture *gl_tex; BOOL new_texture = FALSE; HRESULT hr = WINED3D_OK; GLenum target; TRACE("texture %p, context %p, srgb %#x, set_surface_desc %p.\n", texture, context, srgb, set_surface_desc); /* sRGB mode cache for preload() calls outside drawprim. */ if (srgb) texture->flags |= WINED3D_TEXTURE_IS_SRGB; else texture->flags &= ~WINED3D_TEXTURE_IS_SRGB; gl_tex = wined3d_texture_get_gl_texture(texture, context->gl_info, srgb); target = texture->target; /* Generate a texture name if we don't already have one. */ if (!gl_tex->name) { *set_surface_desc = TRUE; gl_info->gl_ops.gl.p_glGenTextures(1, &gl_tex->name); checkGLcall("glGenTextures"); TRACE("Generated texture %d.\n", gl_tex->name); if (texture->resource.pool == WINED3D_POOL_DEFAULT) { /* Tell OpenGL to try and keep this texture in video ram (well mostly). */ GLclampf tmp = 0.9f; gl_info->gl_ops.gl.p_glPrioritizeTextures(1, &gl_tex->name, &tmp); } /* Initialise the state of the texture object to the OpenGL defaults, * not the D3D defaults. */ gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP; gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP; gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP; gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0; gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR; gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */ gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */ gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0; gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1; if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE; else gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = srgb; gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE; wined3d_texture_set_dirty(texture, TRUE); new_texture = TRUE; if (texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP) { /* This means double binding the texture at creation, but keeps * the code simpler all in all, and the run-time path free from * additional checks. */ context_bind_texture(context, target, gl_tex->name); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); checkGLcall("glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)"); } } else { *set_surface_desc = FALSE; } if (gl_tex->name) { context_bind_texture(context, target, gl_tex->name); if (new_texture) { /* For a new texture we have to set the texture levels after * binding the texture. Beware that texture rectangles do not * support mipmapping, but set the maxmiplevel if we're relying * on the partial GL_ARB_texture_non_power_of_two emulation with * texture rectangles. (I.e., do not care about cond_np2 here, * just look for GL_TEXTURE_RECTANGLE_ARB.) */ if (target != GL_TEXTURE_RECTANGLE_ARB) { TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", texture->level_count - 1); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1); checkGLcall("glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count)"); } if (target == GL_TEXTURE_CUBE_MAP_ARB) { /* Cubemaps are always set to clamp, regardless of the sampler state. */ gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); } } } else { ERR("This texture doesn't have an OpenGL texture assigned to it.\n"); hr = WINED3DERR_INVALIDCALL; } return hr; }
/* Context activation is done by the caller. */ void wined3d_texture_bind(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) { const struct wined3d_gl_info *gl_info = context->gl_info; struct gl_texture *gl_tex; GLenum target; TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb); if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) srgb = FALSE; /* sRGB mode cache for preload() calls outside drawprim. */ if (srgb) texture->flags |= WINED3D_TEXTURE_IS_SRGB; else texture->flags &= ~WINED3D_TEXTURE_IS_SRGB; gl_tex = wined3d_texture_get_gl_texture(texture, srgb); target = texture->target; if (gl_tex->name) { context_bind_texture(context, target, gl_tex->name); return; } gl_info->gl_ops.gl.p_glGenTextures(1, &gl_tex->name); checkGLcall("glGenTextures"); TRACE("Generated texture %d.\n", gl_tex->name); if (!gl_tex->name) { ERR("Failed to generate a texture name.\n"); return; } if (texture->resource.pool == WINED3D_POOL_DEFAULT) { /* Tell OpenGL to try and keep this texture in video ram (well mostly). */ GLclampf tmp = 0.9f; gl_info->gl_ops.gl.p_glPrioritizeTextures(1, &gl_tex->name, &tmp); } /* Initialise the state of the texture object to the OpenGL defaults, not * the wined3d defaults. */ gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP; gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP; gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP; gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0; gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR; gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */ gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */ gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0; gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1; if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE; else gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = srgb; gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE; wined3d_texture_set_dirty(texture); context_bind_texture(context, target, gl_tex->name); if (texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP) { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); checkGLcall("glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)"); } /* For a new texture we have to set the texture levels after binding the * texture. Beware that texture rectangles do not support mipmapping, but * set the maxmiplevel if we're relying on the partial * GL_ARB_texture_non_power_of_two emulation with texture rectangles. * (I.e., do not care about cond_np2 here, just look for * GL_TEXTURE_RECTANGLE_ARB.) */ if (target != GL_TEXTURE_RECTANGLE_ARB) { TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", texture->level_count - 1); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1); checkGLcall("glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count)"); } if (target == GL_TEXTURE_CUBE_MAP_ARB) { /* Cubemaps are always set to clamp, regardless of the sampler state. */ gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); } if (texture->flags & WINED3D_TEXTURE_COND_NP2) { /* Conditinal non power of two textures use a different clamping * default. If we're using the GL_WINE_normalized_texrect partial * driver emulation, we're dealing with a GL_TEXTURE_2D texture which * has the address mode set to repeat - something that prevents us * from hitting the accelerated codepath. Thus manually set the GL * state. The same applies to filtering. Even if the texture has only * one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW * fallback on macos. */ gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGLcall("glTexParameteri"); gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_CLAMP; gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_CLAMP; gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT; gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE; } }