static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_clip_plane *op = data; cs->state.clip_planes[op->plane_idx] = *op->plane; device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx)); }
static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_shader *op = data; cs->state.shader[op->type] = op->shader; device_invalidate_state(cs->device, STATE_SHADER(op->type)); }
static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_sampler_state *op = data; cs->state.sampler_states[op->sampler_idx][op->state] = op->value; device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx)); }
static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_material *op = data; cs->state.material = *op->material; device_invalidate_state(cs->device, STATE_MATERIAL); }
static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_render_state *op = data; cs->state.render_states[op->state] = op->value; device_invalidate_state(cs->device, STATE_RENDER(op->state)); }
static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_vertex_declaration *op = data; cs->state.vertex_declaration = op->declaration; device_invalidate_state(cs->device, STATE_VDECL); }
static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_shader_resource_view *op = data; cs->state.shader_resource_view[op->type][op->view_idx] = op->view; device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); }
static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_sampler *op = data; cs->state.sampler[op->type][op->sampler_idx] = op->sampler; device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); }
static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_viewport *op = data; cs->state.viewport = *op->viewport; device_invalidate_state(cs->device, STATE_VIEWPORT); }
static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_scissor_rect *op = data; cs->state.scissor_rect = *op->rect; device_invalidate_state(cs->device, STATE_SCISSORRECT); }
static void wined3d_cs_exec_set_render_target(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_render_target *op = data; cs->state.fb->render_targets[op->render_target_idx] = op->render_target; device_invalidate_state(cs->device, STATE_FRAMEBUFFER); }
DWORD CDECL wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod) { DWORD old = texture->lod; TRACE("texture %p, lod %u.\n", texture, lod); /* The d3d9:texture test shows that SetLOD is ignored on non-managed * textures. The call always returns 0, and GetLOD always returns 0. */ if (texture->resource.pool != WINED3D_POOL_MANAGED) { TRACE("Ignoring SetLOD on %s texture, returning 0.\n", debug_d3dpool(texture->resource.pool)); return 0; } if (lod >= texture->level_count) lod = texture->level_count - 1; if (texture->lod != lod) { texture->lod = lod; texture->texture_rgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U; texture->texture_srgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U; if (texture->resource.bind_count) device_invalidate_state(texture->resource.device, STATE_SAMPLER(texture->sampler)); } return old; }
static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_texture_state *op = data; cs->state.texture_states[op->stage][op->state] = op->value; device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state)); }
static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_transform *op = data; cs->state.transforms[op->state] = *op->matrix; if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->gl_info.limits.blends)) device_invalidate_state(cs->device, STATE_TRANSFORM(op->state)); }
static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_stream_source_freq *op = data; struct wined3d_stream_state *stream; stream = &cs->state.streams[op->stream_idx]; stream->frequency = op->frequency; stream->flags = op->flags; device_invalidate_state(cs->device, STATE_STREAMSRC); }
static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) { const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; const struct wined3d_cs_set_texture *op = data; struct wined3d_texture *prev; prev = cs->state.textures[op->stage]; cs->state.textures[op->stage] = op->texture; if (op->texture) { if (InterlockedIncrement(&op->texture->resource.bind_count) == 1) op->texture->sampler = op->stage; if (!prev || op->texture->target != prev->target) device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); if (!prev && op->stage < d3d_info->limits.ffp_blend_stages) { /* The source arguments for color and alpha ops have different * meanings when a NULL texture is bound, so the COLOR_OP and * ALPHA_OP have to be dirtified. */ device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); } } if (prev) { if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage) { unsigned int i; /* Search for other stages the texture is bound to. Shouldn't * happen if applications bind textures to a single stage only. */ TRACE("Searching for other stages the texture is bound to.\n"); for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) { if (cs->state.textures[i] == prev) { TRACE("Texture is also bound to stage %u.\n", i); prev->sampler = i; break; } } } if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages) { device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); } } device_invalidate_state(cs->device, STATE_SAMPLER(op->stage)); }
static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_constant_buffer *op = data; struct wined3d_buffer *prev; prev = cs->state.cb[op->type][op->cb_idx]; cs->state.cb[op->type][op->cb_idx] = op->buffer; if (op->buffer) InterlockedIncrement(&op->buffer->resource.bind_count); if (prev) InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); }
static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_index_buffer *op = data; struct wined3d_buffer *prev; prev = cs->state.index_buffer; cs->state.index_buffer = op->buffer; cs->state.index_format = op->format_id; if (op->buffer) InterlockedIncrement(&op->buffer->resource.bind_count); if (prev) InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_INDEXBUFFER); }
static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_stream_source *op = data; struct wined3d_stream_state *stream; struct wined3d_buffer *prev; stream = &cs->state.streams[op->stream_idx]; prev = stream->buffer; stream->buffer = op->buffer; stream->offset = op->offset; stream->stride = op->stride; if (op->buffer) InterlockedIncrement(&op->buffer->resource.bind_count); if (prev) InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_STREAMSRC); }
/* Context activation is done by the caller. */ static void volume_bind_and_dirtify(const struct wined3d_volume *volume, struct wined3d_context *context) { struct wined3d_texture *container = volume->container; DWORD active_sampler; /* We don't need a specific texture unit, but after binding the texture the current unit is dirty. * Read the unit back instead of switching to 0, this avoids messing around with the state manager's * gl states. The current texture unit should always be a valid one. * * To be more specific, this is tricky because we can implicitly be called * from sampler() in state.c. This means we can't touch anything other than * whatever happens to be the currently active texture, or we would risk * marking already applied sampler states dirty again. */ active_sampler = volume->resource.device->rev_tex_unit_map[context->active_texture]; if (active_sampler != WINED3D_UNMAPPED_STAGE) device_invalidate_state(volume->resource.device, STATE_SAMPLER(active_sampler)); container->texture_ops->texture_bind(container, context, FALSE); }
static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_depth_stencil_view *op = data; struct wined3d_device *device = cs->device; struct wined3d_rendertarget_view *prev; if ((prev = cs->state.fb->depth_stencil)) { struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev); if (prev_surface && (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || prev_surface->flags & SFLAG_DISCARD)) { surface_modify_ds_location(prev_surface, WINED3D_LOCATION_DISCARDED, prev->width, prev->height); if (prev_surface == device->onscreen_depth_stencil) { wined3d_surface_decref(device->onscreen_depth_stencil); device->onscreen_depth_stencil = NULL; } } } cs->fb.depth_stencil = op->view; if (!prev != !op->view) { /* Swapping NULL / non NULL depth stencil affects the depth and tests */ device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE)); device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE)); device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK)); device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); } else if (prev && (prev->format_flags & WINED3DFMT_FLAG_FLOAT) != (op->view->format_flags & WINED3DFMT_FLAG_FLOAT)) { device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); } device_invalidate_state(device, STATE_FRAMEBUFFER); }
static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_depth_stencil *op = data; struct wined3d_device *device = cs->device; struct wined3d_surface *prev; if ((prev = cs->state.fb->depth_stencil)) { if (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || prev->flags & SFLAG_DISCARD) { surface_modify_ds_location(prev, WINED3D_LOCATION_DISCARDED, prev->resource.width, prev->resource.height); if (prev == device->onscreen_depth_stencil) { wined3d_surface_decref(device->onscreen_depth_stencil); device->onscreen_depth_stencil = NULL; } } } cs->fb.depth_stencil = op->depth_stencil; if (!prev != !op->depth_stencil) { /* Swapping NULL / non NULL depth stencil affects the depth and tests */ device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE)); device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE)); device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK)); device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); } else if (prev && prev->resource.format->depth_size != op->depth_stencil->resource.format->depth_size) { device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); } device_invalidate_state(device, STATE_FRAMEBUFFER); }
static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_color_key *op = data; struct wined3d_texture *texture = op->texture; if (op->set) { switch (op->flags) { case WINED3D_CKEY_DST_BLT: texture->async.dst_blt_color_key = op->color_key; texture->async.color_key_flags |= WINED3D_CKEY_DST_BLT; break; case WINED3D_CKEY_DST_OVERLAY: texture->async.dst_overlay_color_key = op->color_key; texture->async.color_key_flags |= WINED3D_CKEY_DST_OVERLAY; break; case WINED3D_CKEY_SRC_BLT: if (texture == cs->state.textures[0]) { device_invalidate_state(cs->device, STATE_COLOR_KEY); if (!(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)) device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE)); } texture->async.src_blt_color_key = op->color_key; texture->async.color_key_flags |= WINED3D_CKEY_SRC_BLT; break; case WINED3D_CKEY_SRC_OVERLAY: texture->async.src_overlay_color_key = op->color_key; texture->async.color_key_flags |= WINED3D_CKEY_SRC_OVERLAY; break; } } else { switch (op->flags) { case WINED3D_CKEY_DST_BLT: texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT; break; case WINED3D_CKEY_DST_OVERLAY: texture->async.color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY; break; case WINED3D_CKEY_SRC_BLT: if (texture == cs->state.textures[0] && texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE)); texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_BLT; break; case WINED3D_CKEY_SRC_OVERLAY: texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY; break; } } }
static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) { const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; const struct wined3d_cs_set_texture *op = data; struct wined3d_texture *prev; BOOL old_use_color_key = FALSE, new_use_color_key = FALSE; prev = cs->state.textures[op->stage]; cs->state.textures[op->stage] = op->texture; if (op->texture) { const struct wined3d_format *new_format = op->texture->resource.format; const struct wined3d_format *old_format = prev ? prev->resource.format : NULL; unsigned int old_fmt_flags = prev ? prev->resource.format_flags : 0; unsigned int new_fmt_flags = op->texture->resource.format_flags; if (InterlockedIncrement(&op->texture->resource.bind_count) == 1) op->texture->sampler = op->stage; if (!prev || op->texture->target != prev->target || !is_same_fixup(new_format->color_fixup, old_format->color_fixup) || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW)) device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); if (!prev && op->stage < d3d_info->limits.ffp_blend_stages) { /* The source arguments for color and alpha ops have different * meanings when a NULL texture is bound, so the COLOR_OP and * ALPHA_OP have to be dirtified. */ device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); } if (!op->stage && op->texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) new_use_color_key = TRUE; } if (prev) { if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage) { unsigned int i; /* Search for other stages the texture is bound to. Shouldn't * happen if applications bind textures to a single stage only. */ TRACE("Searching for other stages the texture is bound to.\n"); for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) { if (cs->state.textures[i] == prev) { TRACE("Texture is also bound to stage %u.\n", i); prev->sampler = i; break; } } } if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages) { device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); } if (!op->stage && prev->async.color_key_flags & WINED3D_CKEY_SRC_BLT) old_use_color_key = TRUE; } device_invalidate_state(cs->device, STATE_SAMPLER(op->stage)); if (new_use_color_key != old_use_color_key) device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE)); if (new_use_color_key) device_invalidate_state(cs->device, STATE_COLOR_KEY); }
/* 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]; struct wined3d_device *device = swapchain->device; 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; RECT win_rect; 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; 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)) { ENTER_GL(); context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, SFLAG_INTEXTURE); glReadBuffer(GL_COLOR_ATTACHMENT0); context_check_fbo_status(context, GL_READ_FRAMEBUFFER); context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL); context_set_draw_buffer(context, GL_BACK); device_invalidate_state(device, STATE_FRAMEBUFFER); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); device_invalidate_state(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE)); device_invalidate_state(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1)); device_invalidate_state(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2)); device_invalidate_state(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3)); glDisable(GL_SCISSOR_TEST); device_invalidate_state(device, STATE_RENDER(WINED3DRS_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"); LEAVE_GL(); } else { 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; ENTER_GL(); context_bind_fbo(context2, GL_FRAMEBUFFER, NULL); /* 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->gl_info, backbuffer); glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, gl_filter); 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. */ glPushAttrib(GL_VIEWPORT_BIT); glViewport(dst_rect->left, win_h - dst_rect->bottom, dst_rect->right, win_h - dst_rect->top); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glBegin(GL_QUADS); /* bottom left */ glTexCoord2f(tex_left, tex_bottom); glVertex2i(-1, -1); /* top left */ glTexCoord2f(tex_left, tex_top); glVertex2i(-1, 1); /* top right */ glTexCoord2f(tex_right, tex_top); glVertex2i(1, 1); /* bottom right */ glTexCoord2f(tex_right, tex_bottom); glVertex2i(1, -1); glEnd(); glPopMatrix(); glPopAttrib(); device->blitter->unset_shader(context->gl_info); checkGLcall("Swapchain present blit(manual)\n"); LEAVE_GL(); context_release(context2); } }