void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view, unsigned int unit, struct wined3d_sampler *sampler, struct wined3d_context *context) { const struct wined3d_gl_info *gl_info = context->gl_info; struct wined3d_texture *texture; context_active_texture(context, gl_info, unit); if (view->gl_view.name) { context_bind_texture(context, view->gl_view.target, view->gl_view.name); wined3d_sampler_bind(sampler, unit, NULL, context); return; } if (view->resource->type == WINED3D_RTYPE_BUFFER) { FIXME("Buffer shader resources not supported.\n"); return; } texture = wined3d_texture_from_resource(view->resource); wined3d_texture_bind(texture, context, FALSE); wined3d_sampler_bind(sampler, unit, texture, context); }
/* Context activation is done by the caller. */ static void shader_resource_view_bind_and_dirtify(struct wined3d_shader_resource_view *view, struct wined3d_context *context) { if (context->active_texture < ARRAY_SIZE(context->rev_tex_unit_map)) { DWORD active_sampler = context->rev_tex_unit_map[context->active_texture]; if (active_sampler != WINED3D_UNMAPPED_STAGE) context_invalidate_state(context, STATE_SAMPLER(active_sampler)); } /* FIXME: Ideally we'd only do this when touching a binding that's used by * a shader. */ context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING); context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); context_bind_texture(context, view->gl_view.target, view->gl_view.name); }
void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view, struct wined3d_context *context) { struct wined3d_texture *texture; if (view->object) { context_bind_texture(context, view->target, view->object); return; } if (view->resource->type == WINED3D_RTYPE_BUFFER) { FIXME("Buffer shader resources not supported.\n"); return; } texture = wined3d_texture_from_resource(view->resource); wined3d_texture_bind(texture, context, FALSE); }
static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_context *context, struct wined3d_buffer *buffer, const struct wined3d_format *view_format, unsigned int offset, unsigned int size) { const struct wined3d_gl_info *gl_info = context->gl_info; if (!gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT]) { FIXME("OpenGL implementation does not support buffer textures.\n"); return; } if ((offset & (gl_info->limits.texture_buffer_offset_alignment - 1))) { FIXME("Buffer offset %u is not %u byte aligned.\n", offset, gl_info->limits.texture_buffer_offset_alignment); return; } wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER); view->target = GL_TEXTURE_BUFFER; gl_info->gl_ops.gl.p_glGenTextures(1, &view->name); context_bind_texture(context, GL_TEXTURE_BUFFER, view->name); if (gl_info->supported[ARB_TEXTURE_BUFFER_RANGE]) { GL_EXTCALL(glTexBufferRange(GL_TEXTURE_BUFFER, view_format->glInternal, buffer->buffer_object, offset, size)); } else { if (offset || size != buffer->resource.size) FIXME("OpenGL implementation does not support ARB_texture_buffer_range.\n"); GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, view_format->glInternal, buffer->buffer_object)); } checkGLcall("Create buffer texture"); context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING); context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); }
/* A GL context is provided by the caller */ static void swapchain_blit(const struct wined3d_swapchain *swapchain, struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect) { struct wined3d_surface *backbuffer = swapchain->back_buffers[0]; UINT src_w = src_rect->right - src_rect->left; UINT src_h = src_rect->bottom - src_rect->top; GLenum gl_filter; const struct wined3d_gl_info *gl_info = context->gl_info; UINT win_h; TRACE("swapchain %p, context %p, src_rect %s, dst_rect %s.\n", swapchain, context, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect)); if (src_w == dst_rect->right - dst_rect->left && src_h == dst_rect->bottom - dst_rect->top) gl_filter = GL_NEAREST; else gl_filter = GL_LINEAR; if (context->surface && !swapchain->desc.windowed) win_h = swapchain->front_buffer->resource.height; else { RECT win_rect; GetClientRect(swapchain->win_handle, &win_rect); win_h = win_rect.bottom - win_rect.top; } if (gl_info->fbo_ops.glBlitFramebuffer && is_identity_fixup(backbuffer->resource.format->color_fixup)) { DWORD location = WINED3D_LOCATION_TEXTURE_RGB; if (backbuffer->resource.multisample_type) { location = WINED3D_LOCATION_RB_RESOLVED; surface_load_location(backbuffer, location); } context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0); context_check_fbo_status(context, GL_READ_FRAMEBUFFER); context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, swapchain->front_buffer, NULL, WINED3D_LOCATION_DRAWABLE); context_set_draw_buffer(context, GL_BACK); context_invalidate_state(context, STATE_FRAMEBUFFER); gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE)); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1)); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2)); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3)); gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE)); /* Note that the texture is upside down */ gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, dst_rect->left, win_h - dst_rect->top, dst_rect->right, win_h - dst_rect->bottom, GL_COLOR_BUFFER_BIT, gl_filter); checkGLcall("Swapchain present blit(EXT_framebuffer_blit)\n"); } else { struct wined3d_device *device = swapchain->device; struct wined3d_context *context2; float tex_left = src_rect->left; float tex_top = src_rect->top; float tex_right = src_rect->right; float tex_bottom = src_rect->bottom; context2 = context_acquire(device, swapchain->back_buffers[0]); context_apply_blit_state(context2, device); if (backbuffer->flags & SFLAG_NORMCOORD) { tex_left /= src_w; tex_right /= src_w; tex_top /= src_h; tex_bottom /= src_h; } if (is_complex_fixup(backbuffer->resource.format->color_fixup)) gl_filter = GL_NEAREST; context_apply_fbo_state_blit(context2, GL_FRAMEBUFFER, swapchain->front_buffer, NULL, WINED3D_LOCATION_DRAWABLE); context_bind_texture(context2, backbuffer->texture_target, backbuffer->container->texture_rgb.name); /* Set up the texture. The surface is not in a wined3d_texture * container, so there are no D3D texture settings to dirtify. */ device->blitter->set_shader(device->blit_priv, context2, backbuffer); gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, gl_filter); gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MAG_FILTER, gl_filter); context_set_draw_buffer(context, GL_BACK); /* Set the viewport to the destination rectandle, disable any projection * transformation set up by context_apply_blit_state(), and draw a * (-1,-1)-(1,1) quad. * * Back up viewport and matrix to avoid breaking last_was_blit * * Note that context_apply_blit_state() set up viewport and ortho to * match the surface size - we want the GL drawable(=window) size. */ gl_info->gl_ops.gl.p_glPushAttrib(GL_VIEWPORT_BIT); gl_info->gl_ops.gl.p_glViewport(dst_rect->left, win_h - dst_rect->bottom, dst_rect->right, win_h - dst_rect->top); gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION); gl_info->gl_ops.gl.p_glPushMatrix(); gl_info->gl_ops.gl.p_glLoadIdentity(); gl_info->gl_ops.gl.p_glBegin(GL_QUADS); /* bottom left */ gl_info->gl_ops.gl.p_glTexCoord2f(tex_left, tex_bottom); gl_info->gl_ops.gl.p_glVertex2i(-1, -1); /* top left */ gl_info->gl_ops.gl.p_glTexCoord2f(tex_left, tex_top); gl_info->gl_ops.gl.p_glVertex2i(-1, 1); /* top right */ gl_info->gl_ops.gl.p_glTexCoord2f(tex_right, tex_top); gl_info->gl_ops.gl.p_glVertex2i(1, 1); /* bottom right */ gl_info->gl_ops.gl.p_glTexCoord2f(tex_right, tex_bottom); gl_info->gl_ops.gl.p_glVertex2i(1, -1); gl_info->gl_ops.gl.p_glEnd(); gl_info->gl_ops.gl.p_glPopMatrix(); gl_info->gl_ops.gl.p_glPopAttrib(); device->blitter->unset_shader(context->gl_info); checkGLcall("Swapchain present blit(manual)\n"); context_release(context2); } }
static void create_texture_view(struct wined3d_gl_view *view, GLenum view_target, const struct wined3d_view_desc *desc, struct wined3d_texture *texture, const struct wined3d_format *view_format) { const struct wined3d_gl_info *gl_info; unsigned int layer_idx, layer_count; struct wined3d_context *context; GLuint texture_name; view->target = view_target; context = context_acquire(texture->resource.device, NULL, 0); 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); texture_name = wined3d_texture_get_texture_name(texture, context, FALSE); layer_idx = desc->u.texture.layer_idx; layer_count = desc->u.texture.layer_count; if (view_target == GL_TEXTURE_3D && (layer_idx || layer_count != 1)) { FIXME("Depth slice (%u-%u) not supported.\n", layer_idx, layer_count); layer_idx = 0; layer_count = 1; } gl_info->gl_ops.gl.p_glGenTextures(1, &view->name); GL_EXTCALL(glTextureView(view->name, view->target, texture_name, view_format->glInternal, desc->u.texture.level_idx, desc->u.texture.level_count, layer_idx, layer_count)); checkGLcall("Create texture view"); if (is_stencil_view_format(view_format)) { static const GLint swizzle[] = {GL_ZERO, GL_RED, GL_ZERO, GL_ZERO}; if (!gl_info->supported[ARB_STENCIL_TEXTURING]) { context_release(context); FIXME("OpenGL implementation does not support stencil texturing.\n"); return; } context_bind_texture(context, view->target, view->name); gl_info->gl_ops.gl.p_glTexParameteriv(view->target, GL_TEXTURE_SWIZZLE_RGBA, swizzle); gl_info->gl_ops.gl.p_glTexParameteri(view->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); checkGLcall("Initialize stencil view"); context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING); context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); } context_release(context); }
/* 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; } }