From 740b727a94f3bf7e3e120f84b8ea21b1758bd3a2 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 6 Jan 2016 21:38:47 +0100 Subject: [PATCH] patchupdate.py: Generate #ifdef patches in alphabetical order. (cherry picked from commit 0a5887e4836f56d0a0bc30c2718f652327e32178) --- .../wined3d-CSMT_Main/9999-IfDefined.patch | 10120 ++++++++-------- staging/patchupdate.py | 2 +- 2 files changed, 5061 insertions(+), 5061 deletions(-) diff --git a/patches/wined3d-CSMT_Main/9999-IfDefined.patch b/patches/wined3d-CSMT_Main/9999-IfDefined.patch index dca9f00f..571a187e 100644 --- a/patches/wined3d-CSMT_Main/9999-IfDefined.patch +++ b/patches/wined3d-CSMT_Main/9999-IfDefined.patch @@ -1,443 +1,6 @@ From: Wine Staging Team Subject: Autogenerated #ifdef patch for wined3d-CSMT_Main. -diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c ---- a/dlls/wined3d/swapchain.c -+++ b/dlls/wined3d/swapchain.c -@@ -320,7 +320,11 @@ - if (backbuffer->resource.multisample_type) - { - location = WINED3D_LOCATION_RB_RESOLVED; -+#if defined(STAGING_CSMT) - wined3d_resource_load_location(&backbuffer->resource, context, location); -+#else /* STAGING_CSMT */ -+ surface_load_location(backbuffer, context, location); -+#endif /* STAGING_CSMT */ - } - - context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); -@@ -428,11 +432,19 @@ - } - - static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, -+#if defined(STAGING_CSMT) - const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags, - struct wined3d_surface *depth_stencil) - { - struct wined3d_surface *back_buffer = surface_from_resource( - wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)); -+#else /* STAGING_CSMT */ -+ const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) -+{ -+ struct wined3d_surface *back_buffer = surface_from_resource( -+ wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)); -+ const struct wined3d_fb_state *fb = &swapchain->device->fb; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; - struct wined3d_surface *front; -@@ -460,6 +472,37 @@ - NULL, WINED3D_TEXF_POINT); - } - -+#if !defined(STAGING_CSMT) -+ if (swapchain->device->bCursorVisible && swapchain->device->cursor_texture -+ && !swapchain->device->hardwareCursor) -+ { -+ struct wined3d_surface *cursor = surface_from_resource( -+ wined3d_texture_get_sub_resource(swapchain->device->cursor_texture, 0)); -+ RECT destRect = -+ { -+ swapchain->device->xScreenSpace - swapchain->device->xHotSpot, -+ swapchain->device->yScreenSpace - swapchain->device->yHotSpot, -+ swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot, -+ swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot, -+ }; -+ RECT src_rect = -+ { -+ 0, 0, -+ swapchain->device->cursor_texture->resource.width, -+ swapchain->device->cursor_texture->resource.height -+ }; -+ const RECT clip_rect = {0, 0, back_buffer->resource.width, back_buffer->resource.height}; -+ -+ TRACE("Rendering the software cursor.\n"); -+ -+ if (swapchain->desc.windowed) -+ MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2); -+ if (wined3d_clip_blit(&clip_rect, &destRect, &src_rect)) -+ wined3d_surface_blt(back_buffer, &destRect, cursor, &src_rect, WINEDDBLT_ALPHATEST, -+ NULL, WINED3D_TEXF_POINT); -+ } -+ -+#endif /* STAGING_CSMT */ - TRACE("Presenting HDC %p.\n", context->hdc); - - render_to_fbo = swapchain->render_to_fbo; -@@ -501,6 +544,7 @@ - */ - if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) - { -+#if defined(STAGING_CSMT) - wined3d_resource_load_location(&back_buffer->resource, context, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_resource_invalidate_location(&back_buffer->resource, WINED3D_LOCATION_DRAWABLE); - swapchain->render_to_fbo = TRUE; -@@ -509,6 +553,16 @@ - else - { - wined3d_resource_load_location(&back_buffer->resource, context, back_buffer->container->resource.draw_binding); -+#else /* STAGING_CSMT */ -+ surface_load_location(back_buffer, context, WINED3D_LOCATION_TEXTURE_RGB); -+ surface_invalidate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); -+ swapchain->render_to_fbo = TRUE; -+ swapchain_update_draw_bindings(swapchain); -+ } -+ else -+ { -+ surface_load_location(back_buffer, context, back_buffer->container->resource.draw_binding); -+#endif /* STAGING_CSMT */ - } - - if (swapchain->render_to_fbo) -@@ -521,8 +575,13 @@ - swapchain_blit(swapchain, context, &src_rect, &dst_rect); - } - -+#if defined(STAGING_CSMT) - if (swapchain->num_contexts > 1 && !wined3d_settings.cs_multithreaded) - gl_info->gl_ops.gl.p_glFlush(); -+#else /* STAGING_CSMT */ -+ if (swapchain->num_contexts > 1) -+ gl_info->gl_ops.gl.p_glFinish(); -+#endif /* STAGING_CSMT */ - - /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ - gl_info->gl_ops.wgl.p_wglSwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */ -@@ -546,6 +605,7 @@ - - front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); - -+#if defined(STAGING_CSMT) - wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); - wined3d_resource_invalidate_location(&front->resource, ~WINED3D_LOCATION_DRAWABLE); - switch (swapchain->desc.swap_effect) -@@ -574,6 +634,31 @@ - { - wined3d_texture_decref(swapchain->device->cs->onscreen_depth_stencil->container); - swapchain->device->cs->onscreen_depth_stencil = NULL; -+#else /* STAGING_CSMT */ -+ surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); -+ surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); -+ /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM -+ * and INTEXTURE copies can keep their old content if they have any defined content. -+ * If the swapeffect is COPY, the content remains the same. -+ * -+ * The FLIP swap effect is not implemented yet. We could mark WINED3D_LOCATION_DRAWABLE -+ * up to date and hope WGL flipped front and back buffers and read this data into -+ * the FBO. Don't bother about this for now. */ -+ -+ if (fb->depth_stencil) -+ { -+ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(fb->depth_stencil); -+ -+ if (ds && (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL -+ || ds->flags & SFLAG_DISCARD)) -+ { -+ surface_modify_ds_location(ds, WINED3D_LOCATION_DISCARDED, -+ fb->depth_stencil->width, fb->depth_stencil->height); -+ if (ds == swapchain->device->onscreen_depth_stencil) -+ { -+ wined3d_texture_decref(swapchain->device->onscreen_depth_stencil->container); -+ swapchain->device->onscreen_depth_stencil = NULL; -+#endif /* STAGING_CSMT */ - } - } - } -@@ -606,7 +691,11 @@ - - TRACE("Copying surface %p to screen.\n", front); - -+#if defined(STAGING_CSMT) - wined3d_resource_load_location(&front->resource, NULL, WINED3D_LOCATION_DIB); -+#else /* STAGING_CSMT */ -+ surface_load_location(front, NULL, WINED3D_LOCATION_DIB); -+#endif /* STAGING_CSMT */ - - src_dc = front->hDC; - window = swapchain->win_handle; -@@ -634,8 +723,12 @@ - } - - static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, -+#if defined(STAGING_CSMT) - const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags, - struct wined3d_surface *depth_stencil) -+#else /* STAGING_CSMT */ -+ const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) -+#endif /* STAGING_CSMT */ - { - struct wined3d_surface *front, *back; - -@@ -662,9 +755,15 @@ - { - void *tmp; - -+#if defined(STAGING_CSMT) - tmp = front->resource.bitmap_data; - front->resource.bitmap_data = back->resource.bitmap_data; - back->resource.bitmap_data = tmp; -+#else /* STAGING_CSMT */ -+ tmp = front->dib.bitmap_data; -+ front->dib.bitmap_data = back->dib.bitmap_data; -+ back->dib.bitmap_data = tmp; -+#endif /* STAGING_CSMT */ - - if (front->resource.heap_memory) - ERR("GDI Surface %p has heap memory allocated.\n", front); -@@ -735,6 +834,7 @@ - swapchain->render_to_fbo = TRUE; - } - -+#if defined(STAGING_CSMT) - HRESULT swapchain_create_context_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain) - { - const struct wined3d_adapter *adapter = device->adapter; -@@ -798,6 +898,7 @@ - return WINED3D_OK; - } - -+#endif /* STAGING_CSMT */ - static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device, - struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) - { -@@ -888,8 +989,13 @@ - front_buffer = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); - if (!(device->wined3d->flags & WINED3D_NO3D)) - { -+#if defined(STAGING_CSMT) - wined3d_resource_validate_location(&front_buffer->resource, WINED3D_LOCATION_DRAWABLE); - wined3d_resource_invalidate_location(&front_buffer->resource, ~WINED3D_LOCATION_DRAWABLE); -+#else /* STAGING_CSMT */ -+ surface_validate_location(front_buffer, WINED3D_LOCATION_DRAWABLE); -+ surface_invalidate_location(front_buffer, ~WINED3D_LOCATION_DRAWABLE); -+#endif /* STAGING_CSMT */ - } - - /* MSDN says we're only allowed a single fullscreen swapchain per device, -@@ -915,9 +1021,66 @@ - - if (!(device->wined3d->flags & WINED3D_NO3D)) - { -+#if defined(STAGING_CSMT) - hr = wined3d_cs_emit_create_swapchain_context(device->cs, swapchain); - if (FAILED(hr)) - goto err; -+#else /* STAGING_CSMT */ -+ static const enum wined3d_format_id formats[] = -+ { -+ WINED3DFMT_D24_UNORM_S8_UINT, -+ WINED3DFMT_D32_UNORM, -+ WINED3DFMT_R24_UNORM_X8_TYPELESS, -+ WINED3DFMT_D16_UNORM, -+ WINED3DFMT_S1_UINT_D15_UNORM -+ }; -+ -+ const struct wined3d_gl_info *gl_info = &adapter->gl_info; -+ -+ swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context)); -+ if (!swapchain->context) -+ { -+ ERR("Failed to create the context array.\n"); -+ hr = E_OUTOFMEMORY; -+ goto err; -+ } -+ swapchain->num_contexts = 1; -+ -+ /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate. -+ * You are able to add a depth + stencil surface at a later stage when you need it. -+ * In order to support this properly in WineD3D we need the ability to recreate the opengl context and -+ * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new -+ * context, need torecreate shaders, textures and other resources. -+ * -+ * The context manager already takes care of the state problem and for the other tasks code from Reset -+ * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now. -+ * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the -+ * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this -+ * issue needs to be fixed. */ -+ for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++) -+ { -+ swapchain->ds_format = wined3d_get_format(gl_info, formats[i]); -+ swapchain->context[0] = context_create(swapchain, front_buffer, swapchain->ds_format); -+ if (swapchain->context[0]) break; -+ TRACE("Depth stencil format %s is not supported, trying next format\n", -+ debug_d3dformat(formats[i])); -+ } -+ -+ if (!swapchain->context[0]) -+ { -+ WARN("Failed to create context.\n"); -+ hr = WINED3DERR_NOTAVAILABLE; -+ goto err; -+ } -+ -+ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO -+ && (!desc->enable_auto_depth_stencil -+ || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id)) -+ { -+ FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n"); -+ } -+ context_release(swapchain->context[0]); -+#endif /* STAGING_CSMT */ - } - - if (swapchain->desc.backbuffer_count > 0) -diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c ---- a/dlls/wined3d/state.c -+++ b/dlls/wined3d/state.c -@@ -105,7 +105,11 @@ - const struct wined3d_gl_info *gl_info = context->gl_info; - - /* No z test without depth stencil buffers */ -+#if defined(STAGING_CSMT) - if (!state->fb.depth_stencil) -+#else /* STAGING_CSMT */ -+ if (!state->fb->depth_stencil) -+#endif /* STAGING_CSMT */ - { - TRACE("No Z buffer - disabling depth test\n"); - zenable = WINED3D_ZB_FALSE; -@@ -370,8 +374,13 @@ - - static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) - { -+#if defined(STAGING_CSMT) - const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; - unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; -+#else /* STAGING_CSMT */ -+ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; -+ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info = context->gl_info; - GLenum srcBlend, dstBlend; - enum wined3d_blend d3d_blend; -@@ -816,7 +825,11 @@ - GLint depthFail_ccw; - - /* No stencil test without a stencil buffer. */ -+#if defined(STAGING_CSMT) - if (!state->fb.depth_stencil) -+#else /* STAGING_CSMT */ -+ if (!state->fb->depth_stencil) -+#endif /* STAGING_CSMT */ - { - gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); - checkGLcall("glDisable GL_STENCIL_TEST"); -@@ -912,7 +925,11 @@ - - static void state_stencilwrite2s(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) - { -+#if defined(STAGING_CSMT) - DWORD mask = state->fb.depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; -+#else /* STAGING_CSMT */ -+ DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info = context->gl_info; - - GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); -@@ -926,7 +943,11 @@ - - static void state_stencilwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) - { -+#if defined(STAGING_CSMT) - DWORD mask = state->fb.depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; -+#else /* STAGING_CSMT */ -+ DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info = context->gl_info; - - gl_info->gl_ops.gl.p_glStencilMask(mask); -@@ -1128,10 +1149,17 @@ - /* drop through */ - - case WINED3D_FOG_NONE: -+#if defined(STAGING_CSMT) - /* Both are none? According to msdn the alpha channel of the specular - * color contains a fog factor. Set it in draw_strided_slow. - * Same happens with Vertexfog on transformed vertices - */ -+#else /* STAGING_CSMT */ -+ /* Both are none? According to msdn the alpha channel of the specular -+ * color contains a fog factor. Set it in drawStridedSlow. -+ * Same happens with Vertexfog on transformed vertices -+ */ -+#endif /* STAGING_CSMT */ - new_source = FOGSOURCE_COORD; - gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR); - checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); -@@ -1653,7 +1681,11 @@ - if (state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS] - || state->render_states[WINED3D_RS_DEPTHBIAS]) - { -+#if defined(STAGING_CSMT) - const struct wined3d_rendertarget_view *depth = state->fb.depth_stencil; -+#else /* STAGING_CSMT */ -+ const struct wined3d_rendertarget_view *depth = state->fb->depth_stencil; -+#endif /* STAGING_CSMT */ - float scale; - - union -@@ -4190,9 +4222,15 @@ - } - } - } else { -+#if defined(STAGING_CSMT) - /* TODO: support blends in draw_strided_slow - * No need to write a FIXME here, this is done after the general vertex decl decoding - */ -+#else /* STAGING_CSMT */ -+ /* TODO: support blends in drawStridedSlow -+ * No need to write a FIXME here, this is done after the general vertex decl decoding -+ */ -+#endif /* STAGING_CSMT */ - WARN("unsupported blending in openGl\n"); - } - } -@@ -4546,7 +4584,11 @@ - - static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) - { -+#if defined(STAGING_CSMT) - const struct wined3d_rendertarget_view *target = state->fb.render_targets[0]; -+#else /* STAGING_CSMT */ -+ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_viewport vp = state->viewport; - -@@ -4724,7 +4766,11 @@ - } - else - { -+#if defined(STAGING_CSMT) - const struct wined3d_rendertarget_view *target = state->fb.render_targets[0]; -+#else /* STAGING_CSMT */ -+ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; -+#endif /* STAGING_CSMT */ - UINT height; - UINT width; - -@@ -4788,7 +4834,11 @@ - - void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) - { -+#if defined(STAGING_CSMT) - unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; -+#else /* STAGING_CSMT */ -+ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info = context->gl_info; - - TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id); diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -453,752 +16,33 @@ diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c "Expected color 0x00ff0000, got 0x%08x.\n", color); hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); -diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c ---- a/dlls/wined3d/volume.c -+++ b/dlls/wined3d/volume.c -@@ -40,6 +40,32 @@ - return TRUE; - } - -+#if !defined(STAGING_CSMT) -+void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch) -+{ -+ const struct wined3d_format *format = volume->resource.format; -+ -+ if (volume->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) -+ { -+ /* Since compressed formats are block based, pitch means the amount of -+ * bytes to the next row of block rather than the next row of pixels. */ -+ UINT row_block_count = (volume->resource.width + format->block_width - 1) / format->block_width; -+ UINT slice_block_count = (volume->resource.height + format->block_height - 1) / format->block_height; -+ *row_pitch = row_block_count * format->block_byte_count; -+ *slice_pitch = *row_pitch * slice_block_count; -+ } -+ else -+ { -+ unsigned char alignment = volume->resource.device->surface_alignment; -+ *row_pitch = format->byte_count * volume->resource.width; /* Bytes / row */ -+ *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1); -+ *slice_pitch = *row_pitch * volume->resource.height; -+ } -+ -+ TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch); -+} -+ -+#endif /* STAGING_CSMT */ - /* This call just uploads data, the caller is responsible for binding the - * correct texture. */ - /* Context activation is done by the caller. */ -@@ -71,7 +97,11 @@ - dst_row_pitch = width * format->conv_byte_count; - dst_slice_pitch = dst_row_pitch * height; - +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -1339,7 +1339,11 @@ + * result on Wine. + * {D3DFMT_YUY2, "D3DFMT_YUY2", BLOCKS, 0}, + * {D3DFMT_UYVY, "D3DFMT_UYVY", BLOCKS, 0}, */ +#if defined(STAGING_CSMT) - wined3d_resource_get_pitch(&volume->resource, &src_row_pitch, &src_slice_pitch); + {D3DFMT_DXT1, "D3DFMT_DXT1", BLOCKS, 0}, +#else /* STAGING_CSMT */ -+ wined3d_volume_get_pitch(volume, &src_row_pitch, &src_slice_pitch); ++ {D3DFMT_DXT1, "D3DFMT_DXT1", BLOCKS | TODO_FILL_RETURN, 0}, +#endif /* STAGING_CSMT */ - - converted_mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth); - format->convert(data->addr, converted_mem, src_row_pitch, src_slice_pitch, -@@ -99,6 +129,22 @@ - HeapFree(GetProcessHeap(), 0, converted_mem); - } - -+#if !defined(STAGING_CSMT) -+void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) -+{ -+ TRACE("Volume %p, setting %s.\n", volume, wined3d_debug_location(location)); -+ volume->locations |= location; -+ TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations)); -+} -+ -+void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) -+{ -+ TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location)); -+ volume->locations &= ~location; -+ TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations)); -+} -+ -+#endif /* STAGING_CSMT */ - /* Context activation is done by the caller. */ - static void wined3d_volume_download_data(struct wined3d_volume *volume, - const struct wined3d_context *context, const struct wined3d_bo_address *data) -@@ -134,8 +180,33 @@ - static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume) - { - wined3d_resource_free_sysmem(&volume->resource); + /* Vendor-specific formats like ATI2N are a non-issue here since they're not + * supported as offscreen plain surfaces and do not support D3DUSAGE_RENDERTARGET + * when created as texture. */ +@@ -17630,7 +17634,11 @@ + fill_surface(surface_managed, 0x0000ff00, D3DLOCK_NO_DIRTY_UPDATE); + add_dirty_rect_test_draw(device); + color = getPixelColor(device, 320, 240); +#if defined(STAGING_CSMT) - volume->resource.map_heap_memory = NULL; - wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); + todo_wine ok(color_match(color, 0x00ff0000, 1), +#else /* STAGING_CSMT */ -+ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_SYSMEM); -+} -+ -+static DWORD volume_access_from_location(DWORD location) -+{ -+ switch (location) -+ { -+ case WINED3D_LOCATION_DISCARDED: -+ return 0; -+ -+ case WINED3D_LOCATION_SYSMEM: -+ return WINED3D_RESOURCE_ACCESS_CPU; -+ -+ case WINED3D_LOCATION_BUFFER: -+ case WINED3D_LOCATION_TEXTURE_RGB: -+ case WINED3D_LOCATION_TEXTURE_SRGB: -+ return WINED3D_RESOURCE_ACCESS_GPU; -+ -+ default: -+ FIXME("Unhandled location %#x.\n", location); -+ return 0; -+ } ++ ok(color_match(color, 0x00ff0000, 1), +#endif /* STAGING_CSMT */ - } - - /* Context activation is done by the caller. */ -@@ -177,6 +248,7 @@ - - return TRUE; - } -+#if defined(STAGING_CSMT) - - /* Context activation is done by the caller. */ - static void wined3d_volume_load_location(struct wined3d_resource *resource, -@@ -187,6 +259,22 @@ - - TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location), - wined3d_debug_location(volume->resource.locations)); -+#else /* STAGING_CSMT */ -+/* Context activation is done by the caller. */ -+static void wined3d_volume_load_location(struct wined3d_volume *volume, -+ struct wined3d_context *context, DWORD location) -+{ -+ DWORD required_access = volume_access_from_location(location); -+ -+ TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location), -+ wined3d_debug_location(volume->locations)); -+ -+ if ((volume->locations & location) == location) -+ { -+ TRACE("Location(s) already up to date.\n"); -+ return; -+ } -+#endif /* STAGING_CSMT */ - - if ((volume->resource.access_flags & required_access) != required_access) - { -@@ -205,6 +293,7 @@ - && !(volume->container->flags & WINED3D_TEXTURE_SRGB_ALLOCATED))) - ERR("Trying to load (s)RGB texture without prior allocation.\n"); - -+#if defined(STAGING_CSMT) - if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) - { - TRACE("Volume previously discarded, nothing to do.\n"); -@@ -238,6 +327,41 @@ - return; - } - wined3d_resource_validate_location(&volume->resource, location); -+#else /* STAGING_CSMT */ -+ if (volume->locations & WINED3D_LOCATION_DISCARDED) -+ { -+ TRACE("Volume previously discarded, nothing to do.\n"); -+ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); -+ } -+ else if (volume->locations & WINED3D_LOCATION_SYSMEM) -+ { -+ struct wined3d_const_bo_address data = {0, volume->resource.heap_memory}; -+ wined3d_texture_bind_and_dirtify(volume->container, context, -+ location == WINED3D_LOCATION_TEXTURE_SRGB); -+ wined3d_volume_upload_data(volume, context, &data); -+ } -+ else if (volume->locations & WINED3D_LOCATION_BUFFER) -+ { -+ struct wined3d_const_bo_address data = {volume->pbo, NULL}; -+ wined3d_texture_bind_and_dirtify(volume->container, context, -+ location == WINED3D_LOCATION_TEXTURE_SRGB); -+ wined3d_volume_upload_data(volume, context, &data); -+ } -+ else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) -+ { -+ wined3d_volume_srgb_transfer(volume, context, TRUE); -+ } -+ else if (volume->locations & WINED3D_LOCATION_TEXTURE_SRGB) -+ { -+ wined3d_volume_srgb_transfer(volume, context, FALSE); -+ } -+ else -+ { -+ FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->locations)); -+ return; -+ } -+ wined3d_volume_validate_location(volume, location); -+#endif /* STAGING_CSMT */ - - if (wined3d_volume_can_evict(volume)) - wined3d_volume_evict_sysmem(volume); -@@ -248,11 +372,24 @@ - if (!volume->resource.heap_memory) - ERR("Trying to load WINED3D_LOCATION_SYSMEM without setting it up first.\n"); - -+#if defined(STAGING_CSMT) - if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) - { - struct wined3d_bo_address data = {0, volume->resource.heap_memory}; - - if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) -+#else /* STAGING_CSMT */ -+ if (volume->locations & WINED3D_LOCATION_DISCARDED) -+ { -+ TRACE("Volume previously discarded, nothing to do.\n"); -+ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); -+ } -+ else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) -+ { -+ struct wined3d_bo_address data = {0, volume->resource.heap_memory}; -+ -+ if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) -+#endif /* STAGING_CSMT */ - wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); - else - wined3d_texture_bind_and_dirtify(volume->container, context, TRUE); -@@ -263,6 +400,7 @@ - else - { - FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", -+#if defined(STAGING_CSMT) - wined3d_debug_location(volume->resource.locations)); - return; - } -@@ -278,6 +416,28 @@ - struct wined3d_bo_address data = {volume->resource.buffer->name, NULL}; - - if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) -+#else /* STAGING_CSMT */ -+ wined3d_debug_location(volume->locations)); -+ return; -+ } -+ wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); -+ break; -+ -+ case WINED3D_LOCATION_BUFFER: -+ if (!volume->pbo) -+ ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); -+ -+ if (volume->locations & WINED3D_LOCATION_DISCARDED) -+ { -+ TRACE("Volume previously discarded, nothing to do.\n"); -+ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); -+ } -+ else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) -+ { -+ struct wined3d_bo_address data = {volume->pbo, NULL}; -+ -+ if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) -+#endif /* STAGING_CSMT */ - wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); - else - wined3d_texture_bind_and_dirtify(volume->container, context, TRUE); -@@ -287,6 +447,7 @@ - else - { - FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", -+#if defined(STAGING_CSMT) - wined3d_debug_location(volume->resource.locations)); - return; - } -@@ -296,6 +457,17 @@ - default: - FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), - wined3d_debug_location(volume->resource.locations)); -+#else /* STAGING_CSMT */ -+ wined3d_debug_location(volume->locations)); -+ return; -+ } -+ wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); -+ break; -+ -+ default: -+ FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), -+ wined3d_debug_location(volume->locations)); -+#endif /* STAGING_CSMT */ - } - } - -@@ -303,6 +475,7 @@ - void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode) - { - wined3d_texture_prepare_texture(volume->container, context, srgb_mode); -+#if defined(STAGING_CSMT) - wined3d_resource_load_location(&volume->resource, context, - srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB); - } -@@ -315,6 +488,51 @@ - resource_cleanup(&volume->resource); - volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); - wined3d_cs_emit_volume_cleanup(device->cs, volume); -+#else /* STAGING_CSMT */ -+ wined3d_volume_load_location(volume, context, -+ srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB); -+} -+ -+/* Context activation is done by the caller. */ -+static void wined3d_volume_prepare_pbo(struct wined3d_volume *volume, struct wined3d_context *context) -+{ -+ const struct wined3d_gl_info *gl_info = context->gl_info; -+ -+ if (volume->pbo) -+ return; -+ -+ GL_EXTCALL(glGenBuffers(1, &volume->pbo)); -+ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo)); -+ GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, volume->resource.size, NULL, GL_STREAM_DRAW)); -+ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); -+ checkGLcall("Create PBO"); -+ -+ TRACE("Created PBO %u for volume %p.\n", volume->pbo, volume); -+} -+ -+static void wined3d_volume_free_pbo(struct wined3d_volume *volume) -+{ -+ struct wined3d_context *context = context_acquire(volume->resource.device, NULL); -+ const struct wined3d_gl_info *gl_info = context->gl_info; -+ -+ TRACE("Deleting PBO %u belonging to volume %p.\n", volume->pbo, volume); -+ GL_EXTCALL(glDeleteBuffers(1, &volume->pbo)); -+ checkGLcall("glDeleteBuffers"); -+ volume->pbo = 0; -+ context_release(context); -+} -+ -+void wined3d_volume_destroy(struct wined3d_volume *volume) -+{ -+ TRACE("volume %p.\n", volume); -+ -+ if (volume->pbo) -+ wined3d_volume_free_pbo(volume); -+ -+ resource_cleanup(&volume->resource); -+ volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); -+ HeapFree(GetProcessHeap(), 0, volume); -+#endif /* STAGING_CSMT */ - } - - static void volume_unload(struct wined3d_resource *resource) -@@ -328,6 +546,7 @@ - - TRACE("texture %p.\n", resource); - -+#if defined(STAGING_CSMT) - if (wined3d_resource_prepare_system_memory(&volume->resource)) - { - context = context_acquire(device, NULL); -@@ -340,6 +559,29 @@ - ERR("Out of memory when unloading volume %p.\n", volume); - wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); - wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_DISCARDED); -+#else /* STAGING_CSMT */ -+ if (volume_prepare_system_memory(volume)) -+ { -+ context = context_acquire(device, NULL); -+ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); -+ context_release(context); -+ wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM); -+ } -+ else -+ { -+ ERR("Out of memory when unloading volume %p.\n", volume); -+ wined3d_volume_validate_location(volume, WINED3D_LOCATION_DISCARDED); -+ wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_DISCARDED); -+ } -+ -+ if (volume->pbo) -+ { -+ /* Should not happen because only dynamic default pool volumes -+ * have a buffer, and those are not evicted by device_evit_managed_resources -+ * and must be freed before a non-ex device reset. */ -+ ERR("Unloading a volume with a buffer\n"); -+ wined3d_volume_free_pbo(volume); -+#endif /* STAGING_CSMT */ - } - - /* The texture name is managed by the container. */ -@@ -348,6 +590,36 @@ - resource_unload(resource); - } - -+#if !defined(STAGING_CSMT) -+static BOOL volume_check_block_align(const struct wined3d_volume *volume, -+ const struct wined3d_box *box) -+{ -+ UINT width_mask, height_mask; -+ const struct wined3d_format *format = volume->resource.format; -+ -+ if (!box) -+ return TRUE; -+ -+ /* This assumes power of two block sizes, but NPOT block sizes would be -+ * silly anyway. -+ * -+ * This also assumes that the format's block depth is 1. */ -+ width_mask = format->block_width - 1; -+ height_mask = format->block_height - 1; -+ -+ if (box->left & width_mask) -+ return FALSE; -+ if (box->top & height_mask) -+ return FALSE; -+ if (box->right & width_mask && box->right != volume->resource.width) -+ return FALSE; -+ if (box->bottom & height_mask && box->bottom != volume->resource.height) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+#endif /* STAGING_CSMT */ - static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *volume, - const struct wined3d_box *box) - { -@@ -373,6 +645,7 @@ - HRESULT wined3d_volume_map(struct wined3d_volume *volume, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) - { -+#if defined(STAGING_CSMT) - HRESULT hr; - const struct wined3d_format *format = volume->resource.format; - const unsigned int fmt_flags = volume->container->resource.format_flags; -@@ -413,6 +686,177 @@ - if (hr == WINEDDERR_NOTLOCKED) - return WINED3DERR_INVALIDCALL; - return hr; -+#else /* STAGING_CSMT */ -+ struct wined3d_device *device = volume->resource.device; -+ struct wined3d_context *context; -+ const struct wined3d_gl_info *gl_info; -+ BYTE *base_memory; -+ const struct wined3d_format *format = volume->resource.format; -+ const unsigned int fmt_flags = volume->container->resource.format_flags; -+ -+ TRACE("volume %p, map_desc %p, box %p, flags %#x.\n", -+ volume, map_desc, box, flags); -+ -+ map_desc->data = NULL; -+ if (!(volume->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU)) -+ { -+ WARN("Volume %p is not CPU accessible.\n", volume); -+ return WINED3DERR_INVALIDCALL; -+ } -+ if (volume->resource.map_count) -+ { -+ WARN("Volume is already mapped.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ if (!wined3d_volume_check_box_dimensions(volume, box)) -+ { -+ WARN("Map box is invalid.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !volume_check_block_align(volume, box)) -+ { -+ WARN("Map box is misaligned for %ux%u blocks.\n", -+ format->block_width, format->block_height); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); -+ -+ if (volume->resource.map_binding == WINED3D_LOCATION_BUFFER) -+ { -+ context = context_acquire(device, NULL); -+ gl_info = context->gl_info; -+ -+ wined3d_volume_prepare_pbo(volume, context); -+ if (flags & WINED3D_MAP_DISCARD) -+ wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); -+ else -+ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); -+ -+ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo)); -+ -+ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) -+ { -+ GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); -+ mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; -+ base_memory = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, -+ 0, volume->resource.size, mapflags)); -+ } -+ else -+ { -+ GLenum access = wined3d_resource_gl_legacy_map_flags(flags); -+ base_memory = GL_EXTCALL(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, access)); -+ } -+ -+ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); -+ checkGLcall("Map PBO"); -+ -+ context_release(context); -+ } -+ else -+ { -+ if (!volume_prepare_system_memory(volume)) -+ { -+ WARN("Out of memory.\n"); -+ map_desc->data = NULL; -+ return E_OUTOFMEMORY; -+ } -+ -+ if (flags & WINED3D_MAP_DISCARD) -+ { -+ wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); -+ } -+ else if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) -+ { -+ context = context_acquire(device, NULL); -+ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); -+ context_release(context); -+ } -+ base_memory = volume->resource.heap_memory; -+ } -+ -+ TRACE("Base memory pointer %p.\n", base_memory); -+ -+ if (fmt_flags & WINED3DFMT_FLAG_BROKEN_PITCH) -+ { -+ map_desc->row_pitch = volume->resource.width * format->byte_count; -+ map_desc->slice_pitch = map_desc->row_pitch * volume->resource.height; -+ } -+ else -+ { -+ wined3d_volume_get_pitch(volume, &map_desc->row_pitch, &map_desc->slice_pitch); -+ } -+ -+ if (!box) -+ { -+ TRACE("No box supplied - all is ok\n"); -+ map_desc->data = base_memory; -+ } -+ else -+ { -+ TRACE("Lock Box (%p) = l %u, t %u, r %u, b %u, fr %u, ba %u\n", -+ box, box->left, box->top, box->right, box->bottom, box->front, box->back); -+ -+ if ((fmt_flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS) -+ { -+ /* Compressed textures are block based, so calculate the offset of -+ * the block that contains the top-left pixel of the locked rectangle. */ -+ map_desc->data = base_memory -+ + (box->front * map_desc->slice_pitch) -+ + ((box->top / format->block_height) * map_desc->row_pitch) -+ + ((box->left / format->block_width) * format->block_byte_count); -+ } -+ else -+ { -+ map_desc->data = base_memory -+ + (map_desc->slice_pitch * box->front) -+ + (map_desc->row_pitch * box->top) -+ + (box->left * volume->resource.format->byte_count); -+ } -+ } -+ -+ if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) -+ { -+ wined3d_texture_set_dirty(volume->container); -+ wined3d_volume_invalidate_location(volume, ~volume->resource.map_binding); -+ } -+ -+ volume->resource.map_count++; -+ -+ TRACE("Returning memory %p, row pitch %d, slice pitch %d.\n", -+ map_desc->data, map_desc->row_pitch, map_desc->slice_pitch); -+ -+ return WINED3D_OK; -+} -+ -+HRESULT wined3d_volume_unmap(struct wined3d_volume *volume) -+{ -+ TRACE("volume %p.\n", volume); -+ -+ if (!volume->resource.map_count) -+ { -+ WARN("Trying to unlock an unlocked volume %p.\n", volume); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (volume->resource.map_binding == WINED3D_LOCATION_BUFFER) -+ { -+ struct wined3d_device *device = volume->resource.device; -+ struct wined3d_context *context = context_acquire(device, NULL); -+ const struct wined3d_gl_info *gl_info = context->gl_info; -+ -+ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo)); -+ GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); -+ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); -+ checkGLcall("Unmap PBO"); -+ -+ context_release(context); -+ } -+ -+ volume->resource.map_count--; -+ -+ return WINED3D_OK; -+#endif /* STAGING_CSMT */ - } - - static ULONG volume_resource_incref(struct wined3d_resource *resource) -@@ -423,11 +867,13 @@ - return wined3d_texture_incref(volume->container); - } - -+#if defined(STAGING_CSMT) - void wined3d_volume_cleanup_cs(struct wined3d_volume *volume) - { - HeapFree(GetProcessHeap(), 0, volume); - } - -+#endif /* STAGING_CSMT */ - static ULONG volume_resource_decref(struct wined3d_resource *resource) - { - struct wined3d_volume *volume = volume_from_resource(resource); -@@ -449,6 +895,7 @@ - return WINED3DERR_INVALIDCALL; - } - -+#if defined(STAGING_CSMT) - static void wined3d_volume_location_invalidated(struct wined3d_resource *resource, DWORD location) - { - struct wined3d_volume *volume = volume_from_resource(resource); -@@ -457,6 +904,7 @@ - wined3d_texture_set_dirty(volume->container); - } - -+#endif /* STAGING_CSMT */ - static const struct wined3d_resource_ops volume_resource_ops = - { - volume_resource_incref, -@@ -464,8 +912,10 @@ - volume_unload, - volume_resource_sub_resource_map, - volume_resource_sub_resource_unmap, -+#if defined(STAGING_CSMT) - wined3d_volume_location_invalidated, - wined3d_volume_load_location, -+#endif /* STAGING_CSMT */ - }; - - static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container, -@@ -497,7 +947,11 @@ - } - - volume->texture_level = level; -+#if defined(STAGING_CSMT) - volume->resource.locations = WINED3D_LOCATION_DISCARDED; -+#else /* STAGING_CSMT */ -+ volume->locations = WINED3D_LOCATION_DISCARDED; -+#endif /* STAGING_CSMT */ - - if (desc->pool == WINED3D_POOL_DEFAULT && desc->usage & WINED3DUSAGE_DYNAMIC - && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] -@@ -505,7 +959,9 @@ - { - wined3d_resource_free_sysmem(&volume->resource); - volume->resource.map_binding = WINED3D_LOCATION_BUFFER; -+#if defined(STAGING_CSMT) - volume->resource.map_heap_memory = NULL; -+#endif /* STAGING_CSMT */ - } - - volume->container = container; -diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c ---- a/dlls/wined3d/utils.c -+++ b/dlls/wined3d/utils.c -@@ -3733,7 +3733,11 @@ - float y_offset = context->render_offscreen - ? (center_offset - (2.0f * y) - h) / h - : (center_offset - (2.0f * y) - h) / -h; -+#if defined(STAGING_CSMT) - enum wined3d_depth_buffer_type zenable = state->fb.depth_stencil ? -+#else /* STAGING_CSMT */ -+ enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ? -+#endif /* STAGING_CSMT */ - state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE; - float z_scale = zenable ? 2.0f : 0.0f; - float z_offset = zenable ? -1.0f : 0.0f; -@@ -3856,6 +3860,7 @@ - /* case WINED3D_TTFF_COUNT1: Won't ever get here. */ - case WINED3D_TTFF_COUNT2: - mat._13 = mat._23 = mat._33 = mat._43 = 0.0f; -+#if defined(STAGING_CSMT) - /* OpenGL divides the first 3 vertex coord by the 4th by default, - * which is essentially the same as D3DTTFF_PROJECTED. Make sure that - * the 4th coord evaluates to 1.0 to eliminate that. -@@ -3868,6 +3873,20 @@ - * A more serious problem occurs if the app passes 4 coordinates in, and the - * 4th is != 1.0(opengl default). This would have to be fixed in draw_strided_slow - * or a replacement shader. */ -+#else /* STAGING_CSMT */ -+ /* OpenGL divides the first 3 vertex coord by the 4th by default, -+ * which is essentially the same as D3DTTFF_PROJECTED. Make sure that -+ * the 4th coord evaluates to 1.0 to eliminate that. -+ * -+ * If the fixed function pipeline is used, the 4th value remains unused, -+ * so there is no danger in doing this. With vertex shaders we have a -+ * problem. Should an app hit that problem, the code here would have to -+ * check for pixel shaders, and the shader has to undo the default gl divide. -+ * -+ * A more serious problem occurs if the app passes 4 coordinates in, and the -+ * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow -+ * or a replacement shader. */ -+#endif /* STAGING_CSMT */ - default: - mat._14 = mat._24 = mat._34 = 0.0f; mat._44 = 1.0f; - } -@@ -4325,7 +4344,11 @@ - unsigned int i; - DWORD ttff; - DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; -+#if defined(STAGING_CSMT) - unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; -+#else /* STAGING_CSMT */ -+ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; -+#endif /* STAGING_CSMT */ - const struct wined3d_gl_info *gl_info = context->gl_info; - const struct wined3d_d3d_info *d3d_info = context->d3d_info; - -diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c ---- a/dlls/wined3d/wined3d_main.c -+++ b/dlls/wined3d/wined3d_main.c -@@ -87,8 +87,10 @@ - ~0U, /* No GS shader model limit by default. */ - ~0U, /* No PS shader model limit by default. */ - FALSE, /* 3D support enabled by default. */ -+#if defined(STAGING_CSMT) - TRUE, /* Multithreaded CS by default. */ - FALSE, /* Do not ignore render target maps. */ -+#endif /* STAGING_CSMT */ - }; - - struct wined3d * CDECL wined3d_create(DWORD flags) -@@ -328,6 +330,7 @@ - TRACE("Disabling 3D support.\n"); - wined3d_settings.no_3d = TRUE; - } -+#if defined(STAGING_CSMT) - if (!get_config_key(hkey, appkey, "CSMT", buffer, size) - && !strcmp(buffer,"disabled")) - { -@@ -344,6 +347,9 @@ - - FIXME_(winediag)("Experimental wined3d CSMT feature is currently %s.\n", - wined3d_settings.cs_multithreaded ? "enabled" : "disabled"); -+#else /* STAGING_CSMT */ -+ } -+#endif /* STAGING_CSMT */ - - if (appkey) RegCloseKey( appkey ); - if (hkey) RegCloseKey( hkey ); + "Expected color 0x00ff0000, got 0x%08x.\n", color); + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1264,45 +108,535 @@ diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader } static HRESULT arbfp_blit_color_fill(struct wined3d_device *device, struct wined3d_surface *dst_surface, -diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c ---- a/dlls/wined3d/view.c -+++ b/dlls/wined3d/view.c -@@ -33,11 +33,13 @@ - return refcount; +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -32,6 +32,7 @@ + #define WINED3D_BUFFER_HASDESC 0x01 /* A vertex description has been found. */ + #define WINED3D_BUFFER_CREATEBO 0x02 /* Create a buffer object for this buffer. */ + #define WINED3D_BUFFER_DOUBLEBUFFER 0x04 /* Keep both a buffer object and a system memory copy for this buffer. */ ++#if defined(STAGING_CSMT) + #define WINED3D_BUFFER_DISCARD 0x08 /* The next PreLoad may discard the buffer contents. */ + #define WINED3D_BUFFER_SYNC 0x10 /* There has been at least one synchronized map since the last preload. */ + #define WINED3D_BUFFER_APPLESYNC 0x20 /* Using sync as in GL_APPLE_flush_buffer_range. */ +@@ -42,6 +43,19 @@ + #define VB_RESETFULLCONVS 20 /* Reset full conversion counts after that number of draws */ + + void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, UINT offset, UINT size) ++#else /* STAGING_CSMT */ ++#define WINED3D_BUFFER_FLUSH 0x08 /* Manual unmap flushing. */ ++#define WINED3D_BUFFER_DISCARD 0x10 /* A DISCARD lock has occurred since the last preload. */ ++#define WINED3D_BUFFER_SYNC 0x20 /* There has been at least one synchronized map since the last preload. */ ++#define WINED3D_BUFFER_APPLESYNC 0x40 /* Using sync as in GL_APPLE_flush_buffer_range. */ ++ ++#define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */ ++#define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */ ++#define VB_MAXFULLCONVERSIONS 5 /* Number of full conversions before we stop converting */ ++#define VB_RESETFULLCONVS 20 /* Reset full conversion counts after that number of draws */ ++ ++static void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, UINT offset, UINT size) ++#endif /* STAGING_CSMT */ + { + if (!offset && !size) + goto invalidate_all; +@@ -117,7 +131,11 @@ } + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context) ++#else /* STAGING_CSMT */ ++static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context) ++#endif /* STAGING_CSMT */ + { + GLenum gl_usage = GL_STATIC_DRAW_ARB; + GLenum error; +@@ -166,6 +184,10 @@ + { + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)); + checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)"); ++#if !defined(STAGING_CSMT) ++ This->flags |= WINED3D_BUFFER_FLUSH; ++ ++#endif /* STAGING_CSMT */ + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); + checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)"); + This->flags |= WINED3D_BUFFER_APPLESYNC; +@@ -191,10 +213,14 @@ + if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER) + buffer_invalidate_bo_range(This, 0, 0); + else ++#if defined(STAGING_CSMT) + { + wined3d_resource_free_sysmem(&This->resource); + This->resource.map_heap_memory = NULL; + } ++#else /* STAGING_CSMT */ ++ wined3d_resource_free_sysmem(&This->resource); ++#endif /* STAGING_CSMT */ + + return; + +@@ -423,6 +449,7 @@ + { + DWORD src_color = *dst_color; + +#if defined(STAGING_CSMT) - void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) - { - HeapFree(GetProcessHeap(), 0, view); - } - + /* Color conversion like in draw_strided_slow. watch out for little endianity + * If we want that stuff to work on big endian machines too we have to consider more things + * +@@ -431,6 +458,16 @@ + * 0x0000ff00: Green mask + * 0x000000ff: Red mask + */ ++#else /* STAGING_CSMT */ ++ /* Color conversion like in drawStridedSlow. watch out for little endianity ++ * If we want that stuff to work on big endian machines too we have to consider more things ++ * ++ * 0xff000000: Alpha mask ++ * 0x00ff0000: Blue mask ++ * 0x0000ff00: Green mask ++ * 0x000000ff: Red mask ++ */ +#endif /* STAGING_CSMT */ - ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view) - { - ULONG refcount = InterlockedDecrement(&view->refcount); -@@ -46,6 +48,7 @@ - - if (!refcount) + *dst_color = 0; + *dst_color |= (src_color & 0xff00ff00u); /* Alpha Green */ + *dst_color |= (src_color & 0x00ff0000u) >> 16; /* Red */ +@@ -457,8 +494,12 @@ + data->buffer_object = buffer->buffer_object; + if (!buffer->buffer_object) { +#if defined(STAGING_CSMT) - struct wined3d_device *device = view->resource->device; - - /* Call wined3d_object_destroyed() before releasing the resource, -@@ -53,6 +56,13 @@ - view->parent_ops->wined3d_object_destroyed(view->parent); - wined3d_resource_decref(view->resource); - wined3d_cs_emit_view_destroy(device->cs, view); + if ((!buffer->resource.map_count || buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER) + && buffer->flags & WINED3D_BUFFER_CREATEBO) +#else /* STAGING_CSMT */ -+ /* Call wined3d_object_destroyed() before releasing the resource, -+ * since releasing the resource may end up destroying the parent. */ -+ view->parent_ops->wined3d_object_destroyed(view->parent); -+ wined3d_resource_decref(view->resource); -+ HeapFree(GetProcessHeap(), 0, view); ++ if ((buffer->flags & WINED3D_BUFFER_CREATEBO) && !buffer->resource.map_count) ++#endif /* STAGING_CSMT */ + { + buffer_create_buffer_object(buffer, context); + buffer->flags &= ~WINED3D_BUFFER_CREATEBO; +@@ -497,7 +538,9 @@ + + if (!wined3d_resource_allocate_sysmem(&This->resource)) + ERR("Failed to allocate system memory.\n"); ++#if defined(STAGING_CSMT) + This->resource.heap_memory = This->resource.map_heap_memory; ++#endif /* STAGING_CSMT */ + + if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) + context_invalidate_state(context, STATE_INDEXBUFFER); +@@ -545,6 +588,7 @@ + resource_unload(resource); + } + ++#if defined(STAGING_CSMT) + void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer) + { + struct wined3d_context *context; +@@ -577,6 +621,30 @@ + + buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent); + wined3d_cs_emit_buffer_cleanup(device->cs, buffer); ++#else /* STAGING_CSMT */ ++ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer) ++{ ++ ULONG refcount = InterlockedDecrement(&buffer->resource.ref); ++ struct wined3d_context *context; ++ ++ TRACE("%p decreasing refcount to %u.\n", buffer, refcount); ++ ++ if (!refcount) ++ { ++ if (buffer->buffer_object) ++ { ++ context = context_acquire(buffer->resource.device, NULL); ++ delete_gl_buffer(buffer, context->gl_info); ++ context_release(context); ++ ++ HeapFree(GetProcessHeap(), 0, buffer->conversion_map); ++ } ++ ++ resource_cleanup(&buffer->resource); ++ buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent); ++ HeapFree(GetProcessHeap(), 0, buffer->maps); ++ HeapFree(GetProcessHeap(), 0, buffer); +#endif /* STAGING_CSMT */ } return refcount; +@@ -661,6 +729,7 @@ + /* The caller provides a GL context */ + static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags) + { ++#if defined(STAGING_CSMT) + UINT start = 0, len = 0; + + /* This potentially invalidates the element array buffer binding, but the +@@ -684,6 +753,45 @@ + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)); + checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)"); + This->flags &= ~WINED3D_BUFFER_APPLESYNC; ++#else /* STAGING_CSMT */ ++ BYTE *map; ++ UINT start = 0, len = 0; ++ ++ /* This potentially invalidates the element array buffer binding, but the ++ * caller always takes care of this. */ ++ GL_EXTCALL(glBindBuffer(This->buffer_type_hint, This->buffer_object)); ++ checkGLcall("glBindBuffer"); ++ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) ++ { ++ GLbitfield mapflags; ++ mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; ++ if (flags & WINED3D_BUFFER_DISCARD) ++ mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT; ++ else if (!(flags & WINED3D_BUFFER_SYNC)) ++ mapflags |= GL_MAP_UNSYNCHRONIZED_BIT; ++ map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, ++ This->resource.size, mapflags)); ++ checkGLcall("glMapBufferRange"); ++ } ++ else ++ { ++ if (This->flags & WINED3D_BUFFER_APPLESYNC) ++ { ++ DWORD syncflags = 0; ++ if (flags & WINED3D_BUFFER_DISCARD) ++ syncflags |= WINED3D_MAP_DISCARD; ++ else if (!(flags & WINED3D_BUFFER_SYNC)) ++ syncflags |= WINED3D_MAP_NOOVERWRITE; ++ buffer_sync_apple(This, syncflags, gl_info); ++ } ++ map = GL_EXTCALL(glMapBuffer(This->buffer_type_hint, GL_WRITE_ONLY)); ++ checkGLcall("glMapBuffer"); ++ } ++ if (!map) ++ { ++ ERR("Failed to map opengl buffer\n"); ++ return; ++#endif /* STAGING_CSMT */ + } + + while (This->modified_areas) +@@ -692,12 +800,33 @@ + start = This->maps[This->modified_areas].offset; + len = This->maps[This->modified_areas].size; + ++#if defined(STAGING_CSMT) + GL_EXTCALL(glBufferSubData(This->buffer_type_hint, start, len, (BYTE *)This->resource.heap_memory + start)); + checkGLcall("glBufferSubData"); + } + } + + static void buffer_mark_used(struct wined3d_buffer *buffer) ++#else /* STAGING_CSMT */ ++ memcpy(map + start, (BYTE *)This->resource.heap_memory + start, len); ++ ++ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) ++ { ++ GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len)); ++ checkGLcall("glFlushMappedBufferRange"); ++ } ++ else if (This->flags & WINED3D_BUFFER_FLUSH) ++ { ++ GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len)); ++ checkGLcall("glFlushMappedBufferRangeAPPLE"); ++ } ++ } ++ GL_EXTCALL(glUnmapBuffer(This->buffer_type_hint)); ++ checkGLcall("glUnmapBuffer"); ++} ++ ++void buffer_mark_used(struct wined3d_buffer *buffer) ++#endif /* STAGING_CSMT */ + { + buffer->flags &= ~(WINED3D_BUFFER_SYNC | WINED3D_BUFFER_DISCARD); + } +@@ -716,6 +845,14 @@ + + TRACE("buffer %p.\n", buffer); + ++#if !defined(STAGING_CSMT) ++ if (buffer->resource.map_count) ++ { ++ WARN("Buffer is mapped, skipping preload.\n"); ++ return; ++ } ++ ++#endif /* STAGING_CSMT */ + buffer_mark_used(buffer); + + if (!buffer->buffer_object) +@@ -904,6 +1041,7 @@ + + void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) + { ++#if defined(STAGING_CSMT) + struct wined3d_device *device = buffer->resource.device; + + if (buffer->resource.map_count) +@@ -913,6 +1051,12 @@ + } + + wined3d_cs_emit_buffer_preload(device->cs, buffer); ++#else /* STAGING_CSMT */ ++ struct wined3d_context *context; ++ context = context_acquire(buffer->resource.device, NULL); ++ buffer_internal_preload(buffer, context, NULL); ++ context_release(context); ++#endif /* STAGING_CSMT */ + } + + struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer) +@@ -926,6 +1070,7 @@ + { + LONG count; + BYTE *base; ++#if defined(STAGING_CSMT) + struct wined3d_device *device = buffer->resource.device; + struct wined3d_context *context; + +@@ -950,6 +1095,10 @@ + wined3d_cs_emit_create_vbo(device->cs, buffer); + buffer->flags &= ~WINED3D_BUFFER_CREATEBO; + } ++#else /* STAGING_CSMT */ ++ ++ TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags); ++#endif /* STAGING_CSMT */ + + flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags); + /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001 multitexture +@@ -958,7 +1107,11 @@ + * previous contents of the buffer. The r600g driver only does this when + * the buffer is currently in use, while the proprietary NVIDIA driver + * appears to do this unconditionally. */ ++#if defined(STAGING_CSMT) + if (buffer->ignore_discard) ++#else /* STAGING_CSMT */ ++ if (buffer->flags & WINED3D_BUFFER_DISCARD) ++#endif /* STAGING_CSMT */ + flags &= ~WINED3D_MAP_DISCARD; + count = ++buffer->resource.map_count; + +@@ -969,6 +1122,7 @@ + * being uploaded in that case. Two such applications are Port Royale + * and Darkstar One. */ + if (flags & WINED3D_MAP_DISCARD) ++#if defined(STAGING_CSMT) + wined3d_cs_emit_buffer_invalidate_bo_range(device->cs, buffer, 0, 0); + else if (!(flags & WINED3D_MAP_READONLY)) + wined3d_cs_emit_buffer_invalidate_bo_range(device->cs, buffer, offset, size); +@@ -986,6 +1140,19 @@ + wined3d_cs_emit_glfinish(device->cs); + device->cs->ops->finish(device->cs); + } ++#else /* STAGING_CSMT */ ++ buffer_invalidate_bo_range(buffer, 0, 0); ++ else if (!(flags & WINED3D_MAP_READONLY)) ++ buffer_invalidate_bo_range(buffer, offset, size); ++ ++ if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER)) ++ { ++ if (count == 1) ++ { ++ struct wined3d_device *device = buffer->resource.device; ++ struct wined3d_context *context; ++ const struct wined3d_gl_info *gl_info; ++#endif /* STAGING_CSMT */ + + context = context_acquire(device, NULL); + gl_info = context->gl_info; +@@ -1036,6 +1203,7 @@ + buffer_get_sysmem(buffer, context); + } + TRACE("New pointer is %p.\n", buffer->resource.heap_memory); ++#if defined(STAGING_CSMT) + } + context_release(context); + } +@@ -1075,6 +1243,21 @@ + } + + base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.map_heap_memory; ++#else /* STAGING_CSMT */ ++ buffer->map_ptr = NULL; ++ } ++ context_release(context); ++ } ++ } ++ ++ if (flags & WINED3D_MAP_DISCARD) ++ buffer->flags |= WINED3D_BUFFER_DISCARD; ++ else if (!(flags & WINED3D_MAP_NOOVERWRITE)) ++ buffer->flags |= WINED3D_BUFFER_SYNC; ++ } ++ ++ base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory; ++#endif /* STAGING_CSMT */ + *data = base + offset; + + TRACE("Returning memory at %p (base %p, offset %u).\n", *data, base, offset); +@@ -1128,7 +1311,11 @@ + checkGLcall("glFlushMappedBufferRange"); + } + } ++#if defined(STAGING_CSMT) + else if (buffer->flags & WINED3D_BUFFER_APPLESYNC) ++#else /* STAGING_CSMT */ ++ else if (buffer->flags & WINED3D_BUFFER_FLUSH) ++#endif /* STAGING_CSMT */ + { + for (i = 0; i < buffer->modified_areas; ++i) + { +@@ -1139,6 +1326,7 @@ + } + + GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint)); ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFinish(); + else if (wined3d_settings.strict_draw_ordering) +@@ -1147,6 +1335,18 @@ + + buffer_clear_dirty_areas(buffer); + buffer->map_ptr = NULL; ++#else /* STAGING_CSMT */ ++ if (wined3d_settings.strict_draw_ordering) ++ gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ ++ context_release(context); ++ ++ buffer_clear_dirty_areas(buffer); ++ buffer->map_ptr = NULL; ++ } ++ else if (buffer->flags & WINED3D_BUFFER_HASDESC) ++ { ++ wined3d_buffer_preload(buffer); ++#endif /* STAGING_CSMT */ + } + } + +@@ -1198,6 +1398,7 @@ + return WINED3D_OK; + } + ++#if defined(STAGING_CSMT) + static void wined3d_buffer_location_invalidated(struct wined3d_resource *resource, DWORD location) + { + ERR("Not yet implemented.\n"); +@@ -1210,6 +1411,7 @@ + ERR("Not yet implemented.\n"); + } + ++#endif /* STAGING_CSMT */ + static const struct wined3d_resource_ops buffer_resource_ops = + { + buffer_resource_incref, +@@ -1217,8 +1419,10 @@ + buffer_unload, + buffer_resource_sub_resource_map, + buffer_resource_sub_resource_unmap, ++#if defined(STAGING_CSMT) + wined3d_buffer_location_invalidated, + wined3d_buffer_load_location, ++#endif /* STAGING_CSMT */ + }; + + static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device, +@@ -1250,7 +1454,9 @@ + return hr; + } + buffer->buffer_type_hint = bind_hint; ++#if defined(STAGING_CSMT) + buffer->ignore_discard = TRUE; ++#endif /* STAGING_CSMT */ + + TRACE("size %#x, usage %#x, format %s, memory @ %p, iface @ %p.\n", buffer->resource.size, buffer->resource.usage, + debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory, buffer); +@@ -1266,6 +1472,7 @@ + + dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE]; + ++#if defined(STAGING_CSMT) + /* Observations show that draw_strided_slow is faster on dynamic VBs than converting + + * drawStridedFast (half-life 2 and others). + * +@@ -1273,6 +1480,15 @@ + * show that draw_strided_slow is faster than converting + uploading + drawStridedFast. + * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers. + */ ++#else /* STAGING_CSMT */ ++ /* Observations show that drawStridedSlow is faster on dynamic VBs than converting + ++ * drawStridedFast (half-life 2 and others). ++ * ++ * Basically converting the vertices in the buffer is quite expensive, and observations ++ * show that drawStridedSlow is faster than converting + uploading + drawStridedFast. ++ * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers. ++ */ ++#endif /* STAGING_CSMT */ + if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT]) + { + TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n"); +@@ -1290,6 +1506,7 @@ + buffer->flags |= WINED3D_BUFFER_CREATEBO; + } + ++#if defined(STAGING_CSMT) + buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps)); + if (!buffer->maps) + { +@@ -1300,6 +1517,7 @@ + } + buffer->maps_size = 1; + ++#endif /* STAGING_CSMT */ + if (data) + { + BYTE *ptr; +@@ -1308,7 +1526,9 @@ + if (FAILED(hr)) + { + ERR("Failed to map buffer, hr %#x\n", hr); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, buffer->maps); ++#endif /* STAGING_CSMT */ + buffer_unload(&buffer->resource); + resource_cleanup(&buffer->resource); + return hr; +@@ -1319,8 +1539,20 @@ + wined3d_buffer_unmap(buffer); + } + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER; ++#else /* STAGING_CSMT */ ++ buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps)); ++ if (!buffer->maps) ++ { ++ ERR("Out of memory\n"); ++ buffer_unload(&buffer->resource); ++ resource_cleanup(&buffer->resource); ++ return E_OUTOFMEMORY; ++ } ++ buffer->maps_size = 1; ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -1429,6 +1661,7 @@ + + return WINED3D_OK; + } ++#if defined(STAGING_CSMT) + + void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) + { +@@ -1436,3 +1669,4 @@ + buffer->resource.heap_memory = mem; + buffer->flags |= WINED3D_BUFFER_DISCARD; + } ++#endif /* STAGING_CSMT */ diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -1565,1571 +899,1342 @@ diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c } } -diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c ---- a/dlls/wined3d/stateblock.c -+++ b/dlls/wined3d/stateblock.c -@@ -464,7 +464,9 @@ - struct wined3d_texture *texture; - struct wined3d_buffer *buffer; - struct wined3d_shader *shader; -+#if defined(STAGING_CSMT) - struct wined3d_rendertarget_view *view; -+#endif /* STAGING_CSMT */ - unsigned int i, j; +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -22,11 +22,18 @@ - if ((decl = state->vertex_declaration)) -@@ -541,6 +543,7 @@ - } - } - } -+#if defined(STAGING_CSMT) - - if (state->fb.depth_stencil) - { -@@ -566,6 +569,7 @@ - } - } - } -+#endif /* STAGING_CSMT */ - } - - void state_cleanup(struct wined3d_state *state) -@@ -593,7 +597,9 @@ - - HeapFree(GetProcessHeap(), 0, state->vs_consts_f); - HeapFree(GetProcessHeap(), 0, state->ps_consts_f); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, state->fb.render_targets); -+#endif /* STAGING_CSMT */ - } - - ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock) -@@ -1075,8 +1081,13 @@ - gl_primitive_type = stateblock->state.gl_primitive_type; - prev = device->update_state->gl_primitive_type; - device->update_state->gl_primitive_type = gl_primitive_type; -+#if defined(STAGING_CSMT) - if (gl_primitive_type != prev) - wined3d_cs_emit_set_primitive_type(device->cs, gl_primitive_type); -+#else /* STAGING_CSMT */ -+ if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS)) -+ device_invalidate_state(device, STATE_POINT_ENABLE); -+#endif /* STAGING_CSMT */ - } - - if (stateblock->changed.indices) -@@ -1334,6 +1345,7 @@ - state->sampler_states[i][WINED3D_SAMP_ELEMENT_INDEX] = 0; - /* TODO: Vertex offset in the presampled displacement map. */ - state->sampler_states[i][WINED3D_SAMP_DMAP_OFFSET] = 0; -+#if defined(STAGING_CSMT) - state->textures[i] = NULL; - } - -@@ -1351,6 +1363,19 @@ - unsigned int i; - - state->flags = flags; -+#else /* STAGING_CSMT */ -+ } -+} -+ -+HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb, -+ const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info, -+ DWORD flags) -+{ -+ unsigned int i; -+ -+ state->flags = flags; -+ state->fb = fb; -+#endif /* STAGING_CSMT */ - - for (i = 0; i < LIGHTMAP_SIZE; i++) - { -@@ -1368,6 +1393,7 @@ - return E_OUTOFMEMORY; - } + WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#if defined(STAGING_CSMT) - if (!(state->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(*state->fb.render_targets) * gl_info->limits.buffers))) - { -@@ -1377,6 +1403,7 @@ - } - state->fb.rt_size = gl_info->limits.buffers; - -+#endif /* STAGING_CSMT */ - if (flags & WINED3D_STATE_INIT_DEFAULT) - state_init_default(state, gl_info); - -@@ -1387,6 +1414,7 @@ - struct wined3d_device *device, enum wined3d_stateblock_type type) + enum wined3d_cs_op { - HRESULT hr; -+#if defined(STAGING_CSMT) - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; - -@@ -1394,6 +1422,14 @@ - stateblock->device = device; - - if (FAILED(hr = state_init(&stateblock->state, gl_info, d3d_info, 0))) + WINED3D_CS_OP_NOP, + WINED3D_CS_OP_SKIP, + WINED3D_CS_OP_FENCE, +#else /* STAGING_CSMT */ -+ const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; ++#define WINED3D_INITIAL_CS_SIZE 4096 + -+ stateblock->ref = 1; -+ stateblock->device = device; -+ -+ if (FAILED(hr = state_init(&stateblock->state, NULL, &device->adapter->gl_info, d3d_info, 0))) ++enum wined3d_cs_op ++{ +#endif /* STAGING_CSMT */ - return hr; - - if (FAILED(hr = stateblock_allocate_shader_constants(stateblock))) -diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c ---- a/dlls/d3d9/tests/visual.c -+++ b/dlls/d3d9/tests/visual.c -@@ -1339,7 +1339,11 @@ - * result on Wine. - * {D3DFMT_YUY2, "D3DFMT_YUY2", BLOCKS, 0}, - * {D3DFMT_UYVY, "D3DFMT_UYVY", BLOCKS, 0}, */ + WINED3D_CS_OP_PRESENT, + WINED3D_CS_OP_CLEAR, + WINED3D_CS_OP_DRAW, +@@ -53,6 +60,7 @@ + WINED3D_CS_OP_SET_COLOR_KEY, + WINED3D_CS_OP_SET_MATERIAL, + WINED3D_CS_OP_RESET_STATE, +#if defined(STAGING_CSMT) - {D3DFMT_DXT1, "D3DFMT_DXT1", BLOCKS, 0}, -+#else /* STAGING_CSMT */ -+ {D3DFMT_DXT1, "D3DFMT_DXT1", BLOCKS | TODO_FILL_RETURN, 0}, -+#endif /* STAGING_CSMT */ - /* Vendor-specific formats like ATI2N are a non-issue here since they're not - * supported as offscreen plain surfaces and do not support D3DUSAGE_RENDERTARGET - * when created as texture. */ -@@ -17630,7 +17634,11 @@ - fill_surface(surface_managed, 0x0000ff00, D3DLOCK_NO_DIRTY_UPDATE); - add_dirty_rect_test_draw(device); - color = getPixelColor(device, 320, 240); -+#if defined(STAGING_CSMT) - todo_wine ok(color_match(color, 0x00ff0000, 1), -+#else /* STAGING_CSMT */ -+ ok(color_match(color, 0x00ff0000, 1), -+#endif /* STAGING_CSMT */ - "Expected color 0x00ff0000, got 0x%08x.\n", color); - hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -1,3 +1,4 @@ -+#if defined(STAGING_CSMT) - /* - * Direct3D wine internal private include file - * -@@ -21,6 +22,31 @@ - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ -+#else /* STAGING_CSMT */ -+/* -+ * Direct3D wine internal private include file -+ * -+ * Copyright 2002-2003 The wine-d3d team -+ * Copyright 2002-2003 Raphael Junqueira -+ * Copyright 2002-2003, 2004 Jason Edmeades -+ * Copyright 2005 Oliver Stieber -+ * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+#endif /* STAGING_CSMT */ - - #ifndef __WINE_WINED3D_PRIVATE_H - #define __WINE_WINED3D_PRIVATE_H -@@ -31,7 +57,9 @@ - #define WINE_GLAPI - #endif - -+#if defined(STAGING_CSMT) - #include -+#endif /* STAGING_CSMT */ - #include - #include - #include -@@ -284,8 +312,10 @@ - unsigned int max_sm_gs; - unsigned int max_sm_ps; - BOOL no_3d; -+#if defined(STAGING_CSMT) - BOOL cs_multithreaded; - BOOL ignore_rt_map; -+#endif /* STAGING_CSMT */ - }; - - extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; -@@ -1026,9 +1056,14 @@ - WORD use_map; /* MAX_ATTRIBS, 16 */ - }; - -+#if defined(STAGING_CSMT) - void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, - UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count, - BOOL indexed) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count, -+ UINT start_instance, UINT instance_count, BOOL indexed) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN; - - #define eps 1e-8f -@@ -1116,8 +1151,10 @@ - struct list entry; - GLuint id; - struct wined3d_context *context; -+#if defined(STAGING_CSMT) - DWORD samples; - BOOL started; -+#endif /* STAGING_CSMT */ - }; - - union wined3d_gl_query_object -@@ -1153,6 +1190,7 @@ - struct list entry; - GLuint id; - struct wined3d_context *context; -+#if defined(STAGING_CSMT) - UINT64 timestamp; - }; - -@@ -1188,6 +1226,12 @@ - for (i = 0; i < min(dst->rt_size, src->rt_size); i++) - dst->render_targets[i] = src->render_targets[i]; - } + WINED3D_CS_OP_SET_VS_CONSTS_F, + WINED3D_CS_OP_SET_VS_CONSTS_B, + WINED3D_CS_OP_SET_VS_CONSTS_I, +@@ -133,6 +141,30 @@ + float depth; + DWORD stencil; + RECT rects[1]; +#else /* STAGING_CSMT */ +}; + -+void context_alloc_timestamp_query(struct wined3d_context *context, struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; -+void context_free_timestamp_query(struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - struct wined3d_context - { -@@ -1203,7 +1247,9 @@ - DWORD dirtyArray[STATE_HIGHEST + 1]; /* Won't get bigger than that, a state is never marked dirty 2 times */ - DWORD numDirtyEntries; - DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */ -+#if defined(STAGING_CSMT) - struct wined3d_fb_state current_fb; -+#endif /* STAGING_CSMT */ - - struct wined3d_swapchain *swapchain; - struct wined3d_surface *current_rt; -@@ -1301,8 +1347,17 @@ - GLfloat fog_coord_value; - GLfloat color[4], fogstart, fogend, fogcolor[4]; - GLuint dummy_arbfp_prog; -+#if defined(STAGING_CSMT) - - GLenum offscreenBuffer; -+#else /* STAGING_CSMT */ -+}; -+ -+struct wined3d_fb_state ++struct wined3d_cs_present +{ -+ struct wined3d_rendertarget_view **render_targets; -+ struct wined3d_rendertarget_view *depth_stencil; -+#endif /* STAGING_CSMT */ - }; - - typedef void (*APPLYSTATEFUNC)(struct wined3d_context *ctx, const struct wined3d_state *state, DWORD state_id); -@@ -1445,8 +1500,12 @@ - void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN; - BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device, - UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, - const struct wined3d_state *state) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, - struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN; - void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, -@@ -2029,7 +2088,11 @@ - struct wined3d_state - { - DWORD flags; -+#if defined(STAGING_CSMT) - struct wined3d_fb_state fb; -+#else /* STAGING_CSMT */ -+ const struct wined3d_fb_state *fb; -+#endif /* STAGING_CSMT */ - - struct wined3d_vertex_declaration *vertex_declaration; - struct wined3d_stream_output stream_output[MAX_STREAM_OUT]; -@@ -2074,6 +2137,7 @@ - DWORD render_states[WINEHIGHEST_RENDER_STATE + 1]; - }; - -+#if defined(STAGING_CSMT) - struct wined3d_gl_bo - { - GLuint name; -@@ -2082,6 +2146,7 @@ - UINT size; - }; - -+#endif /* STAGING_CSMT */ - #define WINED3D_UNMAPPED_STAGE ~0U - - /* Multithreaded flag. Removed from the public header to signal that -@@ -2137,11 +2202,23 @@ - struct wined3d_rendertarget_view *back_buffer_view; - struct wined3d_swapchain **swapchains; - UINT swapchain_count; -+#if defined(STAGING_CSMT) - struct wined3d_rendertarget_view *auto_depth_stencil_view; - - struct list resources; /* a linked list to track resources created by the device */ - struct list shaders; /* a linked list to track shaders (pixel and vertex) */ - struct wine_rb_tree samplers; -+#else /* STAGING_CSMT */ -+ -+ struct list resources; /* a linked list to track resources created by the device */ -+ struct list shaders; /* a linked list to track shaders (pixel and vertex) */ -+ struct wine_rb_tree samplers; -+ -+ /* Render Target Support */ -+ struct wined3d_fb_state fb; -+ struct wined3d_surface *onscreen_depth_stencil; -+ struct wined3d_rendertarget_view *auto_depth_stencil_view; -+#endif /* STAGING_CSMT */ - - /* For rendering to a texture using glCopyTexImage */ - GLuint depth_blt_texture; -@@ -2152,6 +2229,9 @@ - UINT xScreenSpace; - UINT yScreenSpace; - UINT cursorWidth, cursorHeight; -+#if !defined(STAGING_CSMT) -+ struct wined3d_texture *cursor_texture; -+#endif /* STAGING_CSMT */ - HCURSOR hardwareCursor; - - /* The Wine logo texture */ -@@ -2183,6 +2263,7 @@ - UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN; - void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; - void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; - void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) DECLSPEC_HIDDEN; - void device_exec_update_texture(struct wined3d_context *context, struct wined3d_texture *src_texture, -@@ -2194,6 +2275,11 @@ - void device_create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; - void device_delete_opengl_contexts_cs(struct wined3d_device *device, - struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+void device_switch_onscreen_ds(struct wined3d_device *device, struct wined3d_context *context, -+ struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN; -+void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) - { -@@ -2213,9 +2299,11 @@ - HRESULT (*resource_sub_resource_map)(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags); - HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx); -+#if defined(STAGING_CSMT) - void (*resource_location_invalidated)(struct wined3d_resource *resource, DWORD location); - void (*resource_load_location)(struct wined3d_resource *resource, - struct wined3d_context *context, DWORD location); -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_resource -@@ -2240,6 +2328,7 @@ - UINT depth; - UINT size; - DWORD priority; -+#if defined(STAGING_CSMT) - void *heap_memory, *map_heap_memory, *user_memory, *bitmap_data; - UINT custom_row_pitch, custom_slice_pitch; - struct wined3d_gl_bo *buffer, *map_buffer; -@@ -2247,6 +2336,10 @@ - DWORD locations; - LONG access_fence; - BOOL unmap_dirtify; -+#else /* STAGING_CSMT */ -+ void *heap_memory; -+ struct list resource_list_entry; -+#endif /* STAGING_CSMT */ - - void *parent; - const struct wined3d_parent_ops *parent_ops; -@@ -2271,6 +2364,7 @@ - void *parent, const struct wined3d_parent_ops *parent_ops, - const struct wined3d_resource_ops *resource_ops) DECLSPEC_HIDDEN; - void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN; - BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; - void wined3d_resource_changed(struct wined3d_resource *resource, -@@ -2319,6 +2413,15 @@ - { - while(InterlockedCompareExchange(&resource->access_fence, 0, 0)); - } -+#else /* STAGING_CSMT */ -+BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; -+GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; -+BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN; -+void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - /* Tests show that the start address of resources is 32 byte aligned */ - #define RESOURCE_ALIGNMENT 16 -@@ -2403,7 +2506,9 @@ - - void wined3d_texture_apply_sampler_desc(struct wined3d_texture *texture, - const struct wined3d_sampler_desc *sampler_desc, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - void wined3d_texture_bind(struct wined3d_texture *texture, - struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; - void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture, -@@ -2437,9 +2542,16 @@ - struct wined3d_resource resource; - struct wined3d_texture *container; - -+#if defined(STAGING_CSMT) - DWORD flags; - GLint texture_level; - DWORD download_count; -+#else /* STAGING_CSMT */ -+ DWORD flags, locations; -+ GLint texture_level; -+ DWORD download_count; -+ GLuint pbo; -+#endif /* STAGING_CSMT */ - }; - - static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource) -@@ -2447,6 +2559,7 @@ - return CONTAINING_RECORD(resource, struct wined3d_volume, resource); - } - -+#if defined(STAGING_CSMT) - HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, - unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN; - void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN; -@@ -2462,6 +2575,27 @@ - struct wined3d_surface_dib - { - HBITMAP DIBsection; -+#else /* STAGING_CSMT */ -+BOOL volume_prepare_system_memory(struct wined3d_volume *volume) DECLSPEC_HIDDEN; -+HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, -+ unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN; -+void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN; -+void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch) DECLSPEC_HIDDEN; -+void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, -+ BOOL srgb_mode) DECLSPEC_HIDDEN; -+void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN; -+HRESULT wined3d_volume_map(struct wined3d_volume *volume, -+ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) DECLSPEC_HIDDEN; -+void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN; -+HRESULT wined3d_volume_unmap(struct wined3d_volume *volume) DECLSPEC_HIDDEN; -+void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, -+ const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; -+ -+struct wined3d_surface_dib -+{ -+ HBITMAP DIBsection; -+ void *bitmap_data; -+#endif /* STAGING_CSMT */ - UINT bitmap_size; - }; - -@@ -2487,7 +2621,11 @@ - struct wined3d_surface_ops - { - HRESULT (*surface_private_setup)(struct wined3d_surface *surface); -+#if defined(STAGING_CSMT) - void (*surface_frontbuffer_updated)(struct wined3d_surface *surface); -+#else /* STAGING_CSMT */ -+ void (*surface_unmap)(struct wined3d_surface *surface); -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_surface -@@ -2495,12 +2633,26 @@ - struct wined3d_resource resource; - const struct wined3d_surface_ops *surface_ops; - struct wined3d_texture *container; -+#if defined(STAGING_CSMT) - - DWORD flags; - - UINT pow2Width; - UINT pow2Height; - -+#else /* STAGING_CSMT */ -+ void *user_memory; -+ DWORD locations; -+ ++ enum wined3d_cs_op opcode; ++ HWND dst_window_override; ++ struct wined3d_swapchain *swapchain; ++ const RECT *src_rect; ++ const RECT *dst_rect; ++ const RGNDATA *dirty_region; + DWORD flags; -+ -+ UINT pitch; -+ UINT pow2Width; -+ UINT pow2Height; -+ -+ /* PBO */ -+ GLuint pbo; -+#endif /* STAGING_CSMT */ - GLuint rb_multisample; - GLuint rb_resolved; - GLenum texture_target; -@@ -2544,11 +2696,22 @@ - GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) DECLSPEC_HIDDEN; - void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context, - unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; - void surface_load_ds_location(struct wined3d_surface *surface, - struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; - void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, - struct wined3d_context *context) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; -+void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; -+void surface_load_ds_location(struct wined3d_surface *surface, -+ struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; -+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, -+ struct wined3d_context *context) DECLSPEC_HIDDEN; -+HRESULT surface_load_location(struct wined3d_surface *surface, -+ struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; - void wined3d_surface_prepare(struct wined3d_surface *surface, struct wined3d_context *context, - DWORD location) DECLSPEC_HIDDEN; -@@ -2560,6 +2723,7 @@ - const struct wined3d_gl_info *gl_info, void *mem, unsigned int pitch) DECLSPEC_HIDDEN; - HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point, - struct wined3d_surface *src_surface, const RECT *src_rect) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, - GLenum target, unsigned int level, unsigned int layer, DWORD flags, - struct wined3d_surface **surface) DECLSPEC_HIDDEN; -@@ -2574,6 +2738,17 @@ - void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; - void wined3d_surface_getdc_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; - void wined3d_surface_releasedc_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+void surface_validate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; -+HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, -+ GLenum target, unsigned int level, unsigned int layer, DWORD flags, -+ struct wined3d_surface **surface) DECLSPEC_HIDDEN; -+void wined3d_surface_destroy(struct wined3d_surface *surface) DECLSPEC_HIDDEN; -+void surface_prepare_map_memory(struct wined3d_surface *surface) DECLSPEC_HIDDEN; -+void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, -+ const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point, -+ BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context, - const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -@@ -2595,8 +2770,10 @@ - GLuint name; - }; - -+#if defined(STAGING_CSMT) - void wined3d_sampler_destroy(struct wined3d_sampler *sampler) DECLSPEC_HIDDEN; - -+#endif /* STAGING_CSMT */ - struct wined3d_vertex_declaration_element - { - const struct wined3d_format *format; -@@ -2625,8 +2802,10 @@ - BOOL half_float_conv_needed; - }; - -+#if defined(STAGING_CSMT) - void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; - -+#endif /* STAGING_CSMT */ - struct wined3d_saved_states - { - DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1]; -@@ -2694,6 +2873,7 @@ - void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN; - - void state_cleanup(struct wined3d_state *state) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - HRESULT state_init(struct wined3d_state *state, const struct wined3d_gl_info *gl_info, - const struct wined3d_d3d_info *d3d_info, DWORD flags) DECLSPEC_HIDDEN; - void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN; -@@ -2744,6 +2924,32 @@ - void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; - void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, struct wined3d_context *context, - struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb, -+ const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info, -+ DWORD flags) DECLSPEC_HIDDEN; -+void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN; -+ -+struct wined3d_cs_ops -+{ -+ void *(*require_space)(struct wined3d_cs *cs, size_t size); -+ void (*submit)(struct wined3d_cs *cs); +}; + -+struct wined3d_cs ++struct wined3d_cs_clear +{ -+ const struct wined3d_cs_ops *ops; ++ enum wined3d_cs_op opcode; ++ DWORD rect_count; ++ const RECT *rects; ++ DWORD flags; ++ const struct wined3d_color *color; ++ float depth; ++ DWORD stencil; ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_cs_draw +@@ -155,6 +187,7 @@ + struct wined3d_cs_set_viewport + { + enum wined3d_cs_op opcode; ++#if defined(STAGING_CSMT) + struct wined3d_viewport viewport; + }; + +@@ -162,6 +195,15 @@ + { + enum wined3d_cs_op opcode; + RECT rect; ++#else /* STAGING_CSMT */ ++ const struct wined3d_viewport *viewport; ++}; ++ ++struct wined3d_cs_set_scissor_rect ++{ ++ enum wined3d_cs_op opcode; ++ const RECT *rect; ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_cs_set_rendertarget_view +@@ -289,6 +331,7 @@ + { + enum wined3d_cs_op opcode; + enum wined3d_transform_state state; ++#if defined(STAGING_CSMT) + struct wined3d_matrix matrix; + }; + +@@ -303,6 +346,22 @@ + { + enum wined3d_cs_op opcode; + struct wined3d_material material; ++#else /* STAGING_CSMT */ ++ const struct wined3d_matrix *matrix; ++}; ++ ++struct wined3d_cs_set_clip_plane ++{ ++ enum wined3d_cs_op opcode; ++ UINT plane_idx; ++ const struct wined3d_vec4 *plane; ++}; ++ ++struct wined3d_cs_set_material ++{ ++ enum wined3d_cs_op opcode; ++ const struct wined3d_material *material; ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_cs_reset_state +@@ -310,6 +369,7 @@ + enum wined3d_cs_op opcode; + }; + ++#if defined(STAGING_CSMT) + struct wined3d_cs_set_consts_f + { + enum wined3d_cs_op opcode; +@@ -2880,197 +2940,971 @@ + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, + /* WINED3D_CS_OP_SKIP */ wined3d_cs_exec_skip, + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +- /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, +- /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, +- /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, +- /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, +- /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, +- /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, +- /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, +- /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, +- /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, +- /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, +- /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, +- /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, +- /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, +- /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, +- /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, +- /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, +- /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, +- /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, +- /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, +- /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, +- /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, +- /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, +- /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, +- /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, +- /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, +- /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, +- /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, +- /* WINED3D_CS_OP_SET_VS_CONSTS_B */ wined3d_cs_exec_set_vs_consts_b, +- /* WINED3D_CS_OP_SET_VS_CONSTS_I */ wined3d_cs_exec_set_vs_consts_i, +- /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, +- /* WINED3D_CS_OP_SET_PS_CONSTS_B */ wined3d_cs_exec_set_ps_consts_b, +- /* WINED3D_CS_OP_SET_PS_CONSTS_I */ wined3d_cs_exec_set_ps_consts_i, +- /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, +- /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX */ wined3d_cs_exec_set_base_vertex_index, +- /* WINED3D_CS_OP_SET_PRIMITIVE_TYPE */ wined3d_cs_exec_set_primitive_type, +- /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light, +- /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable, +- /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, +- /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, +- /* WINED3D_CS_OP_RESOURCE_CHANGED */ wined3d_cs_exec_resource_changed, +- /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, +- /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, +- /* WINED3D_CS_OP_BUFFER_SWAP_MEM */ wined3d_cs_exec_buffer_swap_mem, +- /* WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE */ wined3d_cs_exec_buffer_invalidate_bo_range, +- /* WINED3D_CS_OP_BUFFER_PRELOAD */ wined3d_cs_exec_buffer_preload, +- /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, +- /* WINED3D_CS_OP_QUERY_DESTROY */ wined3d_cs_exec_query_destroy, +- /* WINED3D_CS_OP_UPDATE_SURFACE */ wined3d_cs_exec_update_surface, +- /* WINED3D_CS_OP_TEXTURE_PRELOAD */ wined3d_cs_exec_texture_preload, +- /* WINED3D_CS_OP_SURFACE_PRELOAD */ wined3d_cs_exec_surface_preload, +- /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, +- /* WINED3D_CS_OP_EVICT_RESOURCE */ wined3d_cs_exec_evict_resource, +- /* WINED3D_CS_OP_VIEW_DESTROY */ wined3d_cs_exec_view_destroy, +- /* WINED3D_CS_OP_VDECL_DESTROY */ wined3d_cs_exec_vertex_declaration_destroy, +- /* WINED3D_CS_OP_SHADER_CLEANUP */ wined3d_cs_exec_shader_cleanup, +- /* WINED3D_CS_OP_CREATE_VBO */ wined3d_cs_exec_create_vbo, +- /* WINED3D_CS_OP_RESOURCE_CLEANUP */ wined3d_cs_exec_resource_cleanup, +- /* WINED3D_CS_OP_BUFFER_CLEANUP */ wined3d_cs_exec_buffer_cleanup, +- /* WINED3D_CS_OP_VOLUME_CLEANUP */ wined3d_cs_exec_volume_cleanup, +- /* WINED3D_CS_OP_SURFACE_CLEANUP */ wined3d_cs_exec_surface_cleanup, +- /* WINED3D_CS_OP_TEXTURE_CLEANUP */ wined3d_cs_exec_texture_cleanup, +- /* WINED3D_CS_OP_CREATE_DUMMY_TEXTURES */ wined3d_cs_exec_create_dummy_textures, +- /* WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT */ wined3d_cs_exec_create_swapchain_context, +- /* WINED3D_CS_OP_DELETE_GL_CONTEXTS */ wined3d_cs_exec_delete_gl_contexts, +- /* WINED3D_CS_OP_GETDC */ wined3d_cs_exec_getdc, +- /* WINED3D_CS_OP_RELEASEDC */ wined3d_cs_exec_releasedc, +- /* WINED3D_CS_OP_SAMPLER_DESTROY */ wined3d_cs_exec_sampler_destroy, +- /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, +-}; +- +-static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) ++#else /* STAGING_CSMT */ ++static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + { +- struct wined3d_cs_queue *queue = prio ? &cs->prio_queue : &cs->queue; +- size_t queue_size = sizeof(queue->data) / sizeof(*queue->data); ++ const struct wined3d_cs_present *op = data; ++ struct wined3d_swapchain *swapchain; + +- if (queue_size - size < queue->head) +- { +- struct wined3d_cs_skip *skip; +- size_t nop_size = queue_size - queue->head; ++ swapchain = op->swapchain; ++ wined3d_swapchain_set_window(swapchain, op->dst_window_override); + +- skip = _wined3d_cs_mt_require_space(cs, nop_size, prio); +- if (nop_size < sizeof(*skip)) +- { +- skip->opcode = WINED3D_CS_OP_NOP; +- } +- else +- { +- skip->opcode = WINED3D_CS_OP_SKIP; +- skip->size = nop_size; +- } ++ swapchain->swapchain_ops->swapchain_present(swapchain, ++ op->src_rect, op->dst_rect, op->dirty_region, op->flags); ++} + +- if (prio) +- cs->ops->submit_prio(cs, nop_size); +- else +- cs->ops->submit(cs, nop_size); ++void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, ++ const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, ++ const RGNDATA *dirty_region, DWORD flags) ++{ ++ struct wined3d_cs_present *op; + +- assert(!queue->head); +- } ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_PRESENT; ++ op->dst_window_override = dst_window_override; ++ op->swapchain = swapchain; ++ op->src_rect = src_rect; ++ op->dst_rect = dst_rect; ++ op->dirty_region = dirty_region; ++ op->flags = flags; + +- while(1) +- { +- LONG head = queue->head; +- LONG tail = *((volatile LONG *)&queue->tail); +- LONG new_pos; +- /* Empty */ +- if (head == tail) +- break; +- /* Head ahead of tail, take care of wrap-around */ +- new_pos = (head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +- if (head > tail && (new_pos || tail)) +- break; +- /* Tail ahead of head, but still enough space */ +- if (new_pos < tail && new_pos) +- break; ++ cs->ops->submit(cs); ++} + +- TRACE("Waiting for free space. Head %u, tail %u, want %u\n", head, tail, +- (unsigned int) size); +- } ++static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_clear *op = data; + struct wined3d_device *device; -+ struct wined3d_fb_state fb; -+ struct wined3d_state state; -+ -+ size_t data_size; -+ void *data; -+}; -+ -+struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; -+void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ ++ RECT draw_rect; - void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, - DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; -@@ -2793,6 +2999,7 @@ - void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, - struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; - void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, const float *constants, - UINT vector4f_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN; - void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, -@@ -2856,6 +3063,7 @@ - void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, - unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, - unsigned int depth_pitch) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - /* Direct3D terminology with little modifications. We do not have an issued state - * because only the driver knows about it, but we have a created state because d3d -@@ -2870,8 +3078,12 @@ - struct wined3d_query_ops - { - HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags); -+#if defined(STAGING_CSMT) - BOOL (*query_poll)(struct wined3d_query *query); - BOOL (*query_issue)(struct wined3d_query *query, DWORD flags); -+#else /* STAGING_CSMT */ -+ HRESULT (*query_issue)(struct wined3d_query *query, DWORD flags); -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_query -@@ -2885,12 +3097,16 @@ - enum wined3d_query_type type; - DWORD data_size; - void *extendedData; -+#if defined(STAGING_CSMT) - - LONG counter_main, counter_retrieved; - struct list poll_list_entry; - }; - - void wined3d_query_destroy(struct wined3d_query *query) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+}; -+#endif /* STAGING_CSMT */ - - /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other - * fixed function semantics as D3DCOLOR or FLOAT16 */ -@@ -2917,7 +3133,9 @@ - GLenum buffer_object_usage; - GLenum buffer_type_hint; - DWORD flags; -+#if defined(STAGING_CSMT) - BOOL ignore_discard; -+#endif /* STAGING_CSMT */ - void *map_ptr; - - struct wined3d_map_range *maps; -@@ -2942,11 +3160,15 @@ - BYTE *buffer_get_sysmem(struct wined3d_buffer *This, struct wined3d_context *context) DECLSPEC_HIDDEN; - void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_context *context, - const struct wined3d_state *state) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - void buffer_invalidate_bo_range(struct wined3d_buffer *This, UINT offset, UINT size) DECLSPEC_HIDDEN; - void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) DECLSPEC_HIDDEN; - void buffer_create_buffer_object(struct wined3d_buffer *This, - struct wined3d_context *context) DECLSPEC_HIDDEN; - void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+void buffer_mark_used(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - struct wined3d_rendertarget_view - { -@@ -2985,8 +3207,10 @@ - return surface_from_resource(resource); +- return &queue->data[queue->head]; ++ device = cs->device; ++ wined3d_get_draw_rect(&device->state, &draw_rect); ++ device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, ++ &device->fb, op->rect_count, op->rects, &draw_rect, op->flags, ++ op->color, op->depth, op->stencil); } -+#if defined(STAGING_CSMT) - void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; - -+#endif /* STAGING_CSMT */ - struct wined3d_shader_resource_view +-static inline void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) ++void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, ++ DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) { - LONG refcount; -@@ -2999,8 +3223,12 @@ - struct wined3d_swapchain_ops - { - void (*swapchain_present)(struct wined3d_swapchain *swapchain, const RECT *src_rect, -+#if defined(STAGING_CSMT) - const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags, - struct wined3d_surface *depth_stencil); -+#else /* STAGING_CSMT */ -+ const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags); -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_swapchain -@@ -3039,8 +3267,10 @@ - void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; - HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; - void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - HRESULT swapchain_create_context_cs(struct wined3d_device *device, - struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - /***************************************************************************** - * Utility function prototypes -@@ -3243,7 +3473,9 @@ - void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, - const struct wined3d_shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx) DECLSPEC_HIDDEN; - BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage usage) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) - void shader_cleanup(struct wined3d_shader *shader) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) - { -diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c ---- a/dlls/wined3d/vertexdeclaration.c -+++ b/dlls/wined3d/vertexdeclaration.c -@@ -50,12 +50,14 @@ - return refcount; +- return _wined3d_cs_mt_require_space(cs, size, FALSE); ++ struct wined3d_cs_clear *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_CLEAR; ++ op->rect_count = rect_count; ++ op->rects = rects; ++ op->flags = flags; ++ op->color = color; ++ op->depth = depth; ++ op->stencil = stencil; ++ ++ cs->ops->submit(cs); } -+#if defined(STAGING_CSMT) - void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) +-static inline void *wined3d_cs_mt_require_space_prio(struct wined3d_cs *cs, size_t size) ++static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) { - HeapFree(GetProcessHeap(), 0, declaration->elements); - HeapFree(GetProcessHeap(), 0, declaration); +- return _wined3d_cs_mt_require_space(cs, size, TRUE); ++ const struct wined3d_cs_draw *op = data; ++ ++ draw_primitive(cs->device, op->start_idx, op->index_count, ++ op->start_instance, op->instance_count, op->indexed); } -+#endif /* STAGING_CSMT */ - ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration) +-/* FIXME: wined3d_device_uninit_3d() should either flush and wait, or be an +- * OP itself. */ +-static void wined3d_cs_emit_stop(struct wined3d_cs *cs) ++void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count, ++ UINT start_instance, UINT instance_count, BOOL indexed) { - ULONG refcount = InterlockedDecrement(&declaration->ref); -@@ -64,9 +66,15 @@ +- struct wined3d_cs_stop *op; ++ struct wined3d_cs_draw *op; - if (!refcount) - { -+#if defined(STAGING_CSMT) - const struct wined3d_device *device = declaration->device; - declaration->parent_ops->wined3d_object_destroyed(declaration->parent); - wined3d_cs_emit_vertex_declaration_destroy(device->cs, declaration); -+#else /* STAGING_CSMT */ -+ HeapFree(GetProcessHeap(), 0, declaration->elements); -+ declaration->parent_ops->wined3d_object_destroyed(declaration->parent); -+ HeapFree(GetProcessHeap(), 0, declaration); -+#endif /* STAGING_CSMT */ - } +- op = wined3d_cs_mt_require_space(cs, sizeof(*op)); +- op->opcode = WINED3D_CS_OP_STOP; ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_DRAW; ++ op->start_idx = start_idx; ++ op->index_count = index_count; ++ op->start_instance = start_instance; ++ op->instance_count = instance_count; ++ op->indexed = indexed; - return refcount; -diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c ---- a/dlls/winex11.drv/opengl.c -+++ b/dlls/winex11.drv/opengl.c -@@ -1980,7 +1980,9 @@ - escape.code = X11DRV_FLUSH_GL_DRAWABLE; - escape.gl_drawable = 0; - -+#if defined(STAGING_CSMT) - ERR("glFinish\n"); -+#endif /* STAGING_CSMT */ - if ((gl = get_gl_drawable( WindowFromDC( ctx->hdc ), 0 ))) - { - switch (gl->type) -@@ -2006,7 +2008,9 @@ - escape.code = X11DRV_FLUSH_GL_DRAWABLE; - escape.gl_drawable = 0; - -+#if defined(STAGING_CSMT) - ERR("glFlush\n"); -+#endif /* STAGING_CSMT */ - if ((gl = get_gl_drawable( WindowFromDC( ctx->hdc ), 0 ))) - { - switch (gl->type) -diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c ---- a/dlls/wined3d/query.c -+++ b/dlls/wined3d/query.c -@@ -233,6 +233,7 @@ - return refcount; +- wined3d_cs_mt_submit(cs, sizeof(*op)); ++ cs->ops->submit(cs); } -+#if defined(STAGING_CSMT) - void wined3d_query_destroy(struct wined3d_query *query) +-static void wined3d_cs_mt_finish(struct wined3d_cs *cs) ++static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data) { - /* Queries are specific to the GL context that created them. Not -@@ -263,6 +264,7 @@ - HeapFree(GetProcessHeap(), 0, query); +- BOOL fence; +- +- if (cs->thread_id == GetCurrentThreadId()) +- { +- static BOOL once; +- if (!once) +- { +- FIXME("flush_and_wait called from cs thread\n"); +- once = TRUE; +- } +- return; +- } +- +- wined3d_cs_emit_fence(cs, &fence); ++ const struct wined3d_cs_set_predication *op = data; + +- /* A busy wait should be fine, we're not supposed to have to wait very +- * long. */ +- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++ cs->state.predicate = op->predicate; ++ cs->state.predicate_value = op->value; } -+#endif /* STAGING_CSMT */ - ULONG CDECL wined3d_query_decref(struct wined3d_query *query) +-static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs) ++void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value) { - ULONG refcount = InterlockedDecrement(&query->ref); -@@ -270,7 +272,38 @@ - TRACE("%p decreasing refcount to %u.\n", query, refcount); +- BOOL fence; ++ struct wined3d_cs_set_predication *op; - if (!refcount) -+#if defined(STAGING_CSMT) - wined3d_cs_emit_query_destroy(query->device->cs, query); -+#else /* STAGING_CSMT */ -+ { -+ /* Queries are specific to the GL context that created them. Not -+ * deleting the query will obviously leak it, but that's still better -+ * than potentially deleting a different query with the same id in this -+ * context, and (still) leaking the actual query. */ -+ if (query->type == WINED3D_QUERY_TYPE_EVENT) -+ { -+ struct wined3d_event_query *event_query = query->extendedData; -+ if (event_query) wined3d_event_query_destroy(event_query); -+ } -+ else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION) -+ { -+ struct wined3d_occlusion_query *oq = query->extendedData; +- if (cs->thread_id == GetCurrentThreadId()) +- { +- static BOOL once; +- if (!once) +- { +- FIXME("flush_and_wait called from cs thread\n"); +- once = TRUE; +- } +- return; +- } ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_PREDICATION; ++ op->predicate = predicate; ++ op->value = value; + +- wined3d_cs_emit_fence_prio(cs, &fence); ++ cs->ops->submit(cs); ++} + +- /* A busy wait should be fine, we're not supposed to have to wait very +- * long. */ +- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_viewport *op = data; + -+ if (oq->context) context_free_occlusion_query(oq); -+ HeapFree(GetProcessHeap(), 0, query->extendedData); -+ } -+ else if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP) -+ { -+ struct wined3d_timestamp_query *tq = query->extendedData; -+ -+ if (tq->context) -+ context_free_timestamp_query(tq); -+ HeapFree(GetProcessHeap(), 0, query->extendedData); -+ } -+ -+ HeapFree(GetProcessHeap(), 0, query); -+ } -+#endif /* STAGING_CSMT */ - - return refcount; - } -@@ -295,6 +328,7 @@ - { - TRACE("query %p, flags %#x.\n", query, flags); - -+#if defined(STAGING_CSMT) - if (flags & WINED3DISSUE_END) - query->counter_main++; - -@@ -306,6 +340,9 @@ - query->state = QUERY_SIGNALLED; - - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return query->query_ops->query_issue(query, flags); -+#endif /* STAGING_CSMT */ ++ cs->state.viewport = *op->viewport; ++ device_invalidate_state(cs->device, STATE_VIEWPORT); } - static void fill_query_data(void *out, unsigned int out_size, const void *result, unsigned int result_size) -@@ -316,10 +353,25 @@ - static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, - void *data, DWORD size, DWORD flags) +-static const struct wined3d_cs_ops wined3d_cs_mt_ops = ++void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) { -+#if defined(STAGING_CSMT) - struct wined3d_device *device = query->device; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - struct wined3d_occlusion_query *oq = query->extendedData; - GLuint samples; -+#else /* STAGING_CSMT */ -+ struct wined3d_occlusion_query *oq = query->extendedData; -+ struct wined3d_device *device = query->device; -+ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; -+ struct wined3d_context *context; -+ GLuint available; -+ GLuint samples; -+ HRESULT res; +- wined3d_cs_mt_require_space, ++ struct wined3d_cs_set_viewport *op; + -+ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_VIEWPORT; ++ op->viewport = viewport; + -+ if (!oq->context) -+ query->state = QUERY_CREATED; -+#endif /* STAGING_CSMT */ - - if (query->state == QUERY_CREATED) - { -@@ -330,8 +382,10 @@ - return S_OK; - } - -+#if defined(STAGING_CSMT) - TRACE("(%p) : type D3DQUERY_OCCLUSION, data %p, size %#x, flags %#x.\n", query, data, size, flags); - -+#endif /* STAGING_CSMT */ - if (query->state == QUERY_BUILDING) - { - /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ -@@ -347,6 +401,7 @@ - return S_OK; - } - -+#if defined(STAGING_CSMT) - if (!wined3d_settings.cs_multithreaded) - { - if (!query->query_ops->query_poll(query)) -@@ -378,6 +433,14 @@ - FIXME("%p Wrong thread, returning 1.\n", query); - oq->samples = 1; - return TRUE; -+#else /* STAGING_CSMT */ -+ if (oq->context->tid != GetCurrentThreadId()) -+ { -+ FIXME("%p Wrong thread, returning 1.\n", query); -+ samples = 1; -+ fill_query_data(data, size, &samples, sizeof(samples)); -+ return S_OK; -+#endif /* STAGING_CSMT */ - } - - context = context_acquire(query->device, oq->context->current_rt); -@@ -388,6 +451,7 @@ - - if (available) - { -+#if defined(STAGING_CSMT) - GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); - checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); - TRACE("Returning %d samples.\n", samples); -@@ -459,6 +523,69 @@ - - if (data) - fill_query_data(data, dwSize, &ret, sizeof(ret)); -+#else /* STAGING_CSMT */ -+ if (size) -+ { -+ GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); -+ checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); -+ TRACE("Returning %d samples.\n", samples); -+ fill_query_data(data, size, &samples, sizeof(samples)); -+ } -+ res = S_OK; -+ } -+ else -+ { -+ res = S_FALSE; -+ } -+ -+ context_release(context); -+ -+ return res; ++ cs->ops->submit(cs); +} + -+static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query, -+ void *data, DWORD size, DWORD flags) ++static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) +{ -+ struct wined3d_event_query *event_query = query->extendedData; -+ BOOL signaled; -+ enum wined3d_event_query_result ret; ++ const struct wined3d_cs_set_scissor_rect *op = data; + -+ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); -+ -+ if (!data || !size) return S_OK; -+ if (!event_query) -+ { -+ WARN("Event query not supported by GL, reporting GPU idle.\n"); -+ signaled = TRUE; -+ fill_query_data(data, size, &signaled, sizeof(signaled)); -+ return S_OK; -+ } -+ -+ ret = wined3d_event_query_test(event_query, query->device); -+ switch(ret) -+ { -+ case WINED3D_EVENT_QUERY_OK: -+ case WINED3D_EVENT_QUERY_NOT_STARTED: -+ signaled = TRUE; -+ fill_query_data(data, size, &signaled, sizeof(signaled)); -+ break; -+ -+ case WINED3D_EVENT_QUERY_WAITING: -+ signaled = FALSE; -+ fill_query_data(data, size, &signaled, sizeof(signaled)); -+ break; -+ -+ case WINED3D_EVENT_QUERY_WRONG_THREAD: -+ FIXME("(%p) Wrong thread, reporting GPU idle.\n", query); -+ signaled = TRUE; -+ fill_query_data(data, size, &signaled, sizeof(signaled)); -+ break; -+ -+ case WINED3D_EVENT_QUERY_ERROR: -+ ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+#endif /* STAGING_CSMT */ - - return S_OK; - } -@@ -477,7 +604,11 @@ - return query->type; - } - -+#if defined(STAGING_CSMT) - static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) -+#else /* STAGING_CSMT */ -+static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) -+#endif /* STAGING_CSMT */ - { - TRACE("query %p, flags %#x.\n", query, flags); - -@@ -487,6 +618,7 @@ - struct wined3d_event_query *event_query = query->extendedData; - - /* Faked event query support */ -+#if defined(STAGING_CSMT) - if (!event_query) return FALSE; - - wined3d_event_query_issue(event_query, query->device); -@@ -505,6 +637,30 @@ - struct wined3d_device *device = query->device; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - BOOL poll = FALSE; -+#else /* STAGING_CSMT */ -+ if (!event_query) return WINED3D_OK; -+ -+ wined3d_event_query_issue(event_query, query->device); -+ } -+ else if (flags & WINED3DISSUE_BEGIN) -+ { -+ /* Started implicitly at device creation */ -+ ERR("Event query issued with START flag - what to do?\n"); -+ } -+ -+ if (flags & WINED3DISSUE_BEGIN) -+ query->state = QUERY_BUILDING; -+ else -+ query->state = QUERY_SIGNALLED; -+ -+ return WINED3D_OK; ++ cs->state.scissor_rect = *op->rect; ++ device_invalidate_state(cs->device, STATE_SCISSORRECT); +} + -+static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) ++void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) +{ -+ struct wined3d_device *device = query->device; -+ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; -+#endif /* STAGING_CSMT */ - - TRACE("query %p, flags %#x.\n", query, flags); - -@@ -516,7 +672,11 @@ - /* This is allowed according to msdn and our tests. Reset the query and restart */ - if (flags & WINED3DISSUE_BEGIN) - { -+#if defined(STAGING_CSMT) - if (oq->started) -+#else /* STAGING_CSMT */ -+ if (query->state == QUERY_BUILDING) -+#endif /* STAGING_CSMT */ - { - if (oq->context->tid != GetCurrentThreadId()) - { -@@ -545,7 +705,9 @@ - checkGLcall("glBeginQuery()"); - - context_release(context); -+#if defined(STAGING_CSMT) - oq->started = TRUE; -+#endif /* STAGING_CSMT */ - } - if (flags & WINED3DISSUE_END) - { -@@ -553,7 +715,11 @@ - * our tests show that it returns OK. But OpenGL doesn't like it, so avoid - * generating an error - */ -+#if defined(STAGING_CSMT) - if (oq->started) -+#else /* STAGING_CSMT */ -+ if (query->state == QUERY_BUILDING) -+#endif /* STAGING_CSMT */ - { - if (oq->context->tid != GetCurrentThreadId()) - { -@@ -567,10 +733,15 @@ - checkGLcall("glEndQuery()"); - - context_release(context); -+#if defined(STAGING_CSMT) - poll = TRUE; - } - } - oq->started = FALSE; -+#else /* STAGING_CSMT */ ++ struct wined3d_cs_set_scissor_rect *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; ++ op->rect = rect; ++ ++ cs->ops->submit(cs); ++} ++ ++static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_rendertarget_view *op = data; ++ ++ cs->state.fb->render_targets[op->view_idx] = op->view; ++ device_invalidate_state(cs->device, STATE_FRAMEBUFFER); ++} ++ ++void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx, ++ struct wined3d_rendertarget_view *view) ++{ ++ struct wined3d_cs_set_rendertarget_view *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW; ++ op->view_idx = view_idx; ++ op->view = view; ++ ++ cs->ops->submit(cs); ++} ++ ++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_texture_decref(device->onscreen_depth_stencil->container); ++ 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); ++} ++ ++void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) ++{ ++ struct wined3d_cs_set_depth_stencil_view *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW; ++ op->view = view; ++ ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) ++{ ++ struct wined3d_cs_set_vertex_declaration *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION; ++ op->declaration = declaration; ++ ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, ++ struct wined3d_buffer *buffer, UINT offset, UINT stride) ++{ ++ struct wined3d_cs_set_stream_source *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE; ++ op->stream_idx = stream_idx; ++ op->buffer = buffer; ++ op->offset = offset; ++ op->stride = stride; ++ ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags) ++{ ++ struct wined3d_cs_set_stream_source_freq *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ; ++ op->stream_idx = stream_idx; ++ op->frequency = frequency; ++ op->flags = flags; ++ ++ cs->ops->submit(cs); ++} ++ ++static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_stream_output *op = data; ++ struct wined3d_stream_output *stream; ++ struct wined3d_buffer *prev; ++ ++ stream = &cs->state.stream_output[op->stream_idx]; ++ prev = stream->buffer; ++ stream->buffer = op->buffer; ++ stream->offset = op->offset; ++ ++ if (op->buffer) ++ InterlockedIncrement(&op->buffer->resource.bind_count); ++ if (prev) ++ InterlockedDecrement(&prev->resource.bind_count); ++} ++ ++void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, ++ struct wined3d_buffer *buffer, UINT offset) ++{ ++ struct wined3d_cs_set_stream_output *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT; ++ op->stream_idx = stream_idx; ++ op->buffer = buffer; ++ op->offset = offset; ++ ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, ++ enum wined3d_format_id format_id) ++{ ++ struct wined3d_cs_set_index_buffer *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER; ++ op->buffer = buffer; ++ op->format_id = format_id; ++ ++ cs->ops->submit(cs); ++} ++ ++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)); ++} ++ ++void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, ++ UINT cb_idx, struct wined3d_buffer *buffer) ++{ ++ struct wined3d_cs_set_constant_buffer *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER; ++ op->type = type; ++ op->cb_idx = cb_idx; ++ op->buffer = buffer; ++ ++ cs->ops->submit(cs); ++} ++ ++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; + } + } -+#endif /* STAGING_CSMT */ - } - } - else -@@ -578,6 +749,7 @@ - FIXME("%p Occlusion queries not supported.\n", query); - } - -+#if defined(STAGING_CSMT) - return poll; - } - -@@ -636,6 +808,47 @@ - FIXME("%p Wrong thread, returning 1.\n", query); - tq->timestamp = 1; - return TRUE; -+#else /* STAGING_CSMT */ -+ if (flags & WINED3DISSUE_BEGIN) -+ query->state = QUERY_BUILDING; -+ else -+ query->state = QUERY_SIGNALLED; -+ -+ return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ -+} -+ -+static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, -+ void *data, DWORD size, DWORD flags) -+{ -+ struct wined3d_timestamp_query *tq = query->extendedData; -+ struct wined3d_device *device = query->device; -+ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; -+ struct wined3d_context *context; -+ GLuint available; -+ GLuint64 timestamp; -+ HRESULT res; -+ -+ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); -+ -+ if (!tq->context) -+ query->state = QUERY_CREATED; -+ -+ if (query->state == QUERY_CREATED) -+ { -+ /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves. */ -+ TRACE("Query wasn't yet started, returning S_OK.\n"); -+ timestamp = 0; -+ fill_query_data(data, size, ×tamp, sizeof(timestamp)); -+ return S_OK; -+ } -+ -+ if (tq->context->tid != GetCurrentThreadId()) -+ { -+ FIXME("%p Wrong thread, returning 1.\n", query); -+ timestamp = 1; -+ fill_query_data(data, size, ×tamp, sizeof(timestamp)); -+ return S_OK; -+#endif /* STAGING_CSMT */ - } - - context = context_acquire(query->device, tq->context->current_rt); -@@ -646,6 +859,7 @@ - - if (available) - { -+#if defined(STAGING_CSMT) - GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); - checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); - TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); -@@ -663,6 +877,28 @@ - } - - static BOOL wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) -+#else /* STAGING_CSMT */ -+ if (size) -+ { -+ GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); -+ checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); -+ TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); -+ fill_query_data(data, size, ×tamp, sizeof(timestamp)); + } -+ res = S_OK; ++ ++ 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); ++} ++ ++void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture) ++{ ++ struct wined3d_cs_set_texture *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_TEXTURE; ++ op->stage = stage; ++ op->texture = texture; ++ ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type, ++ UINT view_idx, struct wined3d_shader_resource_view *view) ++{ ++ struct wined3d_cs_set_shader_resource_view *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW; ++ op->type = type; ++ op->view_idx = view_idx; ++ op->view = view; ++ ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type, ++ UINT sampler_idx, struct wined3d_sampler *sampler) ++{ ++ struct wined3d_cs_set_sampler *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_SAMPLER; ++ op->type = type; ++ op->sampler_idx = sampler_idx; ++ op->sampler = sampler; ++ ++ cs->ops->submit(cs); ++} ++ ++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)); ++ device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); ++} ++ ++void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader) ++{ ++ struct wined3d_cs_set_shader *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_SHADER; ++ op->type = type; ++ op->shader = shader; ++ ++ cs->ops->submit(cs); ++} ++ ++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)); ++} ++ ++void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value) ++{ ++ struct wined3d_cs_set_render_state *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_RENDER_STATE; ++ op->state = state; ++ op->value = value; ++ ++ cs->ops->submit(cs); ++} ++ ++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)); ++} ++ ++void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, ++ enum wined3d_texture_stage_state state, DWORD value) ++{ ++ struct wined3d_cs_set_texture_state *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE; ++ op->stage = stage; ++ op->state = state; ++ op->value = value; ++ ++ cs->ops->submit(cs); ++} ++ ++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)); ++} ++ ++void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, ++ enum wined3d_sampler_state state, DWORD value) ++{ ++ struct wined3d_cs_set_sampler_state *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE; ++ op->sampler_idx = sampler_idx; ++ op->state = state; ++ op->value = value; ++ ++ cs->ops->submit(cs); ++} ++ ++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->d3d_info.limits.ffp_vertex_blend_matrices)) ++ device_invalidate_state(cs->device, STATE_TRANSFORM(op->state)); ++} ++ ++void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state, ++ const struct wined3d_matrix *matrix) ++{ ++ struct wined3d_cs_set_transform *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_TRANSFORM; ++ op->state = state; ++ op->matrix = matrix; ++ ++ cs->ops->submit(cs); ++} ++ ++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)); ++} ++ ++void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) ++{ ++ struct wined3d_cs_set_clip_plane *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE; ++ op->plane_idx = plane_idx; ++ op->plane = plane; ++ ++ cs->ops->submit(cs); ++} ++ ++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 + { -+ res = S_FALSE; ++ 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; ++ } + } -+ -+ context_release(context); -+ -+ return res; +} + -+static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) -+#endif /* STAGING_CSMT */ - { - struct wined3d_device *device = query->device; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; -@@ -695,6 +931,7 @@ - } - - if (flags & WINED3DISSUE_END) -+#if defined(STAGING_CSMT) - return TRUE; - return FALSE; - } -@@ -711,6 +948,26 @@ - { - TRACE("Query is building, returning S_FALSE.\n"); - return S_FALSE; -+#else /* STAGING_CSMT */ -+ query->state = QUERY_SIGNALLED; -+ -+ return WINED3D_OK; -+} -+ -+static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query, -+ void *data, DWORD size, DWORD flags) ++void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, ++ WORD flags, const struct wined3d_color_key *color_key) +{ -+ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ struct wined3d_cs_set_color_key *op; + -+ if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT) ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_COLOR_KEY; ++ op->texture = texture; ++ op->flags = flags; ++ if (color_key) + { -+ static const struct wined3d_query_data_timestamp_disjoint disjoint_data = {1000 * 1000 * 1000, FALSE}; -+ -+ if (query->state == QUERY_BUILDING) -+ { -+ TRACE("Query is building, returning S_FALSE.\n"); -+ return S_FALSE; -+#endif /* STAGING_CSMT */ - } - - fill_query_data(data, size, &disjoint_data, sizeof(disjoint_data)); -@@ -724,6 +981,7 @@ - return S_OK; - } - -+#if defined(STAGING_CSMT) - static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *query) - { - return TRUE; -@@ -760,6 +1018,41 @@ - { - wined3d_timestamp_disjoint_query_ops_get_data, - wined3d_timestamp_disjoint_query_ops_poll, -+#else /* STAGING_CSMT */ -+static HRESULT wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) -+{ -+ TRACE("query %p, flags %#x.\n", query, flags); -+ -+ if (flags & WINED3DISSUE_BEGIN) -+ query->state = QUERY_BUILDING; -+ if (flags & WINED3DISSUE_END) -+ query->state = QUERY_SIGNALLED; -+ -+ return WINED3D_OK; -+} -+ -+static const struct wined3d_query_ops event_query_ops = -+{ -+ wined3d_event_query_ops_get_data, -+ wined3d_event_query_ops_issue, -+}; -+ -+static const struct wined3d_query_ops occlusion_query_ops = -+{ -+ wined3d_occlusion_query_ops_get_data, -+ wined3d_occlusion_query_ops_issue, -+}; -+ -+static const struct wined3d_query_ops timestamp_query_ops = -+{ -+ wined3d_timestamp_query_ops_get_data, -+ wined3d_timestamp_query_ops_issue, -+}; -+ -+static const struct wined3d_query_ops timestamp_disjoint_query_ops = -+{ -+ wined3d_timestamp_disjoint_query_ops_get_data, -+#endif /* STAGING_CSMT */ - wined3d_timestamp_disjoint_query_ops_issue, - }; - -@@ -781,6 +1074,7 @@ - } - query->query_ops = &occlusion_query_ops; - query->data_size = sizeof(DWORD); -+#if defined(STAGING_CSMT) - query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(struct wined3d_occlusion_query)); - if (!query->extendedData) -@@ -788,6 +1082,15 @@ - ERR("Failed to allocate occlusion query extended data.\n"); - return E_OUTOFMEMORY; - } -+#else /* STAGING_CSMT */ -+ query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query)); -+ if (!query->extendedData) -+ { -+ ERR("Failed to allocate occlusion query extended data.\n"); -+ return E_OUTOFMEMORY; -+ } -+ ((struct wined3d_occlusion_query *)query->extendedData)->context = NULL; -+#endif /* STAGING_CSMT */ - break; - - case WINED3D_QUERY_TYPE_EVENT: -@@ -860,7 +1163,9 @@ - query->state = QUERY_CREATED; - query->device = device; - query->ref = 1; -+#if defined(STAGING_CSMT) - list_init(&query->poll_list_entry); -+#endif /* STAGING_CSMT */ - - return WINED3D_OK; - } -diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c ---- a/dlls/wined3d/drawprim.c -+++ b/dlls/wined3d/drawprim.c -@@ -36,7 +36,11 @@ - #include - - /* Context activation is done by the caller. */ -+#if defined(STAGING_CSMT) - static void draw_strided_fast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size, -+#else /* STAGING_CSMT */ -+static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size, -+#endif /* STAGING_CSMT */ - const void *idx_data, UINT start_idx, INT base_vertex_index, UINT start_instance, UINT instance_count) - { - if (idx_size) -@@ -95,7 +99,11 @@ - */ - - /* Context activation is done by the caller. */ -+#if defined(STAGING_CSMT) - static void draw_strided_slow(const struct wined3d_state *state, struct wined3d_context *context, -+#else /* STAGING_CSMT */ -+static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_context *context, -+#endif /* STAGING_CSMT */ - const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType, - const void *idxData, UINT idxSize, UINT startIdx) - { -@@ -103,6 +111,9 @@ - const WORD *pIdxBufS = NULL; - const DWORD *pIdxBufL = NULL; - UINT vx_index; -+#if !defined(STAGING_CSMT) -+ const struct wined3d_state *state = &device->state; -+#endif /* STAGING_CSMT */ - LONG SkipnStrides = startIdx; - BOOL pixelShader = use_ps(state); - BOOL specular_fog = FALSE; -@@ -452,7 +463,11 @@ - } - - /* Context activation is done by the caller. */ -+#if defined(STAGING_CSMT) - static void draw_strided_slow_vs(struct wined3d_context *context, const struct wined3d_state *state, -+#else /* STAGING_CSMT */ -+static void drawStridedSlowVs(struct wined3d_context *context, const struct wined3d_state *state, -+#endif /* STAGING_CSMT */ - const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, - const void *idxData, UINT idxSize, UINT startIdx) - { -@@ -509,7 +524,11 @@ - } - - /* Context activation is done by the caller. */ -+#if defined(STAGING_CSMT) - static void draw_strided_instanced(struct wined3d_context *context, const struct wined3d_state *state, -+#else /* STAGING_CSMT */ -+static void drawStridedInstanced(struct wined3d_context *context, const struct wined3d_state *state, -+#endif /* STAGING_CSMT */ - const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, - const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index, UINT instance_count) - { -@@ -594,10 +613,17 @@ - } - - /* Routine common to the draw primitive and draw indexed primitive routines */ -+#if defined(STAGING_CSMT) - void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, - UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count, - BOOL indexed) - { -+#else /* STAGING_CSMT */ -+void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count, -+ UINT start_instance, UINT instance_count, BOOL indexed) -+{ -+ const struct wined3d_state *state = &device->state; -+#endif /* STAGING_CSMT */ - const struct wined3d_stream_info *stream_info; - struct wined3d_event_query *ib_query = NULL; - struct wined3d_stream_info si_emulated; -@@ -610,7 +636,11 @@ - - if (!index_count) return; - -+#if defined(STAGING_CSMT) - context = context_acquire(device, wined3d_rendertarget_view_get_surface(state->fb.render_targets[0])); -+#else /* STAGING_CSMT */ -+ context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); -+#endif /* STAGING_CSMT */ - if (!context->valid) - { - context_release(context); -@@ -621,6 +651,7 @@ - - for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) - { -+#if defined(STAGING_CSMT) - struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(state->fb.render_targets[i]); - if (target && target->resource.format->id != WINED3DFMT_NULL) - { -@@ -628,6 +659,15 @@ - { - wined3d_resource_load_location(&target->resource, context, target->container->resource.draw_binding); - wined3d_resource_invalidate_location(&target->resource, ~target->container->resource.draw_binding); -+#else /* STAGING_CSMT */ -+ struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); -+ if (target && target->resource.format->id != WINED3DFMT_NULL) -+ { -+ if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) -+ { -+ surface_load_location(target, context, target->container->resource.draw_binding); -+ surface_invalidate_location(target, ~target->container->resource.draw_binding); -+#endif /* STAGING_CSMT */ - } - else - { -@@ -636,6 +676,7 @@ - } - } - -+#if defined(STAGING_CSMT) - if (state->fb.depth_stencil) - { - /* Note that this depends on the context_acquire() call above to set -@@ -655,6 +696,27 @@ - wined3d_cs_switch_onscreen_ds(device->cs, context, ds); - - if (ds->resource.locations & location) -+#else /* STAGING_CSMT */ -+ if (device->fb.depth_stencil) -+ { -+ /* Note that this depends on the context_acquire() call above to set -+ * context->render_offscreen properly. We don't currently take the -+ * Z-compare function into account, but we could skip loading the -+ * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note -+ * that we never copy the stencil data.*/ -+ DWORD location = context->render_offscreen ? device->fb.depth_stencil->resource->draw_binding -+ : WINED3D_LOCATION_DRAWABLE; -+ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); -+ -+ if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) -+ { -+ RECT current_rect, draw_rect, r; -+ -+ if (!context->render_offscreen && ds != device->onscreen_depth_stencil) -+ device_switch_onscreen_ds(device, context, ds); -+ -+ if (ds->locations & location) -+#endif /* STAGING_CSMT */ - SetRect(¤t_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy); - else - SetRectEmpty(¤t_rect); -@@ -671,6 +733,7 @@ - wined3d_surface_prepare(ds, context, location); - } - -+#if defined(STAGING_CSMT) - if (!context_apply_draw_state(context, device, state)) - { - context_release(context); -@@ -681,6 +744,18 @@ - if (state->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE]) - { - struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil); -+#else /* STAGING_CSMT */ -+ if (!context_apply_draw_state(context, device)) -+ { -+ context_release(context); -+ WARN("Unable to apply draw state, skipping draw.\n"); -+ return; ++ op->color_key = *color_key; ++ op->set = 1; + } ++ else ++ op->set = 0; + -+ if (device->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE]) -+ { -+ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); ++ cs->ops->submit(cs); ++} ++ ++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); ++} ++ ++void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material) ++{ ++ struct wined3d_cs_set_material *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_MATERIAL; ++ op->material = material; ++ ++ cs->ops->submit(cs); ++} ++ ++static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) ++{ ++ struct wined3d_adapter *adapter = cs->device->adapter; ++ HRESULT hr; ++ ++ state_cleanup(&cs->state); ++ memset(&cs->state, 0, sizeof(cs->state)); ++ if (FAILED(hr = state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info, ++ WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) ++ ERR("Failed to initialize CS state, hr %#x.\n", hr); ++} ++ ++void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) ++{ ++ struct wined3d_cs_reset_state *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_RESET_STATE; ++ ++ cs->ops->submit(cs); ++} ++ ++static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = ++{ +#endif /* STAGING_CSMT */ - DWORD location = context->render_offscreen ? ds->container->resource.draw_binding : WINED3D_LOCATION_DRAWABLE; - - surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); -@@ -763,6 +838,7 @@ - else - WARN_(d3d_perf)("Using immediate mode with vertex shaders for half float emulation.\n"); - ++ /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, ++ /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, ++ /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, ++ /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, ++ /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, ++ /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, ++ /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, ++ /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, ++ /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, ++ /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, ++ /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, ++ /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, ++ /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, ++ /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, ++ /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, ++ /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, ++ /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, ++ /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, ++ /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, ++ /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, ++ /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, ++ /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, ++ /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, ++ /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, ++ /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, ++ /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, +#if defined(STAGING_CSMT) - draw_strided_slow_vs(context, state, stream_info, index_count, - state->gl_primitive_type, idx_data, idx_size, start_idx); - } -@@ -785,6 +861,30 @@ - else - { - draw_strided_fast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data, -+#else /* STAGING_CSMT */ -+ drawStridedSlowVs(context, state, stream_info, index_count, -+ state->gl_primitive_type, idx_data, idx_size, start_idx); ++ /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, ++ /* WINED3D_CS_OP_SET_VS_CONSTS_B */ wined3d_cs_exec_set_vs_consts_b, ++ /* WINED3D_CS_OP_SET_VS_CONSTS_I */ wined3d_cs_exec_set_vs_consts_i, ++ /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, ++ /* WINED3D_CS_OP_SET_PS_CONSTS_B */ wined3d_cs_exec_set_ps_consts_b, ++ /* WINED3D_CS_OP_SET_PS_CONSTS_I */ wined3d_cs_exec_set_ps_consts_i, ++ /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, ++ /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX */ wined3d_cs_exec_set_base_vertex_index, ++ /* WINED3D_CS_OP_SET_PRIMITIVE_TYPE */ wined3d_cs_exec_set_primitive_type, ++ /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light, ++ /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable, ++ /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, ++ /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, ++ /* WINED3D_CS_OP_RESOURCE_CHANGED */ wined3d_cs_exec_resource_changed, ++ /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, ++ /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, ++ /* WINED3D_CS_OP_BUFFER_SWAP_MEM */ wined3d_cs_exec_buffer_swap_mem, ++ /* WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE */ wined3d_cs_exec_buffer_invalidate_bo_range, ++ /* WINED3D_CS_OP_BUFFER_PRELOAD */ wined3d_cs_exec_buffer_preload, ++ /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, ++ /* WINED3D_CS_OP_QUERY_DESTROY */ wined3d_cs_exec_query_destroy, ++ /* WINED3D_CS_OP_UPDATE_SURFACE */ wined3d_cs_exec_update_surface, ++ /* WINED3D_CS_OP_TEXTURE_PRELOAD */ wined3d_cs_exec_texture_preload, ++ /* WINED3D_CS_OP_SURFACE_PRELOAD */ wined3d_cs_exec_surface_preload, ++ /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, ++ /* WINED3D_CS_OP_EVICT_RESOURCE */ wined3d_cs_exec_evict_resource, ++ /* WINED3D_CS_OP_VIEW_DESTROY */ wined3d_cs_exec_view_destroy, ++ /* WINED3D_CS_OP_VDECL_DESTROY */ wined3d_cs_exec_vertex_declaration_destroy, ++ /* WINED3D_CS_OP_SHADER_CLEANUP */ wined3d_cs_exec_shader_cleanup, ++ /* WINED3D_CS_OP_CREATE_VBO */ wined3d_cs_exec_create_vbo, ++ /* WINED3D_CS_OP_RESOURCE_CLEANUP */ wined3d_cs_exec_resource_cleanup, ++ /* WINED3D_CS_OP_BUFFER_CLEANUP */ wined3d_cs_exec_buffer_cleanup, ++ /* WINED3D_CS_OP_VOLUME_CLEANUP */ wined3d_cs_exec_volume_cleanup, ++ /* WINED3D_CS_OP_SURFACE_CLEANUP */ wined3d_cs_exec_surface_cleanup, ++ /* WINED3D_CS_OP_TEXTURE_CLEANUP */ wined3d_cs_exec_texture_cleanup, ++ /* WINED3D_CS_OP_CREATE_DUMMY_TEXTURES */ wined3d_cs_exec_create_dummy_textures, ++ /* WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT */ wined3d_cs_exec_create_swapchain_context, ++ /* WINED3D_CS_OP_DELETE_GL_CONTEXTS */ wined3d_cs_exec_delete_gl_contexts, ++ /* WINED3D_CS_OP_GETDC */ wined3d_cs_exec_getdc, ++ /* WINED3D_CS_OP_RELEASEDC */ wined3d_cs_exec_releasedc, ++ /* WINED3D_CS_OP_SAMPLER_DESTROY */ wined3d_cs_exec_sampler_destroy, ++ /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, ++}; ++ ++static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) ++{ ++ struct wined3d_cs_queue *queue = prio ? &cs->prio_queue : &cs->queue; ++ size_t queue_size = sizeof(queue->data) / sizeof(*queue->data); ++ ++ if (queue_size - size < queue->head) ++ { ++ struct wined3d_cs_skip *skip; ++ size_t nop_size = queue_size - queue->head; ++ ++ skip = _wined3d_cs_mt_require_space(cs, nop_size, prio); ++ if (nop_size < sizeof(*skip)) ++ { ++ skip->opcode = WINED3D_CS_OP_NOP; + } + else + { -+ if (context->d3d_info->ffp_generic_attributes) -+ drawStridedSlowVs(context, state, stream_info, index_count, -+ state->gl_primitive_type, idx_data, idx_size, start_idx); -+ else -+ drawStridedSlow(device, context, stream_info, index_count, -+ state->gl_primitive_type, idx_data, idx_size, start_idx); ++ skip->opcode = WINED3D_CS_OP_SKIP; ++ skip->size = nop_size; + } ++ ++ if (prio) ++ cs->ops->submit_prio(cs, nop_size); ++ else ++ cs->ops->submit(cs, nop_size); ++ ++ assert(!queue->head); + } -+ else if (!gl_info->supported[ARB_INSTANCED_ARRAYS] && instance_count) ++ ++ while(1) + { -+ /* Instancing emulation by mixing immediate mode and arrays. */ -+ drawStridedInstanced(context, state, stream_info, index_count, state->gl_primitive_type, -+ idx_data, idx_size, start_idx, state->base_vertex_index, instance_count); ++ LONG head = queue->head; ++ LONG tail = *((volatile LONG *)&queue->tail); ++ LONG new_pos; ++ /* Empty */ ++ if (head == tail) ++ break; ++ /* Head ahead of tail, take care of wrap-around */ ++ new_pos = (head + size) & (WINED3D_CS_QUEUE_SIZE - 1); ++ if (head > tail && (new_pos || tail)) ++ break; ++ /* Tail ahead of head, but still enough space */ ++ if (new_pos < tail && new_pos) ++ break; ++ ++ TRACE("Waiting for free space. Head %u, tail %u, want %u\n", head, tail, ++ (unsigned int) size); + } -+ else ++ ++ return &queue->data[queue->head]; ++} ++ ++static inline void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) ++{ ++ return _wined3d_cs_mt_require_space(cs, size, FALSE); ++} ++ ++static inline void *wined3d_cs_mt_require_space_prio(struct wined3d_cs *cs, size_t size) ++{ ++ return _wined3d_cs_mt_require_space(cs, size, TRUE); ++} ++ ++/* FIXME: wined3d_device_uninit_3d() should either flush and wait, or be an ++ * OP itself. */ ++static void wined3d_cs_emit_stop(struct wined3d_cs *cs) ++{ ++ struct wined3d_cs_stop *op; ++ ++ op = wined3d_cs_mt_require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_STOP; ++ ++ wined3d_cs_mt_submit(cs, sizeof(*op)); ++} ++ ++static void wined3d_cs_mt_finish(struct wined3d_cs *cs) ++{ ++ BOOL fence; ++ ++ if (cs->thread_id == GetCurrentThreadId()) + { -+ drawStridedFast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data, -+#endif /* STAGING_CSMT */ - start_idx, state->base_vertex_index, start_instance, instance_count); ++ static BOOL once; ++ if (!once) ++ { ++ FIXME("flush_and_wait called from cs thread\n"); ++ once = TRUE; ++ } ++ return; ++ } ++ ++ wined3d_cs_emit_fence(cs, &fence); ++ ++ /* A busy wait should be fine, we're not supposed to have to wait very ++ * long. */ ++ while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++} ++ ++static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs) ++{ ++ BOOL fence; ++ ++ if (cs->thread_id == GetCurrentThreadId()) ++ { ++ static BOOL once; ++ if (!once) ++ { ++ FIXME("flush_and_wait called from cs thread\n"); ++ once = TRUE; ++ } ++ return; ++ } ++ ++ wined3d_cs_emit_fence_prio(cs, &fence); ++ ++ /* A busy wait should be fine, we're not supposed to have to wait very ++ * long. */ ++ while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++} ++ ++static const struct wined3d_cs_ops wined3d_cs_mt_ops = ++{ ++ wined3d_cs_mt_require_space, + wined3d_cs_mt_require_space_prio, + wined3d_cs_mt_submit, + wined3d_cs_mt_submit_prio, +@@ -3293,5 +4127,80 @@ + ERR("Closing event failed.\n"); } ++#else /* STAGING_CSMT */ ++}; ++ ++static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) ++{ ++ if (size > cs->data_size) ++ { ++ void *new_data; ++ ++ size = max( size, cs->data_size * 2 ); ++ if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size))) ++ return NULL; ++ ++ cs->data_size = size; ++ cs->data = new_data; ++ } ++ ++ return cs->data; ++} ++ ++static void wined3d_cs_st_submit(struct wined3d_cs *cs) ++{ ++ enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data; ++ ++ wined3d_cs_op_handlers[opcode](cs, cs->data); ++} ++ ++static const struct wined3d_cs_ops wined3d_cs_st_ops = ++{ ++ wined3d_cs_st_require_space, ++ wined3d_cs_st_submit, ++}; ++ ++struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) ++{ ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_cs *cs; ++ ++ if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs)))) ++ return NULL; ++ ++ if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ++ sizeof(*cs->fb.render_targets) * gl_info->limits.buffers))) ++ { ++ HeapFree(GetProcessHeap(), 0, cs); ++ return NULL; ++ } ++ ++ if (FAILED(state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info, ++ WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) ++ { ++ HeapFree(GetProcessHeap(), 0, cs->fb.render_targets); ++ HeapFree(GetProcessHeap(), 0, cs); ++ return NULL; ++ } ++ ++ cs->ops = &wined3d_cs_st_ops; ++ cs->device = device; ++ ++ cs->data_size = WINED3D_INITIAL_CS_SIZE; ++ if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size))) ++ { ++ HeapFree(GetProcessHeap(), 0, cs); ++ return NULL; ++ } ++ ++ return cs; ++} ++ ++void wined3d_cs_destroy(struct wined3d_cs *cs) ++{ ++ state_cleanup(&cs->state); ++ HeapFree(GetProcessHeap(), 0, cs->fb.render_targets); ++ HeapFree(GetProcessHeap(), 0, cs->data); ++#endif /* STAGING_CSMT */ + HeapFree(GetProcessHeap(), 0, cs); + } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4612,6 +3717,242 @@ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c wined3d_device_destroy_bo(device, context, bo); } +#endif /* STAGING_CSMT */ +diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c +--- a/dlls/wined3d/directx.c ++++ b/dlls/wined3d/directx.c +@@ -5555,9 +5555,15 @@ + DebugBreak(); + } + ++#if defined(STAGING_CSMT) + /* Helper functions for providing vertex data to opengl. The arrays are initialized based on + * the extension detection and are used in draw_strided_slow + */ ++#else /* STAGING_CSMT */ ++/* Helper functions for providing vertex data to opengl. The arrays are initialized based on ++ * the extension detection and are used in drawStridedSlow ++ */ ++#endif /* STAGING_CSMT */ + static void WINE_GLAPI position_d3dcolor(const void *data) + { + DWORD pos = *((const DWORD *)data); +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -36,7 +36,11 @@ + #include + + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + static void draw_strided_fast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size, ++#else /* STAGING_CSMT */ ++static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size, ++#endif /* STAGING_CSMT */ + const void *idx_data, UINT start_idx, INT base_vertex_index, UINT start_instance, UINT instance_count) + { + if (idx_size) +@@ -95,7 +99,11 @@ + */ + + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + static void draw_strided_slow(const struct wined3d_state *state, struct wined3d_context *context, ++#else /* STAGING_CSMT */ ++static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_context *context, ++#endif /* STAGING_CSMT */ + const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType, + const void *idxData, UINT idxSize, UINT startIdx) + { +@@ -103,6 +111,9 @@ + const WORD *pIdxBufS = NULL; + const DWORD *pIdxBufL = NULL; + UINT vx_index; ++#if !defined(STAGING_CSMT) ++ const struct wined3d_state *state = &device->state; ++#endif /* STAGING_CSMT */ + LONG SkipnStrides = startIdx; + BOOL pixelShader = use_ps(state); + BOOL specular_fog = FALSE; +@@ -452,7 +463,11 @@ + } + + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + static void draw_strided_slow_vs(struct wined3d_context *context, const struct wined3d_state *state, ++#else /* STAGING_CSMT */ ++static void drawStridedSlowVs(struct wined3d_context *context, const struct wined3d_state *state, ++#endif /* STAGING_CSMT */ + const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, + const void *idxData, UINT idxSize, UINT startIdx) + { +@@ -509,7 +524,11 @@ + } + + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + static void draw_strided_instanced(struct wined3d_context *context, const struct wined3d_state *state, ++#else /* STAGING_CSMT */ ++static void drawStridedInstanced(struct wined3d_context *context, const struct wined3d_state *state, ++#endif /* STAGING_CSMT */ + const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, + const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index, UINT instance_count) + { +@@ -594,10 +613,17 @@ + } + + /* Routine common to the draw primitive and draw indexed primitive routines */ ++#if defined(STAGING_CSMT) + void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, + UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count, + BOOL indexed) + { ++#else /* STAGING_CSMT */ ++void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count, ++ UINT start_instance, UINT instance_count, BOOL indexed) ++{ ++ const struct wined3d_state *state = &device->state; ++#endif /* STAGING_CSMT */ + const struct wined3d_stream_info *stream_info; + struct wined3d_event_query *ib_query = NULL; + struct wined3d_stream_info si_emulated; +@@ -610,7 +636,11 @@ + + if (!index_count) return; + ++#if defined(STAGING_CSMT) + context = context_acquire(device, wined3d_rendertarget_view_get_surface(state->fb.render_targets[0])); ++#else /* STAGING_CSMT */ ++ context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); ++#endif /* STAGING_CSMT */ + if (!context->valid) + { + context_release(context); +@@ -621,6 +651,7 @@ + + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { ++#if defined(STAGING_CSMT) + struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(state->fb.render_targets[i]); + if (target && target->resource.format->id != WINED3DFMT_NULL) + { +@@ -628,6 +659,15 @@ + { + wined3d_resource_load_location(&target->resource, context, target->container->resource.draw_binding); + wined3d_resource_invalidate_location(&target->resource, ~target->container->resource.draw_binding); ++#else /* STAGING_CSMT */ ++ struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); ++ if (target && target->resource.format->id != WINED3DFMT_NULL) ++ { ++ if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) ++ { ++ surface_load_location(target, context, target->container->resource.draw_binding); ++ surface_invalidate_location(target, ~target->container->resource.draw_binding); ++#endif /* STAGING_CSMT */ + } + else + { +@@ -636,6 +676,7 @@ + } + } + ++#if defined(STAGING_CSMT) + if (state->fb.depth_stencil) + { + /* Note that this depends on the context_acquire() call above to set +@@ -655,6 +696,27 @@ + wined3d_cs_switch_onscreen_ds(device->cs, context, ds); + + if (ds->resource.locations & location) ++#else /* STAGING_CSMT */ ++ if (device->fb.depth_stencil) ++ { ++ /* Note that this depends on the context_acquire() call above to set ++ * context->render_offscreen properly. We don't currently take the ++ * Z-compare function into account, but we could skip loading the ++ * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note ++ * that we never copy the stencil data.*/ ++ DWORD location = context->render_offscreen ? device->fb.depth_stencil->resource->draw_binding ++ : WINED3D_LOCATION_DRAWABLE; ++ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); ++ ++ if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) ++ { ++ RECT current_rect, draw_rect, r; ++ ++ if (!context->render_offscreen && ds != device->onscreen_depth_stencil) ++ device_switch_onscreen_ds(device, context, ds); ++ ++ if (ds->locations & location) ++#endif /* STAGING_CSMT */ + SetRect(¤t_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy); + else + SetRectEmpty(¤t_rect); +@@ -671,6 +733,7 @@ + wined3d_surface_prepare(ds, context, location); + } + ++#if defined(STAGING_CSMT) + if (!context_apply_draw_state(context, device, state)) + { + context_release(context); +@@ -681,6 +744,18 @@ + if (state->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE]) + { + struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil); ++#else /* STAGING_CSMT */ ++ if (!context_apply_draw_state(context, device)) ++ { ++ context_release(context); ++ WARN("Unable to apply draw state, skipping draw.\n"); ++ return; ++ } ++ ++ if (device->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE]) ++ { ++ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); ++#endif /* STAGING_CSMT */ + DWORD location = context->render_offscreen ? ds->container->resource.draw_binding : WINED3D_LOCATION_DRAWABLE; + + surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); +@@ -763,6 +838,7 @@ + else + WARN_(d3d_perf)("Using immediate mode with vertex shaders for half float emulation.\n"); + ++#if defined(STAGING_CSMT) + draw_strided_slow_vs(context, state, stream_info, index_count, + state->gl_primitive_type, idx_data, idx_size, start_idx); + } +@@ -785,6 +861,30 @@ + else + { + draw_strided_fast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data, ++#else /* STAGING_CSMT */ ++ drawStridedSlowVs(context, state, stream_info, index_count, ++ state->gl_primitive_type, idx_data, idx_size, start_idx); ++ } ++ else ++ { ++ if (context->d3d_info->ffp_generic_attributes) ++ drawStridedSlowVs(context, state, stream_info, index_count, ++ state->gl_primitive_type, idx_data, idx_size, start_idx); ++ else ++ drawStridedSlow(device, context, stream_info, index_count, ++ state->gl_primitive_type, idx_data, idx_size, start_idx); ++ } ++ } ++ else if (!gl_info->supported[ARB_INSTANCED_ARRAYS] && instance_count) ++ { ++ /* Instancing emulation by mixing immediate mode and arrays. */ ++ drawStridedInstanced(context, state, stream_info, index_count, state->gl_primitive_type, ++ idx_data, idx_size, start_idx, state->base_vertex_index, instance_count); ++ } ++ else ++ { ++ drawStridedFast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data, ++#endif /* STAGING_CSMT */ + start_idx, state->base_vertex_index, start_instance, instance_count); + } + diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -4677,1796 +4018,970 @@ diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c } shader_addline(buffer, "vec4 vpos;\n"); } -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -22,11 +22,18 @@ - - WINE_DEFAULT_DEBUG_CHANNEL(d3d); - -+#if defined(STAGING_CSMT) - enum wined3d_cs_op - { - WINED3D_CS_OP_NOP, - WINED3D_CS_OP_SKIP, - WINED3D_CS_OP_FENCE, -+#else /* STAGING_CSMT */ -+#define WINED3D_INITIAL_CS_SIZE 4096 -+ -+enum wined3d_cs_op -+{ -+#endif /* STAGING_CSMT */ - WINED3D_CS_OP_PRESENT, - WINED3D_CS_OP_CLEAR, - WINED3D_CS_OP_DRAW, -@@ -53,6 +60,7 @@ - WINED3D_CS_OP_SET_COLOR_KEY, - WINED3D_CS_OP_SET_MATERIAL, - WINED3D_CS_OP_RESET_STATE, -+#if defined(STAGING_CSMT) - WINED3D_CS_OP_SET_VS_CONSTS_F, - WINED3D_CS_OP_SET_VS_CONSTS_B, - WINED3D_CS_OP_SET_VS_CONSTS_I, -@@ -133,6 +141,30 @@ - float depth; - DWORD stencil; - RECT rects[1]; -+#else /* STAGING_CSMT */ -+}; -+ -+struct wined3d_cs_present -+{ -+ enum wined3d_cs_op opcode; -+ HWND dst_window_override; -+ struct wined3d_swapchain *swapchain; -+ const RECT *src_rect; -+ const RECT *dst_rect; -+ const RGNDATA *dirty_region; -+ DWORD flags; -+}; -+ -+struct wined3d_cs_clear -+{ -+ enum wined3d_cs_op opcode; -+ DWORD rect_count; -+ const RECT *rects; -+ DWORD flags; -+ const struct wined3d_color *color; -+ float depth; -+ DWORD stencil; -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_cs_draw -@@ -155,6 +187,7 @@ - struct wined3d_cs_set_viewport - { - enum wined3d_cs_op opcode; -+#if defined(STAGING_CSMT) - struct wined3d_viewport viewport; - }; - -@@ -162,6 +195,15 @@ - { - enum wined3d_cs_op opcode; - RECT rect; -+#else /* STAGING_CSMT */ -+ const struct wined3d_viewport *viewport; -+}; -+ -+struct wined3d_cs_set_scissor_rect -+{ -+ enum wined3d_cs_op opcode; -+ const RECT *rect; -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_cs_set_rendertarget_view -@@ -289,6 +331,7 @@ - { - enum wined3d_cs_op opcode; - enum wined3d_transform_state state; -+#if defined(STAGING_CSMT) - struct wined3d_matrix matrix; - }; - -@@ -303,6 +346,22 @@ - { - enum wined3d_cs_op opcode; - struct wined3d_material material; -+#else /* STAGING_CSMT */ -+ const struct wined3d_matrix *matrix; -+}; -+ -+struct wined3d_cs_set_clip_plane -+{ -+ enum wined3d_cs_op opcode; -+ UINT plane_idx; -+ const struct wined3d_vec4 *plane; -+}; -+ -+struct wined3d_cs_set_material -+{ -+ enum wined3d_cs_op opcode; -+ const struct wined3d_material *material; -+#endif /* STAGING_CSMT */ - }; - - struct wined3d_cs_reset_state -@@ -310,6 +369,7 @@ - enum wined3d_cs_op opcode; - }; - -+#if defined(STAGING_CSMT) - struct wined3d_cs_set_consts_f - { - enum wined3d_cs_op opcode; -@@ -2880,197 +2940,971 @@ - /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, - /* WINED3D_CS_OP_SKIP */ wined3d_cs_exec_skip, - /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, -- /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, -- /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, -- /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, -- /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, -- /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, -- /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, -- /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, -- /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, -- /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, -- /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, -- /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, -- /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, -- /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, -- /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, -- /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, -- /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, -- /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, -- /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, -- /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, -- /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, -- /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, -- /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, -- /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, -- /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, -- /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, -- /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, -- /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, -- /* WINED3D_CS_OP_SET_VS_CONSTS_B */ wined3d_cs_exec_set_vs_consts_b, -- /* WINED3D_CS_OP_SET_VS_CONSTS_I */ wined3d_cs_exec_set_vs_consts_i, -- /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, -- /* WINED3D_CS_OP_SET_PS_CONSTS_B */ wined3d_cs_exec_set_ps_consts_b, -- /* WINED3D_CS_OP_SET_PS_CONSTS_I */ wined3d_cs_exec_set_ps_consts_i, -- /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, -- /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX */ wined3d_cs_exec_set_base_vertex_index, -- /* WINED3D_CS_OP_SET_PRIMITIVE_TYPE */ wined3d_cs_exec_set_primitive_type, -- /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light, -- /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable, -- /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, -- /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, -- /* WINED3D_CS_OP_RESOURCE_CHANGED */ wined3d_cs_exec_resource_changed, -- /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, -- /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, -- /* WINED3D_CS_OP_BUFFER_SWAP_MEM */ wined3d_cs_exec_buffer_swap_mem, -- /* WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE */ wined3d_cs_exec_buffer_invalidate_bo_range, -- /* WINED3D_CS_OP_BUFFER_PRELOAD */ wined3d_cs_exec_buffer_preload, -- /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, -- /* WINED3D_CS_OP_QUERY_DESTROY */ wined3d_cs_exec_query_destroy, -- /* WINED3D_CS_OP_UPDATE_SURFACE */ wined3d_cs_exec_update_surface, -- /* WINED3D_CS_OP_TEXTURE_PRELOAD */ wined3d_cs_exec_texture_preload, -- /* WINED3D_CS_OP_SURFACE_PRELOAD */ wined3d_cs_exec_surface_preload, -- /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, -- /* WINED3D_CS_OP_EVICT_RESOURCE */ wined3d_cs_exec_evict_resource, -- /* WINED3D_CS_OP_VIEW_DESTROY */ wined3d_cs_exec_view_destroy, -- /* WINED3D_CS_OP_VDECL_DESTROY */ wined3d_cs_exec_vertex_declaration_destroy, -- /* WINED3D_CS_OP_SHADER_CLEANUP */ wined3d_cs_exec_shader_cleanup, -- /* WINED3D_CS_OP_CREATE_VBO */ wined3d_cs_exec_create_vbo, -- /* WINED3D_CS_OP_RESOURCE_CLEANUP */ wined3d_cs_exec_resource_cleanup, -- /* WINED3D_CS_OP_BUFFER_CLEANUP */ wined3d_cs_exec_buffer_cleanup, -- /* WINED3D_CS_OP_VOLUME_CLEANUP */ wined3d_cs_exec_volume_cleanup, -- /* WINED3D_CS_OP_SURFACE_CLEANUP */ wined3d_cs_exec_surface_cleanup, -- /* WINED3D_CS_OP_TEXTURE_CLEANUP */ wined3d_cs_exec_texture_cleanup, -- /* WINED3D_CS_OP_CREATE_DUMMY_TEXTURES */ wined3d_cs_exec_create_dummy_textures, -- /* WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT */ wined3d_cs_exec_create_swapchain_context, -- /* WINED3D_CS_OP_DELETE_GL_CONTEXTS */ wined3d_cs_exec_delete_gl_contexts, -- /* WINED3D_CS_OP_GETDC */ wined3d_cs_exec_getdc, -- /* WINED3D_CS_OP_RELEASEDC */ wined3d_cs_exec_releasedc, -- /* WINED3D_CS_OP_SAMPLER_DESTROY */ wined3d_cs_exec_sampler_destroy, -- /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, --}; -- --static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) -+#else /* STAGING_CSMT */ -+static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) - { -- struct wined3d_cs_queue *queue = prio ? &cs->prio_queue : &cs->queue; -- size_t queue_size = sizeof(queue->data) / sizeof(*queue->data); -+ const struct wined3d_cs_present *op = data; -+ struct wined3d_swapchain *swapchain; - -- if (queue_size - size < queue->head) -- { -- struct wined3d_cs_skip *skip; -- size_t nop_size = queue_size - queue->head; -+ swapchain = op->swapchain; -+ wined3d_swapchain_set_window(swapchain, op->dst_window_override); - -- skip = _wined3d_cs_mt_require_space(cs, nop_size, prio); -- if (nop_size < sizeof(*skip)) -- { -- skip->opcode = WINED3D_CS_OP_NOP; -- } -- else -- { -- skip->opcode = WINED3D_CS_OP_SKIP; -- skip->size = nop_size; -- } -+ swapchain->swapchain_ops->swapchain_present(swapchain, -+ op->src_rect, op->dst_rect, op->dirty_region, op->flags); -+} - -- if (prio) -- cs->ops->submit_prio(cs, nop_size); -- else -- cs->ops->submit(cs, nop_size); -+void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, -+ const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, -+ const RGNDATA *dirty_region, DWORD flags) -+{ -+ struct wined3d_cs_present *op; - -- assert(!queue->head); -- } -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_PRESENT; -+ op->dst_window_override = dst_window_override; -+ op->swapchain = swapchain; -+ op->src_rect = src_rect; -+ op->dst_rect = dst_rect; -+ op->dirty_region = dirty_region; -+ op->flags = flags; - -- while(1) -- { -- LONG head = queue->head; -- LONG tail = *((volatile LONG *)&queue->tail); -- LONG new_pos; -- /* Empty */ -- if (head == tail) -- break; -- /* Head ahead of tail, take care of wrap-around */ -- new_pos = (head + size) & (WINED3D_CS_QUEUE_SIZE - 1); -- if (head > tail && (new_pos || tail)) -- break; -- /* Tail ahead of head, but still enough space */ -- if (new_pos < tail && new_pos) -- break; -+ cs->ops->submit(cs); -+} - -- TRACE("Waiting for free space. Head %u, tail %u, want %u\n", head, tail, -- (unsigned int) size); -- } -+static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_clear *op = data; -+ struct wined3d_device *device; -+ RECT draw_rect; - -- return &queue->data[queue->head]; -+ device = cs->device; -+ wined3d_get_draw_rect(&device->state, &draw_rect); -+ device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, -+ &device->fb, op->rect_count, op->rects, &draw_rect, op->flags, -+ op->color, op->depth, op->stencil); - } - --static inline void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) -+void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, -+ DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) - { -- return _wined3d_cs_mt_require_space(cs, size, FALSE); -+ struct wined3d_cs_clear *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_CLEAR; -+ op->rect_count = rect_count; -+ op->rects = rects; -+ op->flags = flags; -+ op->color = color; -+ op->depth = depth; -+ op->stencil = stencil; -+ -+ cs->ops->submit(cs); - } - --static inline void *wined3d_cs_mt_require_space_prio(struct wined3d_cs *cs, size_t size) -+static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) - { -- return _wined3d_cs_mt_require_space(cs, size, TRUE); -+ const struct wined3d_cs_draw *op = data; -+ -+ draw_primitive(cs->device, op->start_idx, op->index_count, -+ op->start_instance, op->instance_count, op->indexed); - } - --/* FIXME: wined3d_device_uninit_3d() should either flush and wait, or be an -- * OP itself. */ --static void wined3d_cs_emit_stop(struct wined3d_cs *cs) -+void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count, -+ UINT start_instance, UINT instance_count, BOOL indexed) - { -- struct wined3d_cs_stop *op; -+ struct wined3d_cs_draw *op; - -- op = wined3d_cs_mt_require_space(cs, sizeof(*op)); -- op->opcode = WINED3D_CS_OP_STOP; -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_DRAW; -+ op->start_idx = start_idx; -+ op->index_count = index_count; -+ op->start_instance = start_instance; -+ op->instance_count = instance_count; -+ op->indexed = indexed; - -- wined3d_cs_mt_submit(cs, sizeof(*op)); -+ cs->ops->submit(cs); - } - --static void wined3d_cs_mt_finish(struct wined3d_cs *cs) -+static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data) - { -- BOOL fence; -- -- if (cs->thread_id == GetCurrentThreadId()) -- { -- static BOOL once; -- if (!once) -- { -- FIXME("flush_and_wait called from cs thread\n"); -- once = TRUE; -- } -- return; -- } -- -- wined3d_cs_emit_fence(cs, &fence); -+ const struct wined3d_cs_set_predication *op = data; - -- /* A busy wait should be fine, we're not supposed to have to wait very -- * long. */ -- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); -+ cs->state.predicate = op->predicate; -+ cs->state.predicate_value = op->value; - } - --static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs) -+void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value) - { -- BOOL fence; -+ struct wined3d_cs_set_predication *op; - -- if (cs->thread_id == GetCurrentThreadId()) -- { -- static BOOL once; -- if (!once) -- { -- FIXME("flush_and_wait called from cs thread\n"); -- once = TRUE; -- } -- return; -- } -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_PREDICATION; -+ op->predicate = predicate; -+ op->value = value; - -- wined3d_cs_emit_fence_prio(cs, &fence); -+ cs->ops->submit(cs); -+} - -- /* A busy wait should be fine, we're not supposed to have to wait very -- * long. */ -- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); -+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 const struct wined3d_cs_ops wined3d_cs_mt_ops = -+void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) - { -- wined3d_cs_mt_require_space, -+ struct wined3d_cs_set_viewport *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_VIEWPORT; -+ op->viewport = viewport; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) -+{ -+ struct wined3d_cs_set_scissor_rect *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; -+ op->rect = rect; -+ -+ cs->ops->submit(cs); -+} -+ -+static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_set_rendertarget_view *op = data; -+ -+ cs->state.fb->render_targets[op->view_idx] = op->view; -+ device_invalidate_state(cs->device, STATE_FRAMEBUFFER); -+} -+ -+void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx, -+ struct wined3d_rendertarget_view *view) -+{ -+ struct wined3d_cs_set_rendertarget_view *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW; -+ op->view_idx = view_idx; -+ op->view = view; -+ -+ cs->ops->submit(cs); -+} -+ -+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_texture_decref(device->onscreen_depth_stencil->container); -+ 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); -+} -+ -+void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) -+{ -+ struct wined3d_cs_set_depth_stencil_view *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW; -+ op->view = view; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) -+{ -+ struct wined3d_cs_set_vertex_declaration *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION; -+ op->declaration = declaration; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, -+ struct wined3d_buffer *buffer, UINT offset, UINT stride) -+{ -+ struct wined3d_cs_set_stream_source *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE; -+ op->stream_idx = stream_idx; -+ op->buffer = buffer; -+ op->offset = offset; -+ op->stride = stride; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags) -+{ -+ struct wined3d_cs_set_stream_source_freq *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ; -+ op->stream_idx = stream_idx; -+ op->frequency = frequency; -+ op->flags = flags; -+ -+ cs->ops->submit(cs); -+} -+ -+static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_set_stream_output *op = data; -+ struct wined3d_stream_output *stream; -+ struct wined3d_buffer *prev; -+ -+ stream = &cs->state.stream_output[op->stream_idx]; -+ prev = stream->buffer; -+ stream->buffer = op->buffer; -+ stream->offset = op->offset; -+ -+ if (op->buffer) -+ InterlockedIncrement(&op->buffer->resource.bind_count); -+ if (prev) -+ InterlockedDecrement(&prev->resource.bind_count); -+} -+ -+void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, -+ struct wined3d_buffer *buffer, UINT offset) -+{ -+ struct wined3d_cs_set_stream_output *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT; -+ op->stream_idx = stream_idx; -+ op->buffer = buffer; -+ op->offset = offset; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, -+ enum wined3d_format_id format_id) -+{ -+ struct wined3d_cs_set_index_buffer *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER; -+ op->buffer = buffer; -+ op->format_id = format_id; -+ -+ cs->ops->submit(cs); -+} -+ -+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)); -+} -+ -+void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, -+ UINT cb_idx, struct wined3d_buffer *buffer) -+{ -+ struct wined3d_cs_set_constant_buffer *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER; -+ op->type = type; -+ op->cb_idx = cb_idx; -+ op->buffer = buffer; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture) -+{ -+ struct wined3d_cs_set_texture *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_TEXTURE; -+ op->stage = stage; -+ op->texture = texture; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type, -+ UINT view_idx, struct wined3d_shader_resource_view *view) -+{ -+ struct wined3d_cs_set_shader_resource_view *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW; -+ op->type = type; -+ op->view_idx = view_idx; -+ op->view = view; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type, -+ UINT sampler_idx, struct wined3d_sampler *sampler) -+{ -+ struct wined3d_cs_set_sampler *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_SAMPLER; -+ op->type = type; -+ op->sampler_idx = sampler_idx; -+ op->sampler = sampler; -+ -+ cs->ops->submit(cs); -+} -+ -+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)); -+ device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); -+} -+ -+void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader) -+{ -+ struct wined3d_cs_set_shader *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_SHADER; -+ op->type = type; -+ op->shader = shader; -+ -+ cs->ops->submit(cs); -+} -+ -+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)); -+} -+ -+void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value) -+{ -+ struct wined3d_cs_set_render_state *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_RENDER_STATE; -+ op->state = state; -+ op->value = value; -+ -+ cs->ops->submit(cs); -+} -+ -+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)); -+} -+ -+void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, -+ enum wined3d_texture_stage_state state, DWORD value) -+{ -+ struct wined3d_cs_set_texture_state *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE; -+ op->stage = stage; -+ op->state = state; -+ op->value = value; -+ -+ cs->ops->submit(cs); -+} -+ -+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)); -+} -+ -+void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, -+ enum wined3d_sampler_state state, DWORD value) -+{ -+ struct wined3d_cs_set_sampler_state *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE; -+ op->sampler_idx = sampler_idx; -+ op->state = state; -+ op->value = value; -+ -+ cs->ops->submit(cs); -+} -+ -+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->d3d_info.limits.ffp_vertex_blend_matrices)) -+ device_invalidate_state(cs->device, STATE_TRANSFORM(op->state)); -+} -+ -+void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state, -+ const struct wined3d_matrix *matrix) -+{ -+ struct wined3d_cs_set_transform *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_TRANSFORM; -+ op->state = state; -+ op->matrix = matrix; -+ -+ cs->ops->submit(cs); -+} -+ -+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)); -+} -+ -+void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) -+{ -+ struct wined3d_cs_set_clip_plane *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE; -+ op->plane_idx = plane_idx; -+ op->plane = plane; -+ -+ cs->ops->submit(cs); -+} -+ -+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; -+ } -+ } -+} -+ -+void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ WORD flags, const struct wined3d_color_key *color_key) -+{ -+ struct wined3d_cs_set_color_key *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_COLOR_KEY; -+ op->texture = texture; -+ op->flags = flags; -+ if (color_key) -+ { -+ op->color_key = *color_key; -+ op->set = 1; -+ } -+ else -+ op->set = 0; -+ -+ cs->ops->submit(cs); -+} -+ -+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); -+} -+ -+void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material) -+{ -+ struct wined3d_cs_set_material *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_SET_MATERIAL; -+ op->material = material; -+ -+ cs->ops->submit(cs); -+} -+ -+static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) -+{ -+ struct wined3d_adapter *adapter = cs->device->adapter; -+ HRESULT hr; -+ -+ state_cleanup(&cs->state); -+ memset(&cs->state, 0, sizeof(cs->state)); -+ if (FAILED(hr = state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info, -+ WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) -+ ERR("Failed to initialize CS state, hr %#x.\n", hr); -+} -+ -+void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) -+{ -+ struct wined3d_cs_reset_state *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_RESET_STATE; -+ -+ cs->ops->submit(cs); -+} -+ -+static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = -+{ -+#endif /* STAGING_CSMT */ -+ /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, -+ /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, -+ /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, -+ /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, -+ /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, -+ /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, -+ /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, -+ /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, -+ /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, -+ /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, -+ /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, -+ /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, -+ /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, -+ /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, -+ /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, -+ /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, -+ /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, -+ /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, -+ /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, -+ /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, -+ /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, -+ /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, -+ /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, -+ /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, -+ /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, -+ /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, -+#if defined(STAGING_CSMT) -+ /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, -+ /* WINED3D_CS_OP_SET_VS_CONSTS_B */ wined3d_cs_exec_set_vs_consts_b, -+ /* WINED3D_CS_OP_SET_VS_CONSTS_I */ wined3d_cs_exec_set_vs_consts_i, -+ /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, -+ /* WINED3D_CS_OP_SET_PS_CONSTS_B */ wined3d_cs_exec_set_ps_consts_b, -+ /* WINED3D_CS_OP_SET_PS_CONSTS_I */ wined3d_cs_exec_set_ps_consts_i, -+ /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, -+ /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX */ wined3d_cs_exec_set_base_vertex_index, -+ /* WINED3D_CS_OP_SET_PRIMITIVE_TYPE */ wined3d_cs_exec_set_primitive_type, -+ /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light, -+ /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable, -+ /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, -+ /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, -+ /* WINED3D_CS_OP_RESOURCE_CHANGED */ wined3d_cs_exec_resource_changed, -+ /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, -+ /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, -+ /* WINED3D_CS_OP_BUFFER_SWAP_MEM */ wined3d_cs_exec_buffer_swap_mem, -+ /* WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE */ wined3d_cs_exec_buffer_invalidate_bo_range, -+ /* WINED3D_CS_OP_BUFFER_PRELOAD */ wined3d_cs_exec_buffer_preload, -+ /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, -+ /* WINED3D_CS_OP_QUERY_DESTROY */ wined3d_cs_exec_query_destroy, -+ /* WINED3D_CS_OP_UPDATE_SURFACE */ wined3d_cs_exec_update_surface, -+ /* WINED3D_CS_OP_TEXTURE_PRELOAD */ wined3d_cs_exec_texture_preload, -+ /* WINED3D_CS_OP_SURFACE_PRELOAD */ wined3d_cs_exec_surface_preload, -+ /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, -+ /* WINED3D_CS_OP_EVICT_RESOURCE */ wined3d_cs_exec_evict_resource, -+ /* WINED3D_CS_OP_VIEW_DESTROY */ wined3d_cs_exec_view_destroy, -+ /* WINED3D_CS_OP_VDECL_DESTROY */ wined3d_cs_exec_vertex_declaration_destroy, -+ /* WINED3D_CS_OP_SHADER_CLEANUP */ wined3d_cs_exec_shader_cleanup, -+ /* WINED3D_CS_OP_CREATE_VBO */ wined3d_cs_exec_create_vbo, -+ /* WINED3D_CS_OP_RESOURCE_CLEANUP */ wined3d_cs_exec_resource_cleanup, -+ /* WINED3D_CS_OP_BUFFER_CLEANUP */ wined3d_cs_exec_buffer_cleanup, -+ /* WINED3D_CS_OP_VOLUME_CLEANUP */ wined3d_cs_exec_volume_cleanup, -+ /* WINED3D_CS_OP_SURFACE_CLEANUP */ wined3d_cs_exec_surface_cleanup, -+ /* WINED3D_CS_OP_TEXTURE_CLEANUP */ wined3d_cs_exec_texture_cleanup, -+ /* WINED3D_CS_OP_CREATE_DUMMY_TEXTURES */ wined3d_cs_exec_create_dummy_textures, -+ /* WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT */ wined3d_cs_exec_create_swapchain_context, -+ /* WINED3D_CS_OP_DELETE_GL_CONTEXTS */ wined3d_cs_exec_delete_gl_contexts, -+ /* WINED3D_CS_OP_GETDC */ wined3d_cs_exec_getdc, -+ /* WINED3D_CS_OP_RELEASEDC */ wined3d_cs_exec_releasedc, -+ /* WINED3D_CS_OP_SAMPLER_DESTROY */ wined3d_cs_exec_sampler_destroy, -+ /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, -+}; -+ -+static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) -+{ -+ struct wined3d_cs_queue *queue = prio ? &cs->prio_queue : &cs->queue; -+ size_t queue_size = sizeof(queue->data) / sizeof(*queue->data); -+ -+ if (queue_size - size < queue->head) -+ { -+ struct wined3d_cs_skip *skip; -+ size_t nop_size = queue_size - queue->head; -+ -+ skip = _wined3d_cs_mt_require_space(cs, nop_size, prio); -+ if (nop_size < sizeof(*skip)) -+ { -+ skip->opcode = WINED3D_CS_OP_NOP; -+ } -+ else -+ { -+ skip->opcode = WINED3D_CS_OP_SKIP; -+ skip->size = nop_size; -+ } -+ -+ if (prio) -+ cs->ops->submit_prio(cs, nop_size); -+ else -+ cs->ops->submit(cs, nop_size); -+ -+ assert(!queue->head); -+ } -+ -+ while(1) -+ { -+ LONG head = queue->head; -+ LONG tail = *((volatile LONG *)&queue->tail); -+ LONG new_pos; -+ /* Empty */ -+ if (head == tail) -+ break; -+ /* Head ahead of tail, take care of wrap-around */ -+ new_pos = (head + size) & (WINED3D_CS_QUEUE_SIZE - 1); -+ if (head > tail && (new_pos || tail)) -+ break; -+ /* Tail ahead of head, but still enough space */ -+ if (new_pos < tail && new_pos) -+ break; -+ -+ TRACE("Waiting for free space. Head %u, tail %u, want %u\n", head, tail, -+ (unsigned int) size); -+ } -+ -+ return &queue->data[queue->head]; -+} -+ -+static inline void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) -+{ -+ return _wined3d_cs_mt_require_space(cs, size, FALSE); -+} -+ -+static inline void *wined3d_cs_mt_require_space_prio(struct wined3d_cs *cs, size_t size) -+{ -+ return _wined3d_cs_mt_require_space(cs, size, TRUE); -+} -+ -+/* FIXME: wined3d_device_uninit_3d() should either flush and wait, or be an -+ * OP itself. */ -+static void wined3d_cs_emit_stop(struct wined3d_cs *cs) -+{ -+ struct wined3d_cs_stop *op; -+ -+ op = wined3d_cs_mt_require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_STOP; -+ -+ wined3d_cs_mt_submit(cs, sizeof(*op)); -+} -+ -+static void wined3d_cs_mt_finish(struct wined3d_cs *cs) -+{ -+ BOOL fence; -+ -+ if (cs->thread_id == GetCurrentThreadId()) -+ { -+ static BOOL once; -+ if (!once) -+ { -+ FIXME("flush_and_wait called from cs thread\n"); -+ once = TRUE; -+ } -+ return; -+ } -+ -+ wined3d_cs_emit_fence(cs, &fence); -+ -+ /* A busy wait should be fine, we're not supposed to have to wait very -+ * long. */ -+ while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); -+} -+ -+static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs) -+{ -+ BOOL fence; -+ -+ if (cs->thread_id == GetCurrentThreadId()) -+ { -+ static BOOL once; -+ if (!once) -+ { -+ FIXME("flush_and_wait called from cs thread\n"); -+ once = TRUE; -+ } -+ return; -+ } -+ -+ wined3d_cs_emit_fence_prio(cs, &fence); -+ -+ /* A busy wait should be fine, we're not supposed to have to wait very -+ * long. */ -+ while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); -+} -+ -+static const struct wined3d_cs_ops wined3d_cs_mt_ops = -+{ -+ wined3d_cs_mt_require_space, - wined3d_cs_mt_require_space_prio, - wined3d_cs_mt_submit, - wined3d_cs_mt_submit_prio, -@@ -3293,5 +4127,80 @@ - ERR("Closing event failed.\n"); - } - -+#else /* STAGING_CSMT */ -+}; -+ -+static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) -+{ -+ if (size > cs->data_size) -+ { -+ void *new_data; -+ -+ size = max( size, cs->data_size * 2 ); -+ if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size))) -+ return NULL; -+ -+ cs->data_size = size; -+ cs->data = new_data; -+ } -+ -+ return cs->data; -+} -+ -+static void wined3d_cs_st_submit(struct wined3d_cs *cs) -+{ -+ enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data; -+ -+ wined3d_cs_op_handlers[opcode](cs, cs->data); -+} -+ -+static const struct wined3d_cs_ops wined3d_cs_st_ops = -+{ -+ wined3d_cs_st_require_space, -+ wined3d_cs_st_submit, -+}; -+ -+struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) -+{ -+ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; -+ struct wined3d_cs *cs; -+ -+ if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs)))) -+ return NULL; -+ -+ if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, -+ sizeof(*cs->fb.render_targets) * gl_info->limits.buffers))) -+ { -+ HeapFree(GetProcessHeap(), 0, cs); -+ return NULL; -+ } -+ -+ if (FAILED(state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info, -+ WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) -+ { -+ HeapFree(GetProcessHeap(), 0, cs->fb.render_targets); -+ HeapFree(GetProcessHeap(), 0, cs); -+ return NULL; -+ } -+ -+ cs->ops = &wined3d_cs_st_ops; -+ cs->device = device; -+ -+ cs->data_size = WINED3D_INITIAL_CS_SIZE; -+ if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size))) -+ { -+ HeapFree(GetProcessHeap(), 0, cs); -+ return NULL; -+ } -+ -+ return cs; -+} -+ -+void wined3d_cs_destroy(struct wined3d_cs *cs) -+{ -+ state_cleanup(&cs->state); -+ HeapFree(GetProcessHeap(), 0, cs->fb.render_targets); -+ HeapFree(GetProcessHeap(), 0, cs->data); -+#endif /* STAGING_CSMT */ - HeapFree(GetProcessHeap(), 0, cs); - } -diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c ---- a/dlls/wined3d/texture.c -+++ b/dlls/wined3d/texture.c -@@ -68,8 +68,10 @@ - { - ERR("Failed to allocate sub-resource array.\n"); - resource_cleanup(&texture->resource); -+#if defined(STAGING_CSMT) - if (wined3d_settings.cs_multithreaded) - texture->resource.device->cs->ops->finish(texture->resource.device->cs); -+#endif /* STAGING_CSMT */ - return E_OUTOFMEMORY; - } - -@@ -114,6 +116,7 @@ - resource_unload(&texture->resource); +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -233,6 +233,7 @@ + return refcount; } +#if defined(STAGING_CSMT) - void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) + void wined3d_query_destroy(struct wined3d_query *query) { - wined3d_texture_unload_gl_texture(texture); -@@ -126,6 +129,12 @@ - UINT sub_count = texture->level_count * texture->layer_count; - UINT i; - struct wined3d_device *device = texture->resource.device; -+#else /* STAGING_CSMT */ -+static void wined3d_texture_cleanup(struct wined3d_texture *texture) -+{ -+ UINT sub_count = texture->level_count * texture->layer_count; -+ UINT i; -+#endif /* STAGING_CSMT */ - - TRACE("texture %p.\n", texture); - -@@ -137,8 +146,14 @@ - texture->texture_ops->texture_sub_resource_cleanup(sub_resource); - } - -+#if defined(STAGING_CSMT) - resource_cleanup(&texture->resource); - wined3d_cs_emit_texture_cleanup(device->cs, texture); -+#else /* STAGING_CSMT */ -+ wined3d_texture_unload_gl_texture(texture); -+ HeapFree(GetProcessHeap(), 0, texture->sub_resources); -+ resource_cleanup(&texture->resource); -+#endif /* STAGING_CSMT */ + /* Queries are specific to the GL context that created them. Not +@@ -263,6 +264,7 @@ + HeapFree(GetProcessHeap(), 0, query); } - void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain) -@@ -422,10 +437,16 @@ ++#endif /* STAGING_CSMT */ + ULONG CDECL wined3d_query_decref(struct wined3d_query *query) + { + ULONG refcount = InterlockedDecrement(&query->ref); +@@ -270,7 +272,38 @@ + TRACE("%p decreasing refcount to %u.\n", query, refcount); if (!refcount) ++#if defined(STAGING_CSMT) + wined3d_cs_emit_query_destroy(query->device->cs, query); ++#else /* STAGING_CSMT */ ++ { ++ /* Queries are specific to the GL context that created them. Not ++ * deleting the query will obviously leak it, but that's still better ++ * than potentially deleting a different query with the same id in this ++ * context, and (still) leaking the actual query. */ ++ if (query->type == WINED3D_QUERY_TYPE_EVENT) ++ { ++ struct wined3d_event_query *event_query = query->extendedData; ++ if (event_query) wined3d_event_query_destroy(event_query); ++ } ++ else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION) ++ { ++ struct wined3d_occlusion_query *oq = query->extendedData; ++ ++ if (oq->context) context_free_occlusion_query(oq); ++ HeapFree(GetProcessHeap(), 0, query->extendedData); ++ } ++ else if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP) ++ { ++ struct wined3d_timestamp_query *tq = query->extendedData; ++ ++ if (tq->context) ++ context_free_timestamp_query(tq); ++ HeapFree(GetProcessHeap(), 0, query->extendedData); ++ } ++ ++ HeapFree(GetProcessHeap(), 0, query); ++ } ++#endif /* STAGING_CSMT */ + + return refcount; + } +@@ -295,6 +328,7 @@ + { + TRACE("query %p, flags %#x.\n", query, flags); + ++#if defined(STAGING_CSMT) + if (flags & WINED3DISSUE_END) + query->counter_main++; + +@@ -306,6 +340,9 @@ + query->state = QUERY_SIGNALLED; + + return WINED3D_OK; ++#else /* STAGING_CSMT */ ++ return query->query_ops->query_issue(query, flags); ++#endif /* STAGING_CSMT */ + } + + static void fill_query_data(void *out, unsigned int out_size, const void *result, unsigned int result_size) +@@ -316,10 +353,25 @@ + static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, + void *data, DWORD size, DWORD flags) + { ++#if defined(STAGING_CSMT) + struct wined3d_device *device = query->device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_occlusion_query *oq = query->extendedData; + GLuint samples; ++#else /* STAGING_CSMT */ ++ struct wined3d_occlusion_query *oq = query->extendedData; ++ struct wined3d_device *device = query->device; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_context *context; ++ GLuint available; ++ GLuint samples; ++ HRESULT res; ++ ++ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ ++ if (!oq->context) ++ query->state = QUERY_CREATED; ++#endif /* STAGING_CSMT */ + + if (query->state == QUERY_CREATED) + { +@@ -330,8 +382,10 @@ + return S_OK; + } + ++#if defined(STAGING_CSMT) + TRACE("(%p) : type D3DQUERY_OCCLUSION, data %p, size %#x, flags %#x.\n", query, data, size, flags); + ++#endif /* STAGING_CSMT */ + if (query->state == QUERY_BUILDING) + { + /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ +@@ -347,6 +401,7 @@ + return S_OK; + } + ++#if defined(STAGING_CSMT) + if (!wined3d_settings.cs_multithreaded) + { + if (!query->query_ops->query_poll(query)) +@@ -378,6 +433,14 @@ + FIXME("%p Wrong thread, returning 1.\n", query); + oq->samples = 1; + return TRUE; ++#else /* STAGING_CSMT */ ++ if (oq->context->tid != GetCurrentThreadId()) ++ { ++ FIXME("%p Wrong thread, returning 1.\n", query); ++ samples = 1; ++ fill_query_data(data, size, &samples, sizeof(samples)); ++ return S_OK; ++#endif /* STAGING_CSMT */ + } + + context = context_acquire(query->device, oq->context->current_rt); +@@ -388,6 +451,7 @@ + + if (available) { +#if defined(STAGING_CSMT) - void *parent = texture->resource.parent; - const struct wined3d_parent_ops *parent_ops = texture->resource.parent_ops; - wined3d_texture_cleanup(texture); - parent_ops->wined3d_object_destroyed(parent); + GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); + checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); + TRACE("Returning %d samples.\n", samples); +@@ -459,6 +523,69 @@ + + if (data) + fill_query_data(data, dwSize, &ret, sizeof(ret)); +#else /* STAGING_CSMT */ -+ wined3d_texture_cleanup(texture); -+ texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent); -+ HeapFree(GetProcessHeap(), 0, texture); ++ if (size) ++ { ++ GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); ++ checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); ++ TRACE("Returning %d samples.\n", samples); ++ fill_query_data(data, size, &samples, sizeof(samples)); ++ } ++ res = S_OK; ++ } ++ else ++ { ++ res = S_FALSE; ++ } ++ ++ context_release(context); ++ ++ return res; ++} ++ ++static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query, ++ void *data, DWORD size, DWORD flags) ++{ ++ struct wined3d_event_query *event_query = query->extendedData; ++ BOOL signaled; ++ enum wined3d_event_query_result ret; ++ ++ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ ++ if (!data || !size) return S_OK; ++ if (!event_query) ++ { ++ WARN("Event query not supported by GL, reporting GPU idle.\n"); ++ signaled = TRUE; ++ fill_query_data(data, size, &signaled, sizeof(signaled)); ++ return S_OK; ++ } ++ ++ ret = wined3d_event_query_test(event_query, query->device); ++ switch(ret) ++ { ++ case WINED3D_EVENT_QUERY_OK: ++ case WINED3D_EVENT_QUERY_NOT_STARTED: ++ signaled = TRUE; ++ fill_query_data(data, size, &signaled, sizeof(signaled)); ++ break; ++ ++ case WINED3D_EVENT_QUERY_WAITING: ++ signaled = FALSE; ++ fill_query_data(data, size, &signaled, sizeof(signaled)); ++ break; ++ ++ case WINED3D_EVENT_QUERY_WRONG_THREAD: ++ FIXME("(%p) Wrong thread, reporting GPU idle.\n", query); ++ signaled = TRUE; ++ fill_query_data(data, size, &signaled, sizeof(signaled)); ++ break; ++ ++ case WINED3D_EVENT_QUERY_ERROR: ++ ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++#endif /* STAGING_CSMT */ + + return S_OK; + } +@@ -477,7 +604,11 @@ + return query->type; + } + ++#if defined(STAGING_CSMT) + static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) ++#else /* STAGING_CSMT */ ++static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) ++#endif /* STAGING_CSMT */ + { + TRACE("query %p, flags %#x.\n", query, flags); + +@@ -487,6 +618,7 @@ + struct wined3d_event_query *event_query = query->extendedData; + + /* Faked event query support */ ++#if defined(STAGING_CSMT) + if (!event_query) return FALSE; + + wined3d_event_query_issue(event_query, query->device); +@@ -505,6 +637,30 @@ + struct wined3d_device *device = query->device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + BOOL poll = FALSE; ++#else /* STAGING_CSMT */ ++ if (!event_query) return WINED3D_OK; ++ ++ wined3d_event_query_issue(event_query, query->device); ++ } ++ else if (flags & WINED3DISSUE_BEGIN) ++ { ++ /* Started implicitly at device creation */ ++ ERR("Event query issued with START flag - what to do?\n"); ++ } ++ ++ if (flags & WINED3DISSUE_BEGIN) ++ query->state = QUERY_BUILDING; ++ else ++ query->state = QUERY_SIGNALLED; ++ ++ return WINED3D_OK; ++} ++ ++static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) ++{ ++ struct wined3d_device *device = query->device; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++#endif /* STAGING_CSMT */ + + TRACE("query %p, flags %#x.\n", query, flags); + +@@ -516,7 +672,11 @@ + /* This is allowed according to msdn and our tests. Reset the query and restart */ + if (flags & WINED3DISSUE_BEGIN) + { ++#if defined(STAGING_CSMT) + if (oq->started) ++#else /* STAGING_CSMT */ ++ if (query->state == QUERY_BUILDING) ++#endif /* STAGING_CSMT */ + { + if (oq->context->tid != GetCurrentThreadId()) + { +@@ -545,7 +705,9 @@ + checkGLcall("glBeginQuery()"); + + context_release(context); ++#if defined(STAGING_CSMT) + oq->started = TRUE; ++#endif /* STAGING_CSMT */ + } + if (flags & WINED3DISSUE_END) + { +@@ -553,7 +715,11 @@ + * our tests show that it returns OK. But OpenGL doesn't like it, so avoid + * generating an error + */ ++#if defined(STAGING_CSMT) + if (oq->started) ++#else /* STAGING_CSMT */ ++ if (query->state == QUERY_BUILDING) ++#endif /* STAGING_CSMT */ + { + if (oq->context->tid != GetCurrentThreadId()) + { +@@ -567,10 +733,15 @@ + checkGLcall("glEndQuery()"); + + context_release(context); ++#if defined(STAGING_CSMT) + poll = TRUE; + } + } + oq->started = FALSE; ++#else /* STAGING_CSMT */ ++ } ++ } ++#endif /* STAGING_CSMT */ + } + } + else +@@ -578,6 +749,7 @@ + FIXME("%p Occlusion queries not supported.\n", query); + } + ++#if defined(STAGING_CSMT) + return poll; + } + +@@ -636,6 +808,47 @@ + FIXME("%p Wrong thread, returning 1.\n", query); + tq->timestamp = 1; + return TRUE; ++#else /* STAGING_CSMT */ ++ if (flags & WINED3DISSUE_BEGIN) ++ query->state = QUERY_BUILDING; ++ else ++ query->state = QUERY_SIGNALLED; ++ ++ return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ ++} ++ ++static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, ++ void *data, DWORD size, DWORD flags) ++{ ++ struct wined3d_timestamp_query *tq = query->extendedData; ++ struct wined3d_device *device = query->device; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_context *context; ++ GLuint available; ++ GLuint64 timestamp; ++ HRESULT res; ++ ++ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ ++ if (!tq->context) ++ query->state = QUERY_CREATED; ++ ++ if (query->state == QUERY_CREATED) ++ { ++ /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves. */ ++ TRACE("Query wasn't yet started, returning S_OK.\n"); ++ timestamp = 0; ++ fill_query_data(data, size, ×tamp, sizeof(timestamp)); ++ return S_OK; ++ } ++ ++ if (tq->context->tid != GetCurrentThreadId()) ++ { ++ FIXME("%p Wrong thread, returning 1.\n", query); ++ timestamp = 1; ++ fill_query_data(data, size, ×tamp, sizeof(timestamp)); ++ return S_OK; ++#endif /* STAGING_CSMT */ + } + + context = context_acquire(query->device, tq->context->current_rt); +@@ -646,6 +859,7 @@ + + if (available) + { ++#if defined(STAGING_CSMT) + GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); + checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); + TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); +@@ -663,6 +877,28 @@ + } + + static BOOL wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) ++#else /* STAGING_CSMT */ ++ if (size) ++ { ++ GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); ++ checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); ++ TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); ++ fill_query_data(data, size, ×tamp, sizeof(timestamp)); ++ } ++ res = S_OK; ++ } ++ else ++ { ++ res = S_FALSE; ++ } ++ ++ context_release(context); ++ ++ return res; ++} ++ ++static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) ++#endif /* STAGING_CSMT */ + { + struct wined3d_device *device = query->device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; +@@ -695,6 +931,7 @@ + } + + if (flags & WINED3DISSUE_END) ++#if defined(STAGING_CSMT) + return TRUE; + return FALSE; + } +@@ -711,6 +948,26 @@ + { + TRACE("Query is building, returning S_FALSE.\n"); + return S_FALSE; ++#else /* STAGING_CSMT */ ++ query->state = QUERY_SIGNALLED; ++ ++ return WINED3D_OK; ++} ++ ++static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query, ++ void *data, DWORD size, DWORD flags) ++{ ++ TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ ++ if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT) ++ { ++ static const struct wined3d_query_data_timestamp_disjoint disjoint_data = {1000 * 1000 * 1000, FALSE}; ++ ++ if (query->state == QUERY_BUILDING) ++ { ++ TRACE("Query is building, returning S_FALSE.\n"); ++ return S_FALSE; ++#endif /* STAGING_CSMT */ + } + + fill_query_data(data, size, &disjoint_data, sizeof(disjoint_data)); +@@ -724,6 +981,7 @@ + return S_OK; + } + ++#if defined(STAGING_CSMT) + static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *query) + { + return TRUE; +@@ -760,6 +1018,41 @@ + { + wined3d_timestamp_disjoint_query_ops_get_data, + wined3d_timestamp_disjoint_query_ops_poll, ++#else /* STAGING_CSMT */ ++static HRESULT wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) ++{ ++ TRACE("query %p, flags %#x.\n", query, flags); ++ ++ if (flags & WINED3DISSUE_BEGIN) ++ query->state = QUERY_BUILDING; ++ if (flags & WINED3DISSUE_END) ++ query->state = QUERY_SIGNALLED; ++ ++ return WINED3D_OK; ++} ++ ++static const struct wined3d_query_ops event_query_ops = ++{ ++ wined3d_event_query_ops_get_data, ++ wined3d_event_query_ops_issue, ++}; ++ ++static const struct wined3d_query_ops occlusion_query_ops = ++{ ++ wined3d_occlusion_query_ops_get_data, ++ wined3d_occlusion_query_ops_issue, ++}; ++ ++static const struct wined3d_query_ops timestamp_query_ops = ++{ ++ wined3d_timestamp_query_ops_get_data, ++ wined3d_timestamp_query_ops_issue, ++}; ++ ++static const struct wined3d_query_ops timestamp_disjoint_query_ops = ++{ ++ wined3d_timestamp_disjoint_query_ops_get_data, ++#endif /* STAGING_CSMT */ + wined3d_timestamp_disjoint_query_ops_issue, + }; + +@@ -781,6 +1074,7 @@ + } + query->query_ops = &occlusion_query_ops; + query->data_size = sizeof(DWORD); ++#if defined(STAGING_CSMT) + query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(struct wined3d_occlusion_query)); + if (!query->extendedData) +@@ -788,6 +1082,15 @@ + ERR("Failed to allocate occlusion query extended data.\n"); + return E_OUTOFMEMORY; + } ++#else /* STAGING_CSMT */ ++ query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query)); ++ if (!query->extendedData) ++ { ++ ERR("Failed to allocate occlusion query extended data.\n"); ++ return E_OUTOFMEMORY; ++ } ++ ((struct wined3d_occlusion_query *)query->extendedData)->context = NULL; ++#endif /* STAGING_CSMT */ + break; + + case WINED3D_QUERY_TYPE_EVENT: +@@ -860,7 +1163,9 @@ + query->state = QUERY_CREATED; + query->device = device; + query->ref = 1; ++#if defined(STAGING_CSMT) + list_init(&query->poll_list_entry); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -203,7 +203,9 @@ + ERR("Failed to allocate system memory.\n"); + return E_OUTOFMEMORY; + } ++#if defined(STAGING_CSMT) + resource->heap_memory = resource->map_heap_memory; ++#endif /* STAGING_CSMT */ + } + else + { +@@ -227,6 +229,7 @@ + return WINED3D_OK; + } + ++#if defined(STAGING_CSMT) + void wined3d_resource_free_bo(struct wined3d_resource *resource) + { + struct wined3d_context *context = context_acquire(resource->device, NULL); +@@ -252,6 +255,7 @@ + resource->map_heap_memory = NULL; + } + ++#endif /* STAGING_CSMT */ + void resource_cleanup(struct wined3d_resource *resource) + { + const struct wined3d *d3d = resource->device->wined3d; +@@ -264,7 +268,11 @@ + adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size); + } + ++#if defined(STAGING_CSMT) + wined3d_cs_emit_resource_cleanup(resource->device->cs, resource); ++#else /* STAGING_CSMT */ ++ wined3d_resource_free_sysmem(resource); ++#endif /* STAGING_CSMT */ + + device_resource_released(resource->device, resource); + } +@@ -274,9 +282,11 @@ + if (resource->map_count) + ERR("Resource %p is being unloaded while mapped.\n", resource); + ++#if defined(STAGING_CSMT) + if (resource->buffer) + wined3d_resource_free_bo(resource); + ++#endif /* STAGING_CSMT */ + context_resource_unloaded(resource->device, + resource, resource->type); + } +@@ -355,7 +365,11 @@ + p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1; + *p = mem; + ++#if defined(STAGING_CSMT) + resource->map_heap_memory = ++p; ++#else /* STAGING_CSMT */ ++ resource->heap_memory = ++p; ++#endif /* STAGING_CSMT */ + + return TRUE; + } +@@ -421,7 +435,11 @@ + return ret; + } + ++#if defined(STAGING_CSMT) + static GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) ++#else /* STAGING_CSMT */ ++GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) ++#endif /* STAGING_CSMT */ + { + if (d3d_flags & WINED3D_MAP_READONLY) + return GL_READ_ONLY_ARB; +@@ -462,6 +480,7 @@ + else + resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB; + } ++#if defined(STAGING_CSMT) + + void wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) +@@ -1040,3 +1059,4 @@ + + wined3d_resource_invalidate_location(resource, ~resource->map_binding); + } ++#endif /* STAGING_CSMT */ +diff --git a/dlls/wined3d/sampler.c b/dlls/wined3d/sampler.c +--- a/dlls/wined3d/sampler.c ++++ b/dlls/wined3d/sampler.c +@@ -33,6 +33,7 @@ + return refcount; + } + ++#if defined(STAGING_CSMT) + void wined3d_sampler_destroy(struct wined3d_sampler *sampler) + { + struct wined3d_context *context = context_acquire(sampler->device, NULL); +@@ -54,6 +55,24 @@ + { + struct wined3d_device *device = sampler->device; + wined3d_cs_emit_sampler_destroy(device->cs, sampler); ++#else /* STAGING_CSMT */ ++ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler) ++{ ++ ULONG refcount = InterlockedDecrement(&sampler->refcount); ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++ ++ TRACE("%p decreasing refcount to %u.\n", sampler, refcount); ++ ++ if (!refcount) ++ { ++ context = context_acquire(sampler->device, NULL); ++ gl_info = context->gl_info; ++ GL_EXTCALL(glDeleteSamplers(1, &sampler->name)); ++ context_release(context); ++ ++ HeapFree(GetProcessHeap(), 0, sampler); +#endif /* STAGING_CSMT */ } return refcount; -@@ -497,8 +518,15 @@ - - void CDECL wined3d_texture_preload(struct wined3d_texture *texture) - { -+#if defined(STAGING_CSMT) - const struct wined3d_device *device = texture->resource.device; - wined3d_cs_emit_texture_preload(device->cs, texture); -+#else /* STAGING_CSMT */ -+ struct wined3d_context *context; -+ context = context_acquire(texture->resource.device, NULL); -+ wined3d_texture_load(texture, context, texture->flags & WINED3D_TEXTURE_IS_SRGB); -+ context_release(context); -+#endif /* STAGING_CSMT */ +diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c +--- a/dlls/wined3d/shader.c ++++ b/dlls/wined3d/shader.c +@@ -1872,7 +1872,11 @@ + } } - void * CDECL wined3d_texture_get_parent(const struct wined3d_texture *texture) -@@ -527,6 +555,7 @@ ++#if defined(STAGING_CSMT) + void shader_cleanup(struct wined3d_shader *shader) ++#else /* STAGING_CSMT */ ++static void shader_cleanup(struct wined3d_shader *shader) ++#endif /* STAGING_CSMT */ + { + HeapFree(GetProcessHeap(), 0, shader->output_signature.elements); + HeapFree(GetProcessHeap(), 0, shader->input_signature.elements); +@@ -2131,10 +2135,16 @@ - if (texture->lod != lod) + if (!refcount) { +#if defined(STAGING_CSMT) - if (wined3d_settings.cs_multithreaded) + const struct wined3d_device *device = shader->device; + + shader->parent_ops->wined3d_object_destroyed(shader->parent); + wined3d_cs_emit_shader_cleanup(device->cs, shader); ++#else /* STAGING_CSMT */ ++ shader_cleanup(shader); ++ shader->parent_ops->wined3d_object_destroyed(shader->parent); ++ HeapFree(GetProcessHeap(), 0, shader); ++#endif /* STAGING_CSMT */ + } + + return refcount; +@@ -2417,7 +2427,11 @@ + memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */ + if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE]) + { ++#if defined(STAGING_CSMT) + unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; ++#else /* STAGING_CSMT */ ++ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; ++#endif /* STAGING_CSMT */ + if (rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE) { - struct wined3d_device *device = texture->resource.device; -@@ -534,6 +563,7 @@ - device->cs->ops->finish(device->cs); - } + static unsigned int warned = 0; +diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c +--- a/dlls/wined3d/state.c ++++ b/dlls/wined3d/state.c +@@ -105,7 +105,11 @@ + const struct wined3d_gl_info *gl_info = context->gl_info; -+#endif /* STAGING_CSMT */ - texture->lod = lod; - - texture->texture_rgb.base_level = ~0u; -@@ -652,10 +682,14 @@ - } - - if (device->d3d_initialized) + /* No z test without depth stencil buffers */ +#if defined(STAGING_CSMT) + if (!state->fb.depth_stencil) ++#else /* STAGING_CSMT */ ++ if (!state->fb->depth_stencil) ++#endif /* STAGING_CSMT */ { - wined3d_cs_emit_evict_resource(device->cs, &surface->resource); - device->cs->ops->finish(device->cs); - } -+#else /* STAGING_CSMT */ -+ texture->resource.resource_ops->resource_unload(&texture->resource); -+#endif /* STAGING_CSMT */ + TRACE("No Z buffer - disabling depth test\n"); + zenable = WINED3D_ZB_FALSE; +@@ -370,8 +374,13 @@ - texture->resource.format = format; - texture->resource.multisample_type = multisample_type; -@@ -790,11 +824,19 @@ - struct wined3d_surface *surface = surface_from_resource(sub_resource); - struct wined3d_context *context; - -+#if defined(STAGING_CSMT) - context = context_acquire(surface->resource.device, NULL); - wined3d_resource_prepare_map_memory(&surface->resource, context); - wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); - context_release(context); - wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); -+#else /* STAGING_CSMT */ -+ surface_prepare_map_memory(surface); -+ context = context_acquire(surface->resource.device, NULL); -+ surface_load_location(surface, context, surface->resource.map_binding); -+ context_release(context); -+ surface_invalidate_location(surface, ~surface->resource.map_binding); -+#endif /* STAGING_CSMT */ - } - - static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource) -@@ -806,12 +848,25 @@ - - static void texture2d_sub_resource_invalidate_location(struct wined3d_resource *sub_resource, DWORD location) + static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { +#if defined(STAGING_CSMT) - wined3d_resource_invalidate_location(sub_resource, location); - } - - static void texture2d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) - { - wined3d_resource_validate_location(sub_resource, location); + const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; + unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; +#else /* STAGING_CSMT */ -+ struct wined3d_surface *surface = surface_from_resource(sub_resource); -+ -+ surface_invalidate_location(surface, location); -+} -+ -+static void texture2d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) -+{ -+ struct wined3d_surface *surface = surface_from_resource(sub_resource); -+ -+ surface_validate_location(surface, location); ++ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; +#endif /* STAGING_CSMT */ - } + const struct wined3d_gl_info *gl_info = context->gl_info; + GLenum srcBlend, dstBlend; + enum wined3d_blend d3d_blend; +@@ -816,7 +825,11 @@ + GLint depthFail_ccw; - static void texture2d_sub_resource_upload_data(struct wined3d_resource *sub_resource, -@@ -890,6 +945,7 @@ - - if (gl_info->supported[APPLE_CLIENT_STORAGE]) - { + /* No stencil test without a stencil buffer. */ +#if defined(STAGING_CSMT) - if (surface->flags & (SFLAG_NONPOW2) - || texture->flags & WINED3D_TEXTURE_CONVERTED) - { -@@ -898,12 +954,26 @@ - * WINED3D_TEXTURE_CONVERTED: The conversion destination memory is freed after loading the surface - * heap_memory == NULL: Not defined in the extension. Seems to disable client storage effectively - */ + if (!state->fb.depth_stencil) +#else /* STAGING_CSMT */ -+ if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION) -+ || texture->flags & WINED3D_TEXTURE_CONVERTED -+ || !surface->resource.heap_memory) -+ { -+ /* In some cases we want to disable client storage. -+ * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches -+ * SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues... -+ * WINED3D_TEXTURE_CONVERTED: The conversion destination memory is freed after loading the surface -+ * heap_memory == NULL: Not defined in the extension. Seems to disable client storage effectively -+ */ ++ if (!state->fb->depth_stencil) +#endif /* STAGING_CSMT */ - surface->flags &= ~SFLAG_CLIENT; - } - else - { -+#if defined(STAGING_CSMT) - wined3d_resource_prepare_system_memory(&surface->resource); - -+#endif /* STAGING_CSMT */ - surface->flags |= SFLAG_CLIENT; - mem = surface->resource.heap_memory; - -@@ -994,6 +1064,7 @@ - return wined3d_surface_unmap(surface_from_resource(sub_resource)); - } - -+#if defined(STAGING_CSMT) - static void wined3d_texture_load_location_invalidated(struct wined3d_resource *resource, DWORD location) - { - ERR("Should not be called on textures.\n"); -@@ -1006,6 +1077,7 @@ - ERR("Should not be called on textures.\n"); - } - -+#endif /* STAGING_CSMT */ - static const struct wined3d_resource_ops texture2d_resource_ops = - { - texture_resource_incref, -@@ -1013,8 +1085,10 @@ - wined3d_texture_unload, - texture2d_resource_sub_resource_map, - texture2d_resource_sub_resource_unmap, -+#if defined(STAGING_CSMT) - wined3d_texture_load_location_invalidated, - wined3d_texture_load_location, -+#endif /* STAGING_CSMT */ - }; - - static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, -@@ -1031,7 +1105,9 @@ - if (WINED3DFMT_UNKNOWN >= desc->format) { - WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; - } + gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); + checkGLcall("glDisable GL_STENCIL_TEST"); +@@ -912,7 +925,11 @@ -@@ -1041,6 +1117,7 @@ - if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) - { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); + static void state_stencilwrite2s(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); - return WINED3DERR_INVALIDCALL; - } -@@ -1049,6 +1126,14 @@ - { - WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); - HeapFree(GetProcessHeap(), 0, texture); + DWORD mask = state->fb.depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; +#else /* STAGING_CSMT */ -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (levels != 1) -+ { -+ WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); ++ DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; +#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; - } - } -@@ -1069,7 +1154,9 @@ - else - { - WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; - } - } -@@ -1079,7 +1166,9 @@ - surface_flags, device, parent, parent_ops, &texture2d_resource_ops))) - { - WARN("Failed to initialize texture, returning %#x\n", hr); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return hr; - } + const struct wined3d_gl_info *gl_info = context->gl_info; -@@ -1142,7 +1231,9 @@ - if (WINED3DFMT_UNKNOWN >= desc->format) - { - WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; - } + GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); +@@ -926,7 +943,11 @@ -@@ -1173,7 +1264,9 @@ - else - { - WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n"); + static void state_stencilwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); + DWORD mask = state->fb.depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; ++#else /* STAGING_CSMT */ ++ DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; +#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; + const struct wined3d_gl_info *gl_info = context->gl_info; + + gl_info->gl_ops.gl.p_glStencilMask(mask); +@@ -1128,10 +1149,17 @@ + /* drop through */ + + case WINED3D_FOG_NONE: ++#if defined(STAGING_CSMT) + /* Both are none? According to msdn the alpha channel of the specular + * color contains a fog factor. Set it in draw_strided_slow. + * Same happens with Vertexfog on transformed vertices + */ ++#else /* STAGING_CSMT */ ++ /* Both are none? According to msdn the alpha channel of the specular ++ * color contains a fog factor. Set it in drawStridedSlow. ++ * Same happens with Vertexfog on transformed vertices ++ */ ++#endif /* STAGING_CSMT */ + new_source = FOGSOURCE_COORD; + gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); +@@ -1653,7 +1681,11 @@ + if (state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS] + || state->render_states[WINED3D_RS_DEPTHBIAS]) + { ++#if defined(STAGING_CSMT) + const struct wined3d_rendertarget_view *depth = state->fb.depth_stencil; ++#else /* STAGING_CSMT */ ++ const struct wined3d_rendertarget_view *depth = state->fb->depth_stencil; ++#endif /* STAGING_CSMT */ + float scale; + + union +@@ -4190,9 +4222,15 @@ } } -@@ -1186,6 +1279,7 @@ - if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) - { - WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); + } else { +#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); - return WINED3DERR_INVALIDCALL; - } -@@ -1194,6 +1288,14 @@ - { - WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning WINED3DERR_INVALIDCALL.\n"); - HeapFree(GetProcessHeap(), 0, texture); + /* TODO: support blends in draw_strided_slow + * No need to write a FIXME here, this is done after the general vertex decl decoding + */ +#else /* STAGING_CSMT */ -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (levels != 1) -+ { -+ WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning WINED3DERR_INVALIDCALL.\n"); ++ /* TODO: support blends in drawStridedSlow ++ * No need to write a FIXME here, this is done after the general vertex decl decoding ++ */ +#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; + WARN("unsupported blending in openGl\n"); } } -@@ -1202,7 +1304,9 @@ - surface_flags, device, parent, parent_ops, &texture2d_resource_ops))) - { - WARN("Failed to initialize texture, returning %#x.\n", hr); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return hr; - } +@@ -4546,7 +4584,11 @@ -@@ -1288,12 +1392,25 @@ - - static void texture3d_sub_resource_invalidate_location(struct wined3d_resource *sub_resource, DWORD location) + static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { +#if defined(STAGING_CSMT) - wined3d_resource_invalidate_location(sub_resource, location); - } + const struct wined3d_rendertarget_view *target = state->fb.render_targets[0]; ++#else /* STAGING_CSMT */ ++ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; ++#endif /* STAGING_CSMT */ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_viewport vp = state->viewport; - static void texture3d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) +@@ -4724,7 +4766,11 @@ + } + else + { ++#if defined(STAGING_CSMT) + const struct wined3d_rendertarget_view *target = state->fb.render_targets[0]; ++#else /* STAGING_CSMT */ ++ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; ++#endif /* STAGING_CSMT */ + UINT height; + UINT width; + +@@ -4788,7 +4834,11 @@ + + void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - wined3d_resource_validate_location(sub_resource, location); -+#else /* STAGING_CSMT */ -+ struct wined3d_volume *volume = volume_from_resource(sub_resource); -+ -+ wined3d_volume_invalidate_location(volume, location); -+} -+ -+static void texture3d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) -+{ -+ struct wined3d_volume *volume = volume_from_resource(sub_resource); -+ -+ wined3d_volume_validate_location(volume, location); -+#endif /* STAGING_CSMT */ - } - - static void texture3d_sub_resource_upload_data(struct wined3d_resource *sub_resource, -@@ -1303,7 +1420,11 @@ - struct wined3d_const_bo_address addr; - unsigned int row_pitch, slice_pitch; - +#if defined(STAGING_CSMT) - wined3d_resource_get_pitch(sub_resource, &row_pitch, &slice_pitch); + unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; +#else /* STAGING_CSMT */ -+ wined3d_volume_get_pitch(volume, &row_pitch, &slice_pitch); ++ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; +#endif /* STAGING_CSMT */ - if (row_pitch != data->row_pitch || slice_pitch != data->slice_pitch) - FIXME("Ignoring row/slice pitch (%u/%u).\n", data->row_pitch, data->slice_pitch); + const struct wined3d_gl_info *gl_info = context->gl_info; -@@ -1328,7 +1449,11 @@ - void *mem = NULL; + TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id); +diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c +--- a/dlls/wined3d/stateblock.c ++++ b/dlls/wined3d/stateblock.c +@@ -464,7 +464,9 @@ + struct wined3d_texture *texture; + struct wined3d_buffer *buffer; + struct wined3d_shader *shader; ++#if defined(STAGING_CSMT) + struct wined3d_rendertarget_view *view; ++#endif /* STAGING_CSMT */ + unsigned int i, j; - if (gl_info->supported[APPLE_CLIENT_STORAGE] && !format->convert -+#if defined(STAGING_CSMT) - && wined3d_resource_prepare_system_memory(&volume->resource)) -+#else /* STAGING_CSMT */ -+ && volume_prepare_system_memory(volume)) -+#endif /* STAGING_CSMT */ - { - TRACE("Enabling GL_UNPACK_CLIENT_STORAGE_APPLE for volume %p\n", volume); - gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); -@@ -1405,6 +1530,7 @@ - if (WINED3DFMT_UNKNOWN >= desc->format) - { - WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); - return WINED3DERR_INVALIDCALL; - } -@@ -1413,6 +1539,14 @@ - { - WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); - HeapFree(GetProcessHeap(), 0, texture); -+#else /* STAGING_CSMT */ -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (!gl_info->supported[EXT_TEXTURE3D]) -+ { -+ WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); -+#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; - } - -@@ -1422,6 +1556,7 @@ - if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) - { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); - return WINED3DERR_INVALIDCALL; - } -@@ -1430,6 +1565,14 @@ - { - WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); - HeapFree(GetProcessHeap(), 0, texture); -+#else /* STAGING_CSMT */ -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (levels != 1) -+ { -+ WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); -+#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; - } - } -@@ -1457,7 +1600,9 @@ - { - WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n", - desc->width, desc->height, desc->depth); -+#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return WINED3DERR_INVALIDCALL; + if ((decl = state->vertex_declaration)) +@@ -541,6 +543,7 @@ } } -@@ -1467,7 +1612,9 @@ - 0, device, parent, parent_ops, &texture3d_resource_ops))) - { - WARN("Failed to initialize texture, returning %#x.\n", hr); + } +#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, texture); -+#endif /* STAGING_CSMT */ - return hr; - } -@@ -1568,6 +1715,9 @@ - if (FAILED(hr)) + if (state->fb.depth_stencil) { - WARN("Failed to initialize texture, returning %#x.\n", hr); -+#if !defined(STAGING_CSMT) -+ HeapFree(GetProcessHeap(), 0, object); +@@ -566,6 +569,7 @@ + } + } + } ++#endif /* STAGING_CSMT */ + } + + void state_cleanup(struct wined3d_state *state) +@@ -593,7 +597,9 @@ + + HeapFree(GetProcessHeap(), 0, state->vs_consts_f); + HeapFree(GetProcessHeap(), 0, state->ps_consts_f); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, state->fb.render_targets); ++#endif /* STAGING_CSMT */ + } + + ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock) +@@ -1075,8 +1081,13 @@ + gl_primitive_type = stateblock->state.gl_primitive_type; + prev = device->update_state->gl_primitive_type; + device->update_state->gl_primitive_type = gl_primitive_type; ++#if defined(STAGING_CSMT) + if (gl_primitive_type != prev) + wined3d_cs_emit_set_primitive_type(device->cs, gl_primitive_type); ++#else /* STAGING_CSMT */ ++ if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS)) ++ device_invalidate_state(device, STATE_POINT_ENABLE); +#endif /* STAGING_CSMT */ - return hr; } + if (stateblock->changed.indices) +@@ -1334,6 +1345,7 @@ + state->sampler_states[i][WINED3D_SAMP_ELEMENT_INDEX] = 0; + /* TODO: Vertex offset in the presampled displacement map. */ + state->sampler_states[i][WINED3D_SAMP_DMAP_OFFSET] = 0; ++#if defined(STAGING_CSMT) + state->textures[i] = NULL; + } + +@@ -1351,6 +1363,19 @@ + unsigned int i; + + state->flags = flags; ++#else /* STAGING_CSMT */ ++ } ++} ++ ++HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb, ++ const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info, ++ DWORD flags) ++{ ++ unsigned int i; ++ ++ state->flags = flags; ++ state->fb = fb; ++#endif /* STAGING_CSMT */ + + for (i = 0; i < LIGHTMAP_SIZE; i++) + { +@@ -1368,6 +1393,7 @@ + return E_OUTOFMEMORY; + } + ++#if defined(STAGING_CSMT) + if (!(state->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(*state->fb.render_targets) * gl_info->limits.buffers))) + { +@@ -1377,6 +1403,7 @@ + } + state->fb.rt_size = gl_info->limits.buffers; + ++#endif /* STAGING_CSMT */ + if (flags & WINED3D_STATE_INIT_DEFAULT) + state_init_default(state, gl_info); + +@@ -1387,6 +1414,7 @@ + struct wined3d_device *device, enum wined3d_stateblock_type type) + { + HRESULT hr; ++#if defined(STAGING_CSMT) + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; + +@@ -1394,6 +1422,14 @@ + stateblock->device = device; + + if (FAILED(hr = state_init(&stateblock->state, gl_info, d3d_info, 0))) ++#else /* STAGING_CSMT */ ++ const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; ++ ++ stateblock->ref = 1; ++ stateblock->device = device; ++ ++ if (FAILED(hr = state_init(&stateblock->state, NULL, &device->adapter->gl_info, d3d_info, 0))) ++#endif /* STAGING_CSMT */ + return hr; + + if (FAILED(hr = stateblock_allocate_shader_constants(stateblock))) diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -9151,721 +7666,2206 @@ diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c return hr; } -diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c ---- a/dlls/wined3d/shader.c -+++ b/dlls/wined3d/shader.c -@@ -1872,7 +1872,11 @@ +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -320,7 +320,11 @@ + if (backbuffer->resource.multisample_type) + { + location = WINED3D_LOCATION_RB_RESOLVED; ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&backbuffer->resource, context, location); ++#else /* STAGING_CSMT */ ++ surface_load_location(backbuffer, context, location); ++#endif /* STAGING_CSMT */ + } + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); +@@ -428,11 +432,19 @@ + } + + static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, ++#if defined(STAGING_CSMT) + const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags, + struct wined3d_surface *depth_stencil) + { + struct wined3d_surface *back_buffer = surface_from_resource( + wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)); ++#else /* STAGING_CSMT */ ++ const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) ++{ ++ struct wined3d_surface *back_buffer = surface_from_resource( ++ wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)); ++ const struct wined3d_fb_state *fb = &swapchain->device->fb; ++#endif /* STAGING_CSMT */ + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct wined3d_surface *front; +@@ -460,6 +472,37 @@ + NULL, WINED3D_TEXF_POINT); } + ++#if !defined(STAGING_CSMT) ++ if (swapchain->device->bCursorVisible && swapchain->device->cursor_texture ++ && !swapchain->device->hardwareCursor) ++ { ++ struct wined3d_surface *cursor = surface_from_resource( ++ wined3d_texture_get_sub_resource(swapchain->device->cursor_texture, 0)); ++ RECT destRect = ++ { ++ swapchain->device->xScreenSpace - swapchain->device->xHotSpot, ++ swapchain->device->yScreenSpace - swapchain->device->yHotSpot, ++ swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot, ++ swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot, ++ }; ++ RECT src_rect = ++ { ++ 0, 0, ++ swapchain->device->cursor_texture->resource.width, ++ swapchain->device->cursor_texture->resource.height ++ }; ++ const RECT clip_rect = {0, 0, back_buffer->resource.width, back_buffer->resource.height}; ++ ++ TRACE("Rendering the software cursor.\n"); ++ ++ if (swapchain->desc.windowed) ++ MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2); ++ if (wined3d_clip_blit(&clip_rect, &destRect, &src_rect)) ++ wined3d_surface_blt(back_buffer, &destRect, cursor, &src_rect, WINEDDBLT_ALPHATEST, ++ NULL, WINED3D_TEXF_POINT); ++ } ++ ++#endif /* STAGING_CSMT */ + TRACE("Presenting HDC %p.\n", context->hdc); + + render_to_fbo = swapchain->render_to_fbo; +@@ -501,6 +544,7 @@ + */ + if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&back_buffer->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_resource_invalidate_location(&back_buffer->resource, WINED3D_LOCATION_DRAWABLE); + swapchain->render_to_fbo = TRUE; +@@ -509,6 +553,16 @@ + else + { + wined3d_resource_load_location(&back_buffer->resource, context, back_buffer->container->resource.draw_binding); ++#else /* STAGING_CSMT */ ++ surface_load_location(back_buffer, context, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_invalidate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); ++ swapchain->render_to_fbo = TRUE; ++ swapchain_update_draw_bindings(swapchain); ++ } ++ else ++ { ++ surface_load_location(back_buffer, context, back_buffer->container->resource.draw_binding); ++#endif /* STAGING_CSMT */ + } + + if (swapchain->render_to_fbo) +@@ -521,8 +575,13 @@ + swapchain_blit(swapchain, context, &src_rect, &dst_rect); + } + ++#if defined(STAGING_CSMT) + if (swapchain->num_contexts > 1 && !wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFlush(); ++#else /* STAGING_CSMT */ ++ if (swapchain->num_contexts > 1) ++ gl_info->gl_ops.gl.p_glFinish(); ++#endif /* STAGING_CSMT */ + + /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ + gl_info->gl_ops.wgl.p_wglSwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */ +@@ -546,6 +605,7 @@ + + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); + ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); + wined3d_resource_invalidate_location(&front->resource, ~WINED3D_LOCATION_DRAWABLE); + switch (swapchain->desc.swap_effect) +@@ -574,6 +634,31 @@ + { + wined3d_texture_decref(swapchain->device->cs->onscreen_depth_stencil->container); + swapchain->device->cs->onscreen_depth_stencil = NULL; ++#else /* STAGING_CSMT */ ++ surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); ++ surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); ++ /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM ++ * and INTEXTURE copies can keep their old content if they have any defined content. ++ * If the swapeffect is COPY, the content remains the same. ++ * ++ * The FLIP swap effect is not implemented yet. We could mark WINED3D_LOCATION_DRAWABLE ++ * up to date and hope WGL flipped front and back buffers and read this data into ++ * the FBO. Don't bother about this for now. */ ++ ++ if (fb->depth_stencil) ++ { ++ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(fb->depth_stencil); ++ ++ if (ds && (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL ++ || ds->flags & SFLAG_DISCARD)) ++ { ++ surface_modify_ds_location(ds, WINED3D_LOCATION_DISCARDED, ++ fb->depth_stencil->width, fb->depth_stencil->height); ++ if (ds == swapchain->device->onscreen_depth_stencil) ++ { ++ wined3d_texture_decref(swapchain->device->onscreen_depth_stencil->container); ++ swapchain->device->onscreen_depth_stencil = NULL; ++#endif /* STAGING_CSMT */ + } + } + } +@@ -606,7 +691,11 @@ + + TRACE("Copying surface %p to screen.\n", front); + ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&front->resource, NULL, WINED3D_LOCATION_DIB); ++#else /* STAGING_CSMT */ ++ surface_load_location(front, NULL, WINED3D_LOCATION_DIB); ++#endif /* STAGING_CSMT */ + + src_dc = front->hDC; + window = swapchain->win_handle; +@@ -634,8 +723,12 @@ + } + + static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, ++#if defined(STAGING_CSMT) + const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags, + struct wined3d_surface *depth_stencil) ++#else /* STAGING_CSMT */ ++ const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) ++#endif /* STAGING_CSMT */ + { + struct wined3d_surface *front, *back; + +@@ -662,9 +755,15 @@ + { + void *tmp; + ++#if defined(STAGING_CSMT) + tmp = front->resource.bitmap_data; + front->resource.bitmap_data = back->resource.bitmap_data; + back->resource.bitmap_data = tmp; ++#else /* STAGING_CSMT */ ++ tmp = front->dib.bitmap_data; ++ front->dib.bitmap_data = back->dib.bitmap_data; ++ back->dib.bitmap_data = tmp; ++#endif /* STAGING_CSMT */ + + if (front->resource.heap_memory) + ERR("GDI Surface %p has heap memory allocated.\n", front); +@@ -735,6 +834,7 @@ + swapchain->render_to_fbo = TRUE; } +#if defined(STAGING_CSMT) - void shader_cleanup(struct wined3d_shader *shader) -+#else /* STAGING_CSMT */ -+static void shader_cleanup(struct wined3d_shader *shader) -+#endif /* STAGING_CSMT */ + HRESULT swapchain_create_context_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain) { - HeapFree(GetProcessHeap(), 0, shader->output_signature.elements); - HeapFree(GetProcessHeap(), 0, shader->input_signature.elements); -@@ -2131,10 +2135,16 @@ + const struct wined3d_adapter *adapter = device->adapter; +@@ -798,6 +898,7 @@ + return WINED3D_OK; + } + ++#endif /* STAGING_CSMT */ + static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device, + struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) + { +@@ -888,8 +989,13 @@ + front_buffer = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); + if (!(device->wined3d->flags & WINED3D_NO3D)) + { ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&front_buffer->resource, WINED3D_LOCATION_DRAWABLE); + wined3d_resource_invalidate_location(&front_buffer->resource, ~WINED3D_LOCATION_DRAWABLE); ++#else /* STAGING_CSMT */ ++ surface_validate_location(front_buffer, WINED3D_LOCATION_DRAWABLE); ++ surface_invalidate_location(front_buffer, ~WINED3D_LOCATION_DRAWABLE); ++#endif /* STAGING_CSMT */ + } + + /* MSDN says we're only allowed a single fullscreen swapchain per device, +@@ -915,9 +1021,66 @@ + + if (!(device->wined3d->flags & WINED3D_NO3D)) + { ++#if defined(STAGING_CSMT) + hr = wined3d_cs_emit_create_swapchain_context(device->cs, swapchain); + if (FAILED(hr)) + goto err; ++#else /* STAGING_CSMT */ ++ static const enum wined3d_format_id formats[] = ++ { ++ WINED3DFMT_D24_UNORM_S8_UINT, ++ WINED3DFMT_D32_UNORM, ++ WINED3DFMT_R24_UNORM_X8_TYPELESS, ++ WINED3DFMT_D16_UNORM, ++ WINED3DFMT_S1_UINT_D15_UNORM ++ }; ++ ++ const struct wined3d_gl_info *gl_info = &adapter->gl_info; ++ ++ swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context)); ++ if (!swapchain->context) ++ { ++ ERR("Failed to create the context array.\n"); ++ hr = E_OUTOFMEMORY; ++ goto err; ++ } ++ swapchain->num_contexts = 1; ++ ++ /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate. ++ * You are able to add a depth + stencil surface at a later stage when you need it. ++ * In order to support this properly in WineD3D we need the ability to recreate the opengl context and ++ * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new ++ * context, need torecreate shaders, textures and other resources. ++ * ++ * The context manager already takes care of the state problem and for the other tasks code from Reset ++ * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now. ++ * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the ++ * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this ++ * issue needs to be fixed. */ ++ for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++) ++ { ++ swapchain->ds_format = wined3d_get_format(gl_info, formats[i]); ++ swapchain->context[0] = context_create(swapchain, front_buffer, swapchain->ds_format); ++ if (swapchain->context[0]) break; ++ TRACE("Depth stencil format %s is not supported, trying next format\n", ++ debug_d3dformat(formats[i])); ++ } ++ ++ if (!swapchain->context[0]) ++ { ++ WARN("Failed to create context.\n"); ++ hr = WINED3DERR_NOTAVAILABLE; ++ goto err; ++ } ++ ++ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO ++ && (!desc->enable_auto_depth_stencil ++ || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id)) ++ { ++ FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n"); ++ } ++ context_release(swapchain->context[0]); ++#endif /* STAGING_CSMT */ + } + + if (swapchain->desc.backbuffer_count > 0) +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -68,8 +68,10 @@ + { + ERR("Failed to allocate sub-resource array.\n"); + resource_cleanup(&texture->resource); ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + texture->resource.device->cs->ops->finish(texture->resource.device->cs); ++#endif /* STAGING_CSMT */ + return E_OUTOFMEMORY; + } + +@@ -114,6 +116,7 @@ + resource_unload(&texture->resource); + } + ++#if defined(STAGING_CSMT) + void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) + { + wined3d_texture_unload_gl_texture(texture); +@@ -126,6 +129,12 @@ + UINT sub_count = texture->level_count * texture->layer_count; + UINT i; + struct wined3d_device *device = texture->resource.device; ++#else /* STAGING_CSMT */ ++static void wined3d_texture_cleanup(struct wined3d_texture *texture) ++{ ++ UINT sub_count = texture->level_count * texture->layer_count; ++ UINT i; ++#endif /* STAGING_CSMT */ + + TRACE("texture %p.\n", texture); + +@@ -137,8 +146,14 @@ + texture->texture_ops->texture_sub_resource_cleanup(sub_resource); + } + ++#if defined(STAGING_CSMT) + resource_cleanup(&texture->resource); + wined3d_cs_emit_texture_cleanup(device->cs, texture); ++#else /* STAGING_CSMT */ ++ wined3d_texture_unload_gl_texture(texture); ++ HeapFree(GetProcessHeap(), 0, texture->sub_resources); ++ resource_cleanup(&texture->resource); ++#endif /* STAGING_CSMT */ + } + + void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain) +@@ -422,10 +437,16 @@ if (!refcount) { +#if defined(STAGING_CSMT) - const struct wined3d_device *device = shader->device; - - shader->parent_ops->wined3d_object_destroyed(shader->parent); - wined3d_cs_emit_shader_cleanup(device->cs, shader); + void *parent = texture->resource.parent; + const struct wined3d_parent_ops *parent_ops = texture->resource.parent_ops; + wined3d_texture_cleanup(texture); + parent_ops->wined3d_object_destroyed(parent); +#else /* STAGING_CSMT */ -+ shader_cleanup(shader); -+ shader->parent_ops->wined3d_object_destroyed(shader->parent); -+ HeapFree(GetProcessHeap(), 0, shader); ++ wined3d_texture_cleanup(texture); ++ texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent); ++ HeapFree(GetProcessHeap(), 0, texture); +#endif /* STAGING_CSMT */ } return refcount; -@@ -2417,7 +2427,11 @@ - memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */ - if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE]) - { -+#if defined(STAGING_CSMT) - unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; -+#else /* STAGING_CSMT */ -+ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; -+#endif /* STAGING_CSMT */ - if (rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE) - { - static unsigned int warned = 0; -diff --git a/dlls/wined3d/sampler.c b/dlls/wined3d/sampler.c ---- a/dlls/wined3d/sampler.c -+++ b/dlls/wined3d/sampler.c -@@ -33,6 +33,7 @@ - return refcount; - } +@@ -497,8 +518,15 @@ -+#if defined(STAGING_CSMT) - void wined3d_sampler_destroy(struct wined3d_sampler *sampler) - { - struct wined3d_context *context = context_acquire(sampler->device, NULL); -@@ -54,6 +55,24 @@ - { - struct wined3d_device *device = sampler->device; - wined3d_cs_emit_sampler_destroy(device->cs, sampler); -+#else /* STAGING_CSMT */ -+ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler) -+{ -+ ULONG refcount = InterlockedDecrement(&sampler->refcount); -+ const struct wined3d_gl_info *gl_info; -+ struct wined3d_context *context; -+ -+ TRACE("%p decreasing refcount to %u.\n", sampler, refcount); -+ -+ if (!refcount) -+ { -+ context = context_acquire(sampler->device, NULL); -+ gl_info = context->gl_info; -+ GL_EXTCALL(glDeleteSamplers(1, &sampler->name)); -+ context_release(context); -+ -+ HeapFree(GetProcessHeap(), 0, sampler); -+#endif /* STAGING_CSMT */ - } - - return refcount; -diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c ---- a/dlls/wined3d/buffer.c -+++ b/dlls/wined3d/buffer.c -@@ -32,6 +32,7 @@ - #define WINED3D_BUFFER_HASDESC 0x01 /* A vertex description has been found. */ - #define WINED3D_BUFFER_CREATEBO 0x02 /* Create a buffer object for this buffer. */ - #define WINED3D_BUFFER_DOUBLEBUFFER 0x04 /* Keep both a buffer object and a system memory copy for this buffer. */ -+#if defined(STAGING_CSMT) - #define WINED3D_BUFFER_DISCARD 0x08 /* The next PreLoad may discard the buffer contents. */ - #define WINED3D_BUFFER_SYNC 0x10 /* There has been at least one synchronized map since the last preload. */ - #define WINED3D_BUFFER_APPLESYNC 0x20 /* Using sync as in GL_APPLE_flush_buffer_range. */ -@@ -42,6 +43,19 @@ - #define VB_RESETFULLCONVS 20 /* Reset full conversion counts after that number of draws */ - - void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, UINT offset, UINT size) -+#else /* STAGING_CSMT */ -+#define WINED3D_BUFFER_FLUSH 0x08 /* Manual unmap flushing. */ -+#define WINED3D_BUFFER_DISCARD 0x10 /* A DISCARD lock has occurred since the last preload. */ -+#define WINED3D_BUFFER_SYNC 0x20 /* There has been at least one synchronized map since the last preload. */ -+#define WINED3D_BUFFER_APPLESYNC 0x40 /* Using sync as in GL_APPLE_flush_buffer_range. */ -+ -+#define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */ -+#define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */ -+#define VB_MAXFULLCONVERSIONS 5 /* Number of full conversions before we stop converting */ -+#define VB_RESETFULLCONVS 20 /* Reset full conversion counts after that number of draws */ -+ -+static void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, UINT offset, UINT size) -+#endif /* STAGING_CSMT */ - { - if (!offset && !size) - goto invalidate_all; -@@ -117,7 +131,11 @@ - } - - /* Context activation is done by the caller. */ -+#if defined(STAGING_CSMT) - void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context) -+#else /* STAGING_CSMT */ -+static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context) -+#endif /* STAGING_CSMT */ - { - GLenum gl_usage = GL_STATIC_DRAW_ARB; - GLenum error; -@@ -166,6 +184,10 @@ - { - GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)); - checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)"); -+#if !defined(STAGING_CSMT) -+ This->flags |= WINED3D_BUFFER_FLUSH; -+ -+#endif /* STAGING_CSMT */ - GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); - checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)"); - This->flags |= WINED3D_BUFFER_APPLESYNC; -@@ -191,10 +213,14 @@ - if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER) - buffer_invalidate_bo_range(This, 0, 0); - else -+#if defined(STAGING_CSMT) - { - wined3d_resource_free_sysmem(&This->resource); - This->resource.map_heap_memory = NULL; - } -+#else /* STAGING_CSMT */ -+ wined3d_resource_free_sysmem(&This->resource); -+#endif /* STAGING_CSMT */ - - return; - -@@ -423,6 +449,7 @@ - { - DWORD src_color = *dst_color; - -+#if defined(STAGING_CSMT) - /* Color conversion like in draw_strided_slow. watch out for little endianity - * If we want that stuff to work on big endian machines too we have to consider more things - * -@@ -431,6 +458,16 @@ - * 0x0000ff00: Green mask - * 0x000000ff: Red mask - */ -+#else /* STAGING_CSMT */ -+ /* Color conversion like in drawStridedSlow. watch out for little endianity -+ * If we want that stuff to work on big endian machines too we have to consider more things -+ * -+ * 0xff000000: Alpha mask -+ * 0x00ff0000: Blue mask -+ * 0x0000ff00: Green mask -+ * 0x000000ff: Red mask -+ */ -+#endif /* STAGING_CSMT */ - *dst_color = 0; - *dst_color |= (src_color & 0xff00ff00u); /* Alpha Green */ - *dst_color |= (src_color & 0x00ff0000u) >> 16; /* Red */ -@@ -457,8 +494,12 @@ - data->buffer_object = buffer->buffer_object; - if (!buffer->buffer_object) - { -+#if defined(STAGING_CSMT) - if ((!buffer->resource.map_count || buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER) - && buffer->flags & WINED3D_BUFFER_CREATEBO) -+#else /* STAGING_CSMT */ -+ if ((buffer->flags & WINED3D_BUFFER_CREATEBO) && !buffer->resource.map_count) -+#endif /* STAGING_CSMT */ - { - buffer_create_buffer_object(buffer, context); - buffer->flags &= ~WINED3D_BUFFER_CREATEBO; -@@ -497,7 +538,9 @@ - - if (!wined3d_resource_allocate_sysmem(&This->resource)) - ERR("Failed to allocate system memory.\n"); -+#if defined(STAGING_CSMT) - This->resource.heap_memory = This->resource.map_heap_memory; -+#endif /* STAGING_CSMT */ - - if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) - context_invalidate_state(context, STATE_INDEXBUFFER); -@@ -545,6 +588,7 @@ - resource_unload(resource); - } - -+#if defined(STAGING_CSMT) - void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer) - { - struct wined3d_context *context; -@@ -577,6 +621,30 @@ - - buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent); - wined3d_cs_emit_buffer_cleanup(device->cs, buffer); -+#else /* STAGING_CSMT */ -+ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer) -+{ -+ ULONG refcount = InterlockedDecrement(&buffer->resource.ref); -+ struct wined3d_context *context; -+ -+ TRACE("%p decreasing refcount to %u.\n", buffer, refcount); -+ -+ if (!refcount) -+ { -+ if (buffer->buffer_object) -+ { -+ context = context_acquire(buffer->resource.device, NULL); -+ delete_gl_buffer(buffer, context->gl_info); -+ context_release(context); -+ -+ HeapFree(GetProcessHeap(), 0, buffer->conversion_map); -+ } -+ -+ resource_cleanup(&buffer->resource); -+ buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent); -+ HeapFree(GetProcessHeap(), 0, buffer->maps); -+ HeapFree(GetProcessHeap(), 0, buffer); -+#endif /* STAGING_CSMT */ - } - - return refcount; -@@ -661,6 +729,7 @@ - /* The caller provides a GL context */ - static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags) + void CDECL wined3d_texture_preload(struct wined3d_texture *texture) { +#if defined(STAGING_CSMT) - UINT start = 0, len = 0; - - /* This potentially invalidates the element array buffer binding, but the -@@ -684,6 +753,45 @@ - GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)); - checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)"); - This->flags &= ~WINED3D_BUFFER_APPLESYNC; -+#else /* STAGING_CSMT */ -+ BYTE *map; -+ UINT start = 0, len = 0; -+ -+ /* This potentially invalidates the element array buffer binding, but the -+ * caller always takes care of this. */ -+ GL_EXTCALL(glBindBuffer(This->buffer_type_hint, This->buffer_object)); -+ checkGLcall("glBindBuffer"); -+ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) -+ { -+ GLbitfield mapflags; -+ mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; -+ if (flags & WINED3D_BUFFER_DISCARD) -+ mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT; -+ else if (!(flags & WINED3D_BUFFER_SYNC)) -+ mapflags |= GL_MAP_UNSYNCHRONIZED_BIT; -+ map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, -+ This->resource.size, mapflags)); -+ checkGLcall("glMapBufferRange"); -+ } -+ else -+ { -+ if (This->flags & WINED3D_BUFFER_APPLESYNC) -+ { -+ DWORD syncflags = 0; -+ if (flags & WINED3D_BUFFER_DISCARD) -+ syncflags |= WINED3D_MAP_DISCARD; -+ else if (!(flags & WINED3D_BUFFER_SYNC)) -+ syncflags |= WINED3D_MAP_NOOVERWRITE; -+ buffer_sync_apple(This, syncflags, gl_info); -+ } -+ map = GL_EXTCALL(glMapBuffer(This->buffer_type_hint, GL_WRITE_ONLY)); -+ checkGLcall("glMapBuffer"); -+ } -+ if (!map) -+ { -+ ERR("Failed to map opengl buffer\n"); -+ return; -+#endif /* STAGING_CSMT */ - } - - while (This->modified_areas) -@@ -692,12 +800,33 @@ - start = This->maps[This->modified_areas].offset; - len = This->maps[This->modified_areas].size; - -+#if defined(STAGING_CSMT) - GL_EXTCALL(glBufferSubData(This->buffer_type_hint, start, len, (BYTE *)This->resource.heap_memory + start)); - checkGLcall("glBufferSubData"); - } - } - - static void buffer_mark_used(struct wined3d_buffer *buffer) -+#else /* STAGING_CSMT */ -+ memcpy(map + start, (BYTE *)This->resource.heap_memory + start, len); -+ -+ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) -+ { -+ GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len)); -+ checkGLcall("glFlushMappedBufferRange"); -+ } -+ else if (This->flags & WINED3D_BUFFER_FLUSH) -+ { -+ GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len)); -+ checkGLcall("glFlushMappedBufferRangeAPPLE"); -+ } -+ } -+ GL_EXTCALL(glUnmapBuffer(This->buffer_type_hint)); -+ checkGLcall("glUnmapBuffer"); -+} -+ -+void buffer_mark_used(struct wined3d_buffer *buffer) -+#endif /* STAGING_CSMT */ - { - buffer->flags &= ~(WINED3D_BUFFER_SYNC | WINED3D_BUFFER_DISCARD); - } -@@ -716,6 +845,14 @@ - - TRACE("buffer %p.\n", buffer); - -+#if !defined(STAGING_CSMT) -+ if (buffer->resource.map_count) -+ { -+ WARN("Buffer is mapped, skipping preload.\n"); -+ return; -+ } -+ -+#endif /* STAGING_CSMT */ - buffer_mark_used(buffer); - - if (!buffer->buffer_object) -@@ -904,6 +1041,7 @@ - - void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) - { -+#if defined(STAGING_CSMT) - struct wined3d_device *device = buffer->resource.device; - - if (buffer->resource.map_count) -@@ -913,6 +1051,12 @@ - } - - wined3d_cs_emit_buffer_preload(device->cs, buffer); + const struct wined3d_device *device = texture->resource.device; + wined3d_cs_emit_texture_preload(device->cs, texture); +#else /* STAGING_CSMT */ + struct wined3d_context *context; -+ context = context_acquire(buffer->resource.device, NULL); -+ buffer_internal_preload(buffer, context, NULL); ++ context = context_acquire(texture->resource.device, NULL); ++ wined3d_texture_load(texture, context, texture->flags & WINED3D_TEXTURE_IS_SRGB); + context_release(context); +#endif /* STAGING_CSMT */ } - struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer) -@@ -926,6 +1070,7 @@ - { - LONG count; - BYTE *base; -+#if defined(STAGING_CSMT) - struct wined3d_device *device = buffer->resource.device; - struct wined3d_context *context; + void * CDECL wined3d_texture_get_parent(const struct wined3d_texture *texture) +@@ -527,6 +555,7 @@ -@@ -950,6 +1095,10 @@ - wined3d_cs_emit_create_vbo(device->cs, buffer); - buffer->flags &= ~WINED3D_BUFFER_CREATEBO; - } -+#else /* STAGING_CSMT */ -+ -+ TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags); -+#endif /* STAGING_CSMT */ - - flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags); - /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001 multitexture -@@ -958,7 +1107,11 @@ - * previous contents of the buffer. The r600g driver only does this when - * the buffer is currently in use, while the proprietary NVIDIA driver - * appears to do this unconditionally. */ -+#if defined(STAGING_CSMT) - if (buffer->ignore_discard) -+#else /* STAGING_CSMT */ -+ if (buffer->flags & WINED3D_BUFFER_DISCARD) -+#endif /* STAGING_CSMT */ - flags &= ~WINED3D_MAP_DISCARD; - count = ++buffer->resource.map_count; - -@@ -969,6 +1122,7 @@ - * being uploaded in that case. Two such applications are Port Royale - * and Darkstar One. */ - if (flags & WINED3D_MAP_DISCARD) -+#if defined(STAGING_CSMT) - wined3d_cs_emit_buffer_invalidate_bo_range(device->cs, buffer, 0, 0); - else if (!(flags & WINED3D_MAP_READONLY)) - wined3d_cs_emit_buffer_invalidate_bo_range(device->cs, buffer, offset, size); -@@ -986,6 +1140,19 @@ - wined3d_cs_emit_glfinish(device->cs); - device->cs->ops->finish(device->cs); - } -+#else /* STAGING_CSMT */ -+ buffer_invalidate_bo_range(buffer, 0, 0); -+ else if (!(flags & WINED3D_MAP_READONLY)) -+ buffer_invalidate_bo_range(buffer, offset, size); -+ -+ if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER)) -+ { -+ if (count == 1) -+ { -+ struct wined3d_device *device = buffer->resource.device; -+ struct wined3d_context *context; -+ const struct wined3d_gl_info *gl_info; -+#endif /* STAGING_CSMT */ - - context = context_acquire(device, NULL); - gl_info = context->gl_info; -@@ -1036,6 +1203,7 @@ - buffer_get_sysmem(buffer, context); - } - TRACE("New pointer is %p.\n", buffer->resource.heap_memory); -+#if defined(STAGING_CSMT) - } - context_release(context); - } -@@ -1075,6 +1243,21 @@ - } - - base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.map_heap_memory; -+#else /* STAGING_CSMT */ -+ buffer->map_ptr = NULL; -+ } -+ context_release(context); -+ } -+ } -+ -+ if (flags & WINED3D_MAP_DISCARD) -+ buffer->flags |= WINED3D_BUFFER_DISCARD; -+ else if (!(flags & WINED3D_MAP_NOOVERWRITE)) -+ buffer->flags |= WINED3D_BUFFER_SYNC; -+ } -+ -+ base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory; -+#endif /* STAGING_CSMT */ - *data = base + offset; - - TRACE("Returning memory at %p (base %p, offset %u).\n", *data, base, offset); -@@ -1128,7 +1311,11 @@ - checkGLcall("glFlushMappedBufferRange"); - } - } -+#if defined(STAGING_CSMT) - else if (buffer->flags & WINED3D_BUFFER_APPLESYNC) -+#else /* STAGING_CSMT */ -+ else if (buffer->flags & WINED3D_BUFFER_FLUSH) -+#endif /* STAGING_CSMT */ - { - for (i = 0; i < buffer->modified_areas; ++i) - { -@@ -1139,6 +1326,7 @@ - } - - GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint)); + if (texture->lod != lod) + { +#if defined(STAGING_CSMT) if (wined3d_settings.cs_multithreaded) - gl_info->gl_ops.gl.p_glFinish(); - else if (wined3d_settings.strict_draw_ordering) -@@ -1147,6 +1335,18 @@ + { + struct wined3d_device *device = texture->resource.device; +@@ -534,6 +563,7 @@ + device->cs->ops->finish(device->cs); + } - buffer_clear_dirty_areas(buffer); - buffer->map_ptr = NULL; -+#else /* STAGING_CSMT */ -+ if (wined3d_settings.strict_draw_ordering) -+ gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ -+ context_release(context); -+ -+ buffer_clear_dirty_areas(buffer); -+ buffer->map_ptr = NULL; -+ } -+ else if (buffer->flags & WINED3D_BUFFER_HASDESC) -+ { -+ wined3d_buffer_preload(buffer); +#endif /* STAGING_CSMT */ + texture->lod = lod; + + texture->texture_rgb.base_level = ~0u; +@@ -652,10 +682,14 @@ } + + if (device->d3d_initialized) ++#if defined(STAGING_CSMT) + { + wined3d_cs_emit_evict_resource(device->cs, &surface->resource); + device->cs->ops->finish(device->cs); + } ++#else /* STAGING_CSMT */ ++ texture->resource.resource_ops->resource_unload(&texture->resource); ++#endif /* STAGING_CSMT */ + + texture->resource.format = format; + texture->resource.multisample_type = multisample_type; +@@ -790,11 +824,19 @@ + struct wined3d_surface *surface = surface_from_resource(sub_resource); + struct wined3d_context *context; + ++#if defined(STAGING_CSMT) + context = context_acquire(surface->resource.device, NULL); + wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + context_release(context); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); ++#else /* STAGING_CSMT */ ++ surface_prepare_map_memory(surface); ++ context = context_acquire(surface->resource.device, NULL); ++ surface_load_location(surface, context, surface->resource.map_binding); ++ context_release(context); ++ surface_invalidate_location(surface, ~surface->resource.map_binding); ++#endif /* STAGING_CSMT */ } -@@ -1198,6 +1398,7 @@ - return WINED3D_OK; + static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource) +@@ -806,12 +848,25 @@ + + static void texture2d_sub_resource_invalidate_location(struct wined3d_resource *sub_resource, DWORD location) + { ++#if defined(STAGING_CSMT) + wined3d_resource_invalidate_location(sub_resource, location); + } + + static void texture2d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) + { + wined3d_resource_validate_location(sub_resource, location); ++#else /* STAGING_CSMT */ ++ struct wined3d_surface *surface = surface_from_resource(sub_resource); ++ ++ surface_invalidate_location(surface, location); ++} ++ ++static void texture2d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) ++{ ++ struct wined3d_surface *surface = surface_from_resource(sub_resource); ++ ++ surface_validate_location(surface, location); ++#endif /* STAGING_CSMT */ + } + + static void texture2d_sub_resource_upload_data(struct wined3d_resource *sub_resource, +@@ -890,6 +945,7 @@ + + if (gl_info->supported[APPLE_CLIENT_STORAGE]) + { ++#if defined(STAGING_CSMT) + if (surface->flags & (SFLAG_NONPOW2) + || texture->flags & WINED3D_TEXTURE_CONVERTED) + { +@@ -898,12 +954,26 @@ + * WINED3D_TEXTURE_CONVERTED: The conversion destination memory is freed after loading the surface + * heap_memory == NULL: Not defined in the extension. Seems to disable client storage effectively + */ ++#else /* STAGING_CSMT */ ++ if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION) ++ || texture->flags & WINED3D_TEXTURE_CONVERTED ++ || !surface->resource.heap_memory) ++ { ++ /* In some cases we want to disable client storage. ++ * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches ++ * SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues... ++ * WINED3D_TEXTURE_CONVERTED: The conversion destination memory is freed after loading the surface ++ * heap_memory == NULL: Not defined in the extension. Seems to disable client storage effectively ++ */ ++#endif /* STAGING_CSMT */ + surface->flags &= ~SFLAG_CLIENT; + } + else + { ++#if defined(STAGING_CSMT) + wined3d_resource_prepare_system_memory(&surface->resource); + ++#endif /* STAGING_CSMT */ + surface->flags |= SFLAG_CLIENT; + mem = surface->resource.heap_memory; + +@@ -994,6 +1064,7 @@ + return wined3d_surface_unmap(surface_from_resource(sub_resource)); } +#if defined(STAGING_CSMT) - static void wined3d_buffer_location_invalidated(struct wined3d_resource *resource, DWORD location) + static void wined3d_texture_load_location_invalidated(struct wined3d_resource *resource, DWORD location) { - ERR("Not yet implemented.\n"); -@@ -1210,6 +1411,7 @@ - ERR("Not yet implemented.\n"); + ERR("Should not be called on textures.\n"); +@@ -1006,6 +1077,7 @@ + ERR("Should not be called on textures.\n"); } +#endif /* STAGING_CSMT */ - static const struct wined3d_resource_ops buffer_resource_ops = + static const struct wined3d_resource_ops texture2d_resource_ops = { - buffer_resource_incref, -@@ -1217,8 +1419,10 @@ - buffer_unload, - buffer_resource_sub_resource_map, - buffer_resource_sub_resource_unmap, + texture_resource_incref, +@@ -1013,8 +1085,10 @@ + wined3d_texture_unload, + texture2d_resource_sub_resource_map, + texture2d_resource_sub_resource_unmap, +#if defined(STAGING_CSMT) - wined3d_buffer_location_invalidated, - wined3d_buffer_load_location, + wined3d_texture_load_location_invalidated, + wined3d_texture_load_location, +#endif /* STAGING_CSMT */ }; - static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device, -@@ -1250,7 +1454,9 @@ + static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, +@@ -1031,7 +1105,9 @@ + if (WINED3DFMT_UNKNOWN >= desc->format) + { + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + +@@ -1041,6 +1117,7 @@ + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } +@@ -1049,6 +1126,14 @@ + { + WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); + HeapFree(GetProcessHeap(), 0, texture); ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (levels != 1) ++ { ++ WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + } +@@ -1069,7 +1154,9 @@ + else + { + WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + } +@@ -1079,7 +1166,9 @@ + surface_flags, device, parent, parent_ops, &texture2d_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x\n", hr); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ return hr; } - buffer->buffer_type_hint = bind_hint; -+#if defined(STAGING_CSMT) - buffer->ignore_discard = TRUE; -+#endif /* STAGING_CSMT */ - TRACE("size %#x, usage %#x, format %s, memory @ %p, iface @ %p.\n", buffer->resource.size, buffer->resource.usage, - debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory, buffer); -@@ -1266,6 +1472,7 @@ - - dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE]; - -+#if defined(STAGING_CSMT) - /* Observations show that draw_strided_slow is faster on dynamic VBs than converting + - * drawStridedFast (half-life 2 and others). - * -@@ -1273,6 +1480,15 @@ - * show that draw_strided_slow is faster than converting + uploading + drawStridedFast. - * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers. - */ -+#else /* STAGING_CSMT */ -+ /* Observations show that drawStridedSlow is faster on dynamic VBs than converting + -+ * drawStridedFast (half-life 2 and others). -+ * -+ * Basically converting the vertices in the buffer is quite expensive, and observations -+ * show that drawStridedSlow is faster than converting + uploading + drawStridedFast. -+ * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers. -+ */ -+#endif /* STAGING_CSMT */ - if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT]) +@@ -1142,7 +1231,9 @@ + if (WINED3DFMT_UNKNOWN >= desc->format) { - TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n"); -@@ -1290,6 +1506,7 @@ - buffer->flags |= WINED3D_BUFFER_CREATEBO; + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; } +@@ -1173,7 +1264,9 @@ + else + { + WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n"); +#if defined(STAGING_CSMT) - buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps)); - if (!buffer->maps) - { -@@ -1300,6 +1517,7 @@ - } - buffer->maps_size = 1; - + HeapFree(GetProcessHeap(), 0, texture); +#endif /* STAGING_CSMT */ - if (data) - { - BYTE *ptr; -@@ -1308,7 +1526,9 @@ - if (FAILED(hr)) + return WINED3DERR_INVALIDCALL; + } + } +@@ -1186,6 +1279,7 @@ + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { - ERR("Failed to map buffer, hr %#x\n", hr); + WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); +#if defined(STAGING_CSMT) - HeapFree(GetProcessHeap(), 0, buffer->maps); -+#endif /* STAGING_CSMT */ - buffer_unload(&buffer->resource); - resource_cleanup(&buffer->resource); - return hr; -@@ -1319,8 +1539,20 @@ - wined3d_buffer_unmap(buffer); - } - -+#if defined(STAGING_CSMT) - if (wined3d_settings.cs_multithreaded) - buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER; -+#else /* STAGING_CSMT */ -+ buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps)); -+ if (!buffer->maps) -+ { -+ ERR("Out of memory\n"); -+ buffer_unload(&buffer->resource); -+ resource_cleanup(&buffer->resource); -+ return E_OUTOFMEMORY; -+ } -+ buffer->maps_size = 1; -+#endif /* STAGING_CSMT */ - - return WINED3D_OK; - } -@@ -1429,6 +1661,7 @@ - - return WINED3D_OK; - } -+#if defined(STAGING_CSMT) - - void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) - { -@@ -1436,3 +1669,4 @@ - buffer->resource.heap_memory = mem; - buffer->flags |= WINED3D_BUFFER_DISCARD; - } -+#endif /* STAGING_CSMT */ -diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c ---- a/dlls/wined3d/directx.c -+++ b/dlls/wined3d/directx.c -@@ -5555,9 +5555,15 @@ - DebugBreak(); - } - -+#if defined(STAGING_CSMT) - /* Helper functions for providing vertex data to opengl. The arrays are initialized based on - * the extension detection and are used in draw_strided_slow - */ -+#else /* STAGING_CSMT */ -+/* Helper functions for providing vertex data to opengl. The arrays are initialized based on -+ * the extension detection and are used in drawStridedSlow -+ */ -+#endif /* STAGING_CSMT */ - static void WINE_GLAPI position_d3dcolor(const void *data) - { - DWORD pos = *((const DWORD *)data); -diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c ---- a/dlls/wined3d/resource.c -+++ b/dlls/wined3d/resource.c -@@ -203,7 +203,9 @@ - ERR("Failed to allocate system memory.\n"); - return E_OUTOFMEMORY; + HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; } -+#if defined(STAGING_CSMT) - resource->heap_memory = resource->map_heap_memory; +@@ -1194,6 +1288,14 @@ + { + WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning WINED3DERR_INVALIDCALL.\n"); + HeapFree(GetProcessHeap(), 0, texture); ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (levels != 1) ++ { ++ WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning WINED3DERR_INVALIDCALL.\n"); +#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } } - else +@@ -1202,7 +1304,9 @@ + surface_flags, device, parent, parent_ops, &texture2d_resource_ops))) { -@@ -227,6 +229,7 @@ - return WINED3D_OK; - } - + WARN("Failed to initialize texture, returning %#x.\n", hr); +#if defined(STAGING_CSMT) - void wined3d_resource_free_bo(struct wined3d_resource *resource) - { - struct wined3d_context *context = context_acquire(resource->device, NULL); -@@ -252,6 +255,7 @@ - resource->map_heap_memory = NULL; - } - + HeapFree(GetProcessHeap(), 0, texture); +#endif /* STAGING_CSMT */ - void resource_cleanup(struct wined3d_resource *resource) - { - const struct wined3d *d3d = resource->device->wined3d; -@@ -264,7 +268,11 @@ - adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size); + return hr; } -+#if defined(STAGING_CSMT) - wined3d_cs_emit_resource_cleanup(resource->device->cs, resource); -+#else /* STAGING_CSMT */ -+ wined3d_resource_free_sysmem(resource); -+#endif /* STAGING_CSMT */ +@@ -1288,12 +1392,25 @@ - device_resource_released(resource->device, resource); + static void texture3d_sub_resource_invalidate_location(struct wined3d_resource *sub_resource, DWORD location) + { ++#if defined(STAGING_CSMT) + wined3d_resource_invalidate_location(sub_resource, location); } -@@ -274,9 +282,11 @@ - if (resource->map_count) - ERR("Resource %p is being unloaded while mapped.\n", resource); -+#if defined(STAGING_CSMT) - if (resource->buffer) - wined3d_resource_free_bo(resource); - -+#endif /* STAGING_CSMT */ - context_resource_unloaded(resource->device, - resource, resource->type); - } -@@ -355,7 +365,11 @@ - p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1; - *p = mem; - -+#if defined(STAGING_CSMT) - resource->map_heap_memory = ++p; + static void texture3d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) + { + wined3d_resource_validate_location(sub_resource, location); +#else /* STAGING_CSMT */ -+ resource->heap_memory = ++p; ++ struct wined3d_volume *volume = volume_from_resource(sub_resource); ++ ++ wined3d_volume_invalidate_location(volume, location); ++} ++ ++static void texture3d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location) ++{ ++ struct wined3d_volume *volume = volume_from_resource(sub_resource); ++ ++ wined3d_volume_validate_location(volume, location); +#endif /* STAGING_CSMT */ + } + + static void texture3d_sub_resource_upload_data(struct wined3d_resource *sub_resource, +@@ -1303,7 +1420,11 @@ + struct wined3d_const_bo_address addr; + unsigned int row_pitch, slice_pitch; + ++#if defined(STAGING_CSMT) + wined3d_resource_get_pitch(sub_resource, &row_pitch, &slice_pitch); ++#else /* STAGING_CSMT */ ++ wined3d_volume_get_pitch(volume, &row_pitch, &slice_pitch); ++#endif /* STAGING_CSMT */ + if (row_pitch != data->row_pitch || slice_pitch != data->slice_pitch) + FIXME("Ignoring row/slice pitch (%u/%u).\n", data->row_pitch, data->slice_pitch); + +@@ -1328,7 +1449,11 @@ + void *mem = NULL; + + if (gl_info->supported[APPLE_CLIENT_STORAGE] && !format->convert ++#if defined(STAGING_CSMT) + && wined3d_resource_prepare_system_memory(&volume->resource)) ++#else /* STAGING_CSMT */ ++ && volume_prepare_system_memory(volume)) ++#endif /* STAGING_CSMT */ + { + TRACE("Enabling GL_UNPACK_CLIENT_STORAGE_APPLE for volume %p\n", volume); + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); +@@ -1405,6 +1530,7 @@ + if (WINED3DFMT_UNKNOWN >= desc->format) + { + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } +@@ -1413,6 +1539,14 @@ + { + WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); + HeapFree(GetProcessHeap(), 0, texture); ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (!gl_info->supported[EXT_TEXTURE3D]) ++ { ++ WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + +@@ -1422,6 +1556,7 @@ + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } +@@ -1430,6 +1565,14 @@ + { + WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); + HeapFree(GetProcessHeap(), 0, texture); ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (levels != 1) ++ { ++ WARN("WINED3DUSAGE_AUTOGENMIPMAP is set, and level count != 1, returning D3DERR_INVALIDCALL.\n"); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + } +@@ -1457,7 +1600,9 @@ + { + WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n", + desc->width, desc->height, desc->depth); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + } +@@ -1467,7 +1612,9 @@ + 0, device, parent, parent_ops, &texture3d_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return hr; + } + +@@ -1568,6 +1715,9 @@ + if (FAILED(hr)) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); ++#if !defined(STAGING_CSMT) ++ HeapFree(GetProcessHeap(), 0, object); ++#endif /* STAGING_CSMT */ + return hr; + } + +diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c +--- a/dlls/wined3d/utils.c ++++ b/dlls/wined3d/utils.c +@@ -3733,7 +3733,11 @@ + float y_offset = context->render_offscreen + ? (center_offset - (2.0f * y) - h) / h + : (center_offset - (2.0f * y) - h) / -h; ++#if defined(STAGING_CSMT) + enum wined3d_depth_buffer_type zenable = state->fb.depth_stencil ? ++#else /* STAGING_CSMT */ ++ enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ? ++#endif /* STAGING_CSMT */ + state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE; + float z_scale = zenable ? 2.0f : 0.0f; + float z_offset = zenable ? -1.0f : 0.0f; +@@ -3856,6 +3860,7 @@ + /* case WINED3D_TTFF_COUNT1: Won't ever get here. */ + case WINED3D_TTFF_COUNT2: + mat._13 = mat._23 = mat._33 = mat._43 = 0.0f; ++#if defined(STAGING_CSMT) + /* OpenGL divides the first 3 vertex coord by the 4th by default, + * which is essentially the same as D3DTTFF_PROJECTED. Make sure that + * the 4th coord evaluates to 1.0 to eliminate that. +@@ -3868,6 +3873,20 @@ + * A more serious problem occurs if the app passes 4 coordinates in, and the + * 4th is != 1.0(opengl default). This would have to be fixed in draw_strided_slow + * or a replacement shader. */ ++#else /* STAGING_CSMT */ ++ /* OpenGL divides the first 3 vertex coord by the 4th by default, ++ * which is essentially the same as D3DTTFF_PROJECTED. Make sure that ++ * the 4th coord evaluates to 1.0 to eliminate that. ++ * ++ * If the fixed function pipeline is used, the 4th value remains unused, ++ * so there is no danger in doing this. With vertex shaders we have a ++ * problem. Should an app hit that problem, the code here would have to ++ * check for pixel shaders, and the shader has to undo the default gl divide. ++ * ++ * A more serious problem occurs if the app passes 4 coordinates in, and the ++ * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow ++ * or a replacement shader. */ ++#endif /* STAGING_CSMT */ + default: + mat._14 = mat._24 = mat._34 = 0.0f; mat._44 = 1.0f; + } +@@ -4325,7 +4344,11 @@ + unsigned int i; + DWORD ttff; + DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; ++#if defined(STAGING_CSMT) + unsigned int rt_fmt_flags = state->fb.render_targets[0]->format_flags; ++#else /* STAGING_CSMT */ ++ unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; ++#endif /* STAGING_CSMT */ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_d3d_info *d3d_info = context->d3d_info; + +diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c +--- a/dlls/wined3d/vertexdeclaration.c ++++ b/dlls/wined3d/vertexdeclaration.c +@@ -50,12 +50,14 @@ + return refcount; + } + ++#if defined(STAGING_CSMT) + void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) + { + HeapFree(GetProcessHeap(), 0, declaration->elements); + HeapFree(GetProcessHeap(), 0, declaration); + } + ++#endif /* STAGING_CSMT */ + ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration) + { + ULONG refcount = InterlockedDecrement(&declaration->ref); +@@ -64,9 +66,15 @@ + + if (!refcount) + { ++#if defined(STAGING_CSMT) + const struct wined3d_device *device = declaration->device; + declaration->parent_ops->wined3d_object_destroyed(declaration->parent); + wined3d_cs_emit_vertex_declaration_destroy(device->cs, declaration); ++#else /* STAGING_CSMT */ ++ HeapFree(GetProcessHeap(), 0, declaration->elements); ++ declaration->parent_ops->wined3d_object_destroyed(declaration->parent); ++ HeapFree(GetProcessHeap(), 0, declaration); ++#endif /* STAGING_CSMT */ + } + + return refcount; +diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c +--- a/dlls/wined3d/view.c ++++ b/dlls/wined3d/view.c +@@ -33,11 +33,13 @@ + return refcount; + } + ++#if defined(STAGING_CSMT) + void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) + { + HeapFree(GetProcessHeap(), 0, view); + } + ++#endif /* STAGING_CSMT */ + ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view) + { + ULONG refcount = InterlockedDecrement(&view->refcount); +@@ -46,6 +48,7 @@ + + if (!refcount) + { ++#if defined(STAGING_CSMT) + struct wined3d_device *device = view->resource->device; + + /* Call wined3d_object_destroyed() before releasing the resource, +@@ -53,6 +56,13 @@ + view->parent_ops->wined3d_object_destroyed(view->parent); + wined3d_resource_decref(view->resource); + wined3d_cs_emit_view_destroy(device->cs, view); ++#else /* STAGING_CSMT */ ++ /* Call wined3d_object_destroyed() before releasing the resource, ++ * since releasing the resource may end up destroying the parent. */ ++ view->parent_ops->wined3d_object_destroyed(view->parent); ++ wined3d_resource_decref(view->resource); ++ HeapFree(GetProcessHeap(), 0, view); ++#endif /* STAGING_CSMT */ + } + + return refcount; +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -40,6 +40,32 @@ + return TRUE; + } + ++#if !defined(STAGING_CSMT) ++void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch) ++{ ++ const struct wined3d_format *format = volume->resource.format; ++ ++ if (volume->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) ++ { ++ /* Since compressed formats are block based, pitch means the amount of ++ * bytes to the next row of block rather than the next row of pixels. */ ++ UINT row_block_count = (volume->resource.width + format->block_width - 1) / format->block_width; ++ UINT slice_block_count = (volume->resource.height + format->block_height - 1) / format->block_height; ++ *row_pitch = row_block_count * format->block_byte_count; ++ *slice_pitch = *row_pitch * slice_block_count; ++ } ++ else ++ { ++ unsigned char alignment = volume->resource.device->surface_alignment; ++ *row_pitch = format->byte_count * volume->resource.width; /* Bytes / row */ ++ *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1); ++ *slice_pitch = *row_pitch * volume->resource.height; ++ } ++ ++ TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch); ++} ++ ++#endif /* STAGING_CSMT */ + /* This call just uploads data, the caller is responsible for binding the + * correct texture. */ + /* Context activation is done by the caller. */ +@@ -71,7 +97,11 @@ + dst_row_pitch = width * format->conv_byte_count; + dst_slice_pitch = dst_row_pitch * height; + ++#if defined(STAGING_CSMT) + wined3d_resource_get_pitch(&volume->resource, &src_row_pitch, &src_slice_pitch); ++#else /* STAGING_CSMT */ ++ wined3d_volume_get_pitch(volume, &src_row_pitch, &src_slice_pitch); ++#endif /* STAGING_CSMT */ + + converted_mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth); + format->convert(data->addr, converted_mem, src_row_pitch, src_slice_pitch, +@@ -99,6 +129,22 @@ + HeapFree(GetProcessHeap(), 0, converted_mem); + } + ++#if !defined(STAGING_CSMT) ++void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) ++{ ++ TRACE("Volume %p, setting %s.\n", volume, wined3d_debug_location(location)); ++ volume->locations |= location; ++ TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations)); ++} ++ ++void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) ++{ ++ TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location)); ++ volume->locations &= ~location; ++ TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations)); ++} ++ ++#endif /* STAGING_CSMT */ + /* Context activation is done by the caller. */ + static void wined3d_volume_download_data(struct wined3d_volume *volume, + const struct wined3d_context *context, const struct wined3d_bo_address *data) +@@ -134,8 +180,33 @@ + static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume) + { + wined3d_resource_free_sysmem(&volume->resource); ++#if defined(STAGING_CSMT) + volume->resource.map_heap_memory = NULL; + wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); ++#else /* STAGING_CSMT */ ++ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_SYSMEM); ++} ++ ++static DWORD volume_access_from_location(DWORD location) ++{ ++ switch (location) ++ { ++ case WINED3D_LOCATION_DISCARDED: ++ return 0; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return WINED3D_RESOURCE_ACCESS_CPU; ++ ++ case WINED3D_LOCATION_BUFFER: ++ case WINED3D_LOCATION_TEXTURE_RGB: ++ case WINED3D_LOCATION_TEXTURE_SRGB: ++ return WINED3D_RESOURCE_ACCESS_GPU; ++ ++ default: ++ FIXME("Unhandled location %#x.\n", location); ++ return 0; ++ } ++#endif /* STAGING_CSMT */ + } + + /* Context activation is done by the caller. */ +@@ -177,6 +248,7 @@ return TRUE; } -@@ -421,7 +435,11 @@ - return ret; - } - +#if defined(STAGING_CSMT) - static GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) + + /* Context activation is done by the caller. */ + static void wined3d_volume_load_location(struct wined3d_resource *resource, +@@ -187,6 +259,22 @@ + + TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location), + wined3d_debug_location(volume->resource.locations)); +#else /* STAGING_CSMT */ -+GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) ++/* Context activation is done by the caller. */ ++static void wined3d_volume_load_location(struct wined3d_volume *volume, ++ struct wined3d_context *context, DWORD location) ++{ ++ DWORD required_access = volume_access_from_location(location); ++ ++ TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location), ++ wined3d_debug_location(volume->locations)); ++ ++ if ((volume->locations & location) == location) ++ { ++ TRACE("Location(s) already up to date.\n"); ++ return; ++ } +#endif /* STAGING_CSMT */ - { - if (d3d_flags & WINED3D_MAP_READONLY) - return GL_READ_ONLY_ARB; -@@ -462,6 +480,7 @@ - else - resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB; + + if ((volume->resource.access_flags & required_access) != required_access) + { +@@ -205,6 +293,7 @@ + && !(volume->container->flags & WINED3D_TEXTURE_SRGB_ALLOCATED))) + ERR("Trying to load (s)RGB texture without prior allocation.\n"); + ++#if defined(STAGING_CSMT) + if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) + { + TRACE("Volume previously discarded, nothing to do.\n"); +@@ -238,6 +327,41 @@ + return; + } + wined3d_resource_validate_location(&volume->resource, location); ++#else /* STAGING_CSMT */ ++ if (volume->locations & WINED3D_LOCATION_DISCARDED) ++ { ++ TRACE("Volume previously discarded, nothing to do.\n"); ++ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); ++ } ++ else if (volume->locations & WINED3D_LOCATION_SYSMEM) ++ { ++ struct wined3d_const_bo_address data = {0, volume->resource.heap_memory}; ++ wined3d_texture_bind_and_dirtify(volume->container, context, ++ location == WINED3D_LOCATION_TEXTURE_SRGB); ++ wined3d_volume_upload_data(volume, context, &data); ++ } ++ else if (volume->locations & WINED3D_LOCATION_BUFFER) ++ { ++ struct wined3d_const_bo_address data = {volume->pbo, NULL}; ++ wined3d_texture_bind_and_dirtify(volume->container, context, ++ location == WINED3D_LOCATION_TEXTURE_SRGB); ++ wined3d_volume_upload_data(volume, context, &data); ++ } ++ else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) ++ { ++ wined3d_volume_srgb_transfer(volume, context, TRUE); ++ } ++ else if (volume->locations & WINED3D_LOCATION_TEXTURE_SRGB) ++ { ++ wined3d_volume_srgb_transfer(volume, context, FALSE); ++ } ++ else ++ { ++ FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->locations)); ++ return; ++ } ++ wined3d_volume_validate_location(volume, location); ++#endif /* STAGING_CSMT */ + + if (wined3d_volume_can_evict(volume)) + wined3d_volume_evict_sysmem(volume); +@@ -248,11 +372,24 @@ + if (!volume->resource.heap_memory) + ERR("Trying to load WINED3D_LOCATION_SYSMEM without setting it up first.\n"); + ++#if defined(STAGING_CSMT) + if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + struct wined3d_bo_address data = {0, volume->resource.heap_memory}; + + if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) ++#else /* STAGING_CSMT */ ++ if (volume->locations & WINED3D_LOCATION_DISCARDED) ++ { ++ TRACE("Volume previously discarded, nothing to do.\n"); ++ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); ++ } ++ else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ { ++ struct wined3d_bo_address data = {0, volume->resource.heap_memory}; ++ ++ if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) ++#endif /* STAGING_CSMT */ + wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); + else + wined3d_texture_bind_and_dirtify(volume->container, context, TRUE); +@@ -263,6 +400,7 @@ + else + { + FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", ++#if defined(STAGING_CSMT) + wined3d_debug_location(volume->resource.locations)); + return; + } +@@ -278,6 +416,28 @@ + struct wined3d_bo_address data = {volume->resource.buffer->name, NULL}; + + if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) ++#else /* STAGING_CSMT */ ++ wined3d_debug_location(volume->locations)); ++ return; ++ } ++ wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); ++ break; ++ ++ case WINED3D_LOCATION_BUFFER: ++ if (!volume->pbo) ++ ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); ++ ++ if (volume->locations & WINED3D_LOCATION_DISCARDED) ++ { ++ TRACE("Volume previously discarded, nothing to do.\n"); ++ wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); ++ } ++ else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ { ++ struct wined3d_bo_address data = {volume->pbo, NULL}; ++ ++ if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) ++#endif /* STAGING_CSMT */ + wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); + else + wined3d_texture_bind_and_dirtify(volume->container, context, TRUE); +@@ -287,6 +447,7 @@ + else + { + FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", ++#if defined(STAGING_CSMT) + wined3d_debug_location(volume->resource.locations)); + return; + } +@@ -296,6 +457,17 @@ + default: + FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), + wined3d_debug_location(volume->resource.locations)); ++#else /* STAGING_CSMT */ ++ wined3d_debug_location(volume->locations)); ++ return; ++ } ++ wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); ++ break; ++ ++ default: ++ FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), ++ wined3d_debug_location(volume->locations)); ++#endif /* STAGING_CSMT */ + } } + +@@ -303,6 +475,7 @@ + void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode) + { + wined3d_texture_prepare_texture(volume->container, context, srgb_mode); ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&volume->resource, context, + srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB); + } +@@ -315,6 +488,51 @@ + resource_cleanup(&volume->resource); + volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); + wined3d_cs_emit_volume_cleanup(device->cs, volume); ++#else /* STAGING_CSMT */ ++ wined3d_volume_load_location(volume, context, ++ srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB); ++} ++ ++/* Context activation is done by the caller. */ ++static void wined3d_volume_prepare_pbo(struct wined3d_volume *volume, struct wined3d_context *context) ++{ ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ ++ if (volume->pbo) ++ return; ++ ++ GL_EXTCALL(glGenBuffers(1, &volume->pbo)); ++ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo)); ++ GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, volume->resource.size, NULL, GL_STREAM_DRAW)); ++ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); ++ checkGLcall("Create PBO"); ++ ++ TRACE("Created PBO %u for volume %p.\n", volume->pbo, volume); ++} ++ ++static void wined3d_volume_free_pbo(struct wined3d_volume *volume) ++{ ++ struct wined3d_context *context = context_acquire(volume->resource.device, NULL); ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ ++ TRACE("Deleting PBO %u belonging to volume %p.\n", volume->pbo, volume); ++ GL_EXTCALL(glDeleteBuffers(1, &volume->pbo)); ++ checkGLcall("glDeleteBuffers"); ++ volume->pbo = 0; ++ context_release(context); ++} ++ ++void wined3d_volume_destroy(struct wined3d_volume *volume) ++{ ++ TRACE("volume %p.\n", volume); ++ ++ if (volume->pbo) ++ wined3d_volume_free_pbo(volume); ++ ++ resource_cleanup(&volume->resource); ++ volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); ++ HeapFree(GetProcessHeap(), 0, volume); ++#endif /* STAGING_CSMT */ + } + + static void volume_unload(struct wined3d_resource *resource) +@@ -328,6 +546,7 @@ + + TRACE("texture %p.\n", resource); + ++#if defined(STAGING_CSMT) + if (wined3d_resource_prepare_system_memory(&volume->resource)) + { + context = context_acquire(device, NULL); +@@ -340,6 +559,29 @@ + ERR("Out of memory when unloading volume %p.\n", volume); + wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); + wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_DISCARDED); ++#else /* STAGING_CSMT */ ++ if (volume_prepare_system_memory(volume)) ++ { ++ context = context_acquire(device, NULL); ++ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); ++ context_release(context); ++ wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM); ++ } ++ else ++ { ++ ERR("Out of memory when unloading volume %p.\n", volume); ++ wined3d_volume_validate_location(volume, WINED3D_LOCATION_DISCARDED); ++ wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_DISCARDED); ++ } ++ ++ if (volume->pbo) ++ { ++ /* Should not happen because only dynamic default pool volumes ++ * have a buffer, and those are not evicted by device_evit_managed_resources ++ * and must be freed before a non-ex device reset. */ ++ ERR("Unloading a volume with a buffer\n"); ++ wined3d_volume_free_pbo(volume); ++#endif /* STAGING_CSMT */ + } + + /* The texture name is managed by the container. */ +@@ -348,6 +590,36 @@ + resource_unload(resource); + } + ++#if !defined(STAGING_CSMT) ++static BOOL volume_check_block_align(const struct wined3d_volume *volume, ++ const struct wined3d_box *box) ++{ ++ UINT width_mask, height_mask; ++ const struct wined3d_format *format = volume->resource.format; ++ ++ if (!box) ++ return TRUE; ++ ++ /* This assumes power of two block sizes, but NPOT block sizes would be ++ * silly anyway. ++ * ++ * This also assumes that the format's block depth is 1. */ ++ width_mask = format->block_width - 1; ++ height_mask = format->block_height - 1; ++ ++ if (box->left & width_mask) ++ return FALSE; ++ if (box->top & height_mask) ++ return FALSE; ++ if (box->right & width_mask && box->right != volume->resource.width) ++ return FALSE; ++ if (box->bottom & height_mask && box->bottom != volume->resource.height) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++#endif /* STAGING_CSMT */ + static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *volume, + const struct wined3d_box *box) + { +@@ -373,6 +645,7 @@ + HRESULT wined3d_volume_map(struct wined3d_volume *volume, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + { ++#if defined(STAGING_CSMT) + HRESULT hr; + const struct wined3d_format *format = volume->resource.format; + const unsigned int fmt_flags = volume->container->resource.format_flags; +@@ -413,6 +686,177 @@ + if (hr == WINEDDERR_NOTLOCKED) + return WINED3DERR_INVALIDCALL; + return hr; ++#else /* STAGING_CSMT */ ++ struct wined3d_device *device = volume->resource.device; ++ struct wined3d_context *context; ++ const struct wined3d_gl_info *gl_info; ++ BYTE *base_memory; ++ const struct wined3d_format *format = volume->resource.format; ++ const unsigned int fmt_flags = volume->container->resource.format_flags; ++ ++ TRACE("volume %p, map_desc %p, box %p, flags %#x.\n", ++ volume, map_desc, box, flags); ++ ++ map_desc->data = NULL; ++ if (!(volume->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU)) ++ { ++ WARN("Volume %p is not CPU accessible.\n", volume); ++ return WINED3DERR_INVALIDCALL; ++ } ++ if (volume->resource.map_count) ++ { ++ WARN("Volume is already mapped.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ if (!wined3d_volume_check_box_dimensions(volume, box)) ++ { ++ WARN("Map box is invalid.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !volume_check_block_align(volume, box)) ++ { ++ WARN("Map box is misaligned for %ux%u blocks.\n", ++ format->block_width, format->block_height); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); ++ ++ if (volume->resource.map_binding == WINED3D_LOCATION_BUFFER) ++ { ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ ++ wined3d_volume_prepare_pbo(volume, context); ++ if (flags & WINED3D_MAP_DISCARD) ++ wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); ++ else ++ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); ++ ++ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo)); ++ ++ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) ++ { ++ GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); ++ mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; ++ base_memory = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, ++ 0, volume->resource.size, mapflags)); ++ } ++ else ++ { ++ GLenum access = wined3d_resource_gl_legacy_map_flags(flags); ++ base_memory = GL_EXTCALL(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, access)); ++ } ++ ++ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); ++ checkGLcall("Map PBO"); ++ ++ context_release(context); ++ } ++ else ++ { ++ if (!volume_prepare_system_memory(volume)) ++ { ++ WARN("Out of memory.\n"); ++ map_desc->data = NULL; ++ return E_OUTOFMEMORY; ++ } ++ ++ if (flags & WINED3D_MAP_DISCARD) ++ { ++ wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); ++ } ++ else if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) ++ { ++ context = context_acquire(device, NULL); ++ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); ++ context_release(context); ++ } ++ base_memory = volume->resource.heap_memory; ++ } ++ ++ TRACE("Base memory pointer %p.\n", base_memory); ++ ++ if (fmt_flags & WINED3DFMT_FLAG_BROKEN_PITCH) ++ { ++ map_desc->row_pitch = volume->resource.width * format->byte_count; ++ map_desc->slice_pitch = map_desc->row_pitch * volume->resource.height; ++ } ++ else ++ { ++ wined3d_volume_get_pitch(volume, &map_desc->row_pitch, &map_desc->slice_pitch); ++ } ++ ++ if (!box) ++ { ++ TRACE("No box supplied - all is ok\n"); ++ map_desc->data = base_memory; ++ } ++ else ++ { ++ TRACE("Lock Box (%p) = l %u, t %u, r %u, b %u, fr %u, ba %u\n", ++ box, box->left, box->top, box->right, box->bottom, box->front, box->back); ++ ++ if ((fmt_flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS) ++ { ++ /* Compressed textures are block based, so calculate the offset of ++ * the block that contains the top-left pixel of the locked rectangle. */ ++ map_desc->data = base_memory ++ + (box->front * map_desc->slice_pitch) ++ + ((box->top / format->block_height) * map_desc->row_pitch) ++ + ((box->left / format->block_width) * format->block_byte_count); ++ } ++ else ++ { ++ map_desc->data = base_memory ++ + (map_desc->slice_pitch * box->front) ++ + (map_desc->row_pitch * box->top) ++ + (box->left * volume->resource.format->byte_count); ++ } ++ } ++ ++ if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) ++ { ++ wined3d_texture_set_dirty(volume->container); ++ wined3d_volume_invalidate_location(volume, ~volume->resource.map_binding); ++ } ++ ++ volume->resource.map_count++; ++ ++ TRACE("Returning memory %p, row pitch %d, slice pitch %d.\n", ++ map_desc->data, map_desc->row_pitch, map_desc->slice_pitch); ++ ++ return WINED3D_OK; ++} ++ ++HRESULT wined3d_volume_unmap(struct wined3d_volume *volume) ++{ ++ TRACE("volume %p.\n", volume); ++ ++ if (!volume->resource.map_count) ++ { ++ WARN("Trying to unlock an unlocked volume %p.\n", volume); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (volume->resource.map_binding == WINED3D_LOCATION_BUFFER) ++ { ++ struct wined3d_device *device = volume->resource.device; ++ struct wined3d_context *context = context_acquire(device, NULL); ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ ++ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo)); ++ GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); ++ GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); ++ checkGLcall("Unmap PBO"); ++ ++ context_release(context); ++ } ++ ++ volume->resource.map_count--; ++ ++ return WINED3D_OK; ++#endif /* STAGING_CSMT */ + } + + static ULONG volume_resource_incref(struct wined3d_resource *resource) +@@ -423,11 +867,13 @@ + return wined3d_texture_incref(volume->container); + } + ++#if defined(STAGING_CSMT) + void wined3d_volume_cleanup_cs(struct wined3d_volume *volume) + { + HeapFree(GetProcessHeap(), 0, volume); + } + ++#endif /* STAGING_CSMT */ + static ULONG volume_resource_decref(struct wined3d_resource *resource) + { + struct wined3d_volume *volume = volume_from_resource(resource); +@@ -449,6 +895,7 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if defined(STAGING_CSMT) + static void wined3d_volume_location_invalidated(struct wined3d_resource *resource, DWORD location) + { + struct wined3d_volume *volume = volume_from_resource(resource); +@@ -457,6 +904,7 @@ + wined3d_texture_set_dirty(volume->container); + } + ++#endif /* STAGING_CSMT */ + static const struct wined3d_resource_ops volume_resource_ops = + { + volume_resource_incref, +@@ -464,8 +912,10 @@ + volume_unload, + volume_resource_sub_resource_map, + volume_resource_sub_resource_unmap, ++#if defined(STAGING_CSMT) + wined3d_volume_location_invalidated, + wined3d_volume_load_location, ++#endif /* STAGING_CSMT */ + }; + + static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container, +@@ -497,7 +947,11 @@ + } + + volume->texture_level = level; ++#if defined(STAGING_CSMT) + volume->resource.locations = WINED3D_LOCATION_DISCARDED; ++#else /* STAGING_CSMT */ ++ volume->locations = WINED3D_LOCATION_DISCARDED; ++#endif /* STAGING_CSMT */ + + if (desc->pool == WINED3D_POOL_DEFAULT && desc->usage & WINED3DUSAGE_DYNAMIC + && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] +@@ -505,7 +959,9 @@ + { + wined3d_resource_free_sysmem(&volume->resource); + volume->resource.map_binding = WINED3D_LOCATION_BUFFER; ++#if defined(STAGING_CSMT) + volume->resource.map_heap_memory = NULL; ++#endif /* STAGING_CSMT */ + } + + volume->container = container; +diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c +--- a/dlls/wined3d/wined3d_main.c ++++ b/dlls/wined3d/wined3d_main.c +@@ -87,8 +87,10 @@ + ~0U, /* No GS shader model limit by default. */ + ~0U, /* No PS shader model limit by default. */ + FALSE, /* 3D support enabled by default. */ ++#if defined(STAGING_CSMT) + TRUE, /* Multithreaded CS by default. */ + FALSE, /* Do not ignore render target maps. */ ++#endif /* STAGING_CSMT */ + }; + + struct wined3d * CDECL wined3d_create(DWORD flags) +@@ -328,6 +330,7 @@ + TRACE("Disabling 3D support.\n"); + wined3d_settings.no_3d = TRUE; + } ++#if defined(STAGING_CSMT) + if (!get_config_key(hkey, appkey, "CSMT", buffer, size) + && !strcmp(buffer,"disabled")) + { +@@ -344,6 +347,9 @@ + + FIXME_(winediag)("Experimental wined3d CSMT feature is currently %s.\n", + wined3d_settings.cs_multithreaded ? "enabled" : "disabled"); ++#else /* STAGING_CSMT */ ++ } ++#endif /* STAGING_CSMT */ + + if (appkey) RegCloseKey( appkey ); + if (hkey) RegCloseKey( hkey ); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1,3 +1,4 @@ ++#if defined(STAGING_CSMT) + /* + * Direct3D wine internal private include file + * +@@ -21,6 +22,31 @@ + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ ++#else /* STAGING_CSMT */ ++/* ++ * Direct3D wine internal private include file ++ * ++ * Copyright 2002-2003 The wine-d3d team ++ * Copyright 2002-2003 Raphael Junqueira ++ * Copyright 2002-2003, 2004 Jason Edmeades ++ * Copyright 2005 Oliver Stieber ++ * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++#endif /* STAGING_CSMT */ + + #ifndef __WINE_WINED3D_PRIVATE_H + #define __WINE_WINED3D_PRIVATE_H +@@ -31,7 +57,9 @@ + #define WINE_GLAPI + #endif + ++#if defined(STAGING_CSMT) + #include ++#endif /* STAGING_CSMT */ + #include + #include + #include +@@ -284,8 +312,10 @@ + unsigned int max_sm_gs; + unsigned int max_sm_ps; + BOOL no_3d; ++#if defined(STAGING_CSMT) + BOOL cs_multithreaded; + BOOL ignore_rt_map; ++#endif /* STAGING_CSMT */ + }; + + extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; +@@ -1026,9 +1056,14 @@ + WORD use_map; /* MAX_ATTRIBS, 16 */ + }; + ++#if defined(STAGING_CSMT) + void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, + UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count, + BOOL indexed) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count, ++ UINT start_instance, UINT instance_count, BOOL indexed) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN; + + #define eps 1e-8f +@@ -1116,8 +1151,10 @@ + struct list entry; + GLuint id; + struct wined3d_context *context; ++#if defined(STAGING_CSMT) + DWORD samples; + BOOL started; ++#endif /* STAGING_CSMT */ + }; + + union wined3d_gl_query_object +@@ -1153,6 +1190,7 @@ + struct list entry; + GLuint id; + struct wined3d_context *context; ++#if defined(STAGING_CSMT) + UINT64 timestamp; + }; + +@@ -1188,6 +1226,12 @@ + for (i = 0; i < min(dst->rt_size, src->rt_size); i++) + dst->render_targets[i] = src->render_targets[i]; + } ++#else /* STAGING_CSMT */ ++}; ++ ++void context_alloc_timestamp_query(struct wined3d_context *context, struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; ++void context_free_timestamp_query(struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + struct wined3d_context + { +@@ -1203,7 +1247,9 @@ + DWORD dirtyArray[STATE_HIGHEST + 1]; /* Won't get bigger than that, a state is never marked dirty 2 times */ + DWORD numDirtyEntries; + DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */ ++#if defined(STAGING_CSMT) + struct wined3d_fb_state current_fb; ++#endif /* STAGING_CSMT */ + + struct wined3d_swapchain *swapchain; + struct wined3d_surface *current_rt; +@@ -1301,8 +1347,17 @@ + GLfloat fog_coord_value; + GLfloat color[4], fogstart, fogend, fogcolor[4]; + GLuint dummy_arbfp_prog; +#if defined(STAGING_CSMT) - void wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, - UINT *slice_pitch) -@@ -1040,3 +1059,4 @@ - - wined3d_resource_invalidate_location(resource, ~resource->map_binding); - } + GLenum offscreenBuffer; ++#else /* STAGING_CSMT */ ++}; ++ ++struct wined3d_fb_state ++{ ++ struct wined3d_rendertarget_view **render_targets; ++ struct wined3d_rendertarget_view *depth_stencil; +#endif /* STAGING_CSMT */ + }; + + typedef void (*APPLYSTATEFUNC)(struct wined3d_context *ctx, const struct wined3d_state *state, DWORD state_id); +@@ -1445,8 +1500,12 @@ + void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN; + BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device, + UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, + const struct wined3d_state *state) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, + struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN; + void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, +@@ -2029,7 +2088,11 @@ + struct wined3d_state + { + DWORD flags; ++#if defined(STAGING_CSMT) + struct wined3d_fb_state fb; ++#else /* STAGING_CSMT */ ++ const struct wined3d_fb_state *fb; ++#endif /* STAGING_CSMT */ + + struct wined3d_vertex_declaration *vertex_declaration; + struct wined3d_stream_output stream_output[MAX_STREAM_OUT]; +@@ -2074,6 +2137,7 @@ + DWORD render_states[WINEHIGHEST_RENDER_STATE + 1]; + }; + ++#if defined(STAGING_CSMT) + struct wined3d_gl_bo + { + GLuint name; +@@ -2082,6 +2146,7 @@ + UINT size; + }; + ++#endif /* STAGING_CSMT */ + #define WINED3D_UNMAPPED_STAGE ~0U + + /* Multithreaded flag. Removed from the public header to signal that +@@ -2137,11 +2202,23 @@ + struct wined3d_rendertarget_view *back_buffer_view; + struct wined3d_swapchain **swapchains; + UINT swapchain_count; ++#if defined(STAGING_CSMT) + struct wined3d_rendertarget_view *auto_depth_stencil_view; + + struct list resources; /* a linked list to track resources created by the device */ + struct list shaders; /* a linked list to track shaders (pixel and vertex) */ + struct wine_rb_tree samplers; ++#else /* STAGING_CSMT */ ++ ++ struct list resources; /* a linked list to track resources created by the device */ ++ struct list shaders; /* a linked list to track shaders (pixel and vertex) */ ++ struct wine_rb_tree samplers; ++ ++ /* Render Target Support */ ++ struct wined3d_fb_state fb; ++ struct wined3d_surface *onscreen_depth_stencil; ++ struct wined3d_rendertarget_view *auto_depth_stencil_view; ++#endif /* STAGING_CSMT */ + + /* For rendering to a texture using glCopyTexImage */ + GLuint depth_blt_texture; +@@ -2152,6 +2229,9 @@ + UINT xScreenSpace; + UINT yScreenSpace; + UINT cursorWidth, cursorHeight; ++#if !defined(STAGING_CSMT) ++ struct wined3d_texture *cursor_texture; ++#endif /* STAGING_CSMT */ + HCURSOR hardwareCursor; + + /* The Wine logo texture */ +@@ -2183,6 +2263,7 @@ + UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN; + void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; + void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) DECLSPEC_HIDDEN; + void device_exec_update_texture(struct wined3d_context *context, struct wined3d_texture *src_texture, +@@ -2194,6 +2275,11 @@ + void device_create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; + void device_delete_opengl_contexts_cs(struct wined3d_device *device, + struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++void device_switch_onscreen_ds(struct wined3d_device *device, struct wined3d_context *context, ++ struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN; ++void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) + { +@@ -2213,9 +2299,11 @@ + HRESULT (*resource_sub_resource_map)(struct wined3d_resource *resource, unsigned int sub_resource_idx, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags); + HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx); ++#if defined(STAGING_CSMT) + void (*resource_location_invalidated)(struct wined3d_resource *resource, DWORD location); + void (*resource_load_location)(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location); ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_resource +@@ -2240,6 +2328,7 @@ + UINT depth; + UINT size; + DWORD priority; ++#if defined(STAGING_CSMT) + void *heap_memory, *map_heap_memory, *user_memory, *bitmap_data; + UINT custom_row_pitch, custom_slice_pitch; + struct wined3d_gl_bo *buffer, *map_buffer; +@@ -2247,6 +2336,10 @@ + DWORD locations; + LONG access_fence; + BOOL unmap_dirtify; ++#else /* STAGING_CSMT */ ++ void *heap_memory; ++ struct list resource_list_entry; ++#endif /* STAGING_CSMT */ + + void *parent; + const struct wined3d_parent_ops *parent_ops; +@@ -2271,6 +2364,7 @@ + void *parent, const struct wined3d_parent_ops *parent_ops, + const struct wined3d_resource_ops *resource_ops) DECLSPEC_HIDDEN; + void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_changed(struct wined3d_resource *resource, +@@ -2319,6 +2413,15 @@ + { + while(InterlockedCompareExchange(&resource->access_fence, 0, 0)); + } ++#else /* STAGING_CSMT */ ++BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; ++GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; ++BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN; ++void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + /* Tests show that the start address of resources is 32 byte aligned */ + #define RESOURCE_ALIGNMENT 16 +@@ -2403,7 +2506,9 @@ + + void wined3d_texture_apply_sampler_desc(struct wined3d_texture *texture, + const struct wined3d_sampler_desc *sampler_desc, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + void wined3d_texture_bind(struct wined3d_texture *texture, + struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; + void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture, +@@ -2437,9 +2542,16 @@ + struct wined3d_resource resource; + struct wined3d_texture *container; + ++#if defined(STAGING_CSMT) + DWORD flags; + GLint texture_level; + DWORD download_count; ++#else /* STAGING_CSMT */ ++ DWORD flags, locations; ++ GLint texture_level; ++ DWORD download_count; ++ GLuint pbo; ++#endif /* STAGING_CSMT */ + }; + + static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource) +@@ -2447,6 +2559,7 @@ + return CONTAINING_RECORD(resource, struct wined3d_volume, resource); + } + ++#if defined(STAGING_CSMT) + HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, + unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN; + void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN; +@@ -2462,6 +2575,27 @@ + struct wined3d_surface_dib + { + HBITMAP DIBsection; ++#else /* STAGING_CSMT */ ++BOOL volume_prepare_system_memory(struct wined3d_volume *volume) DECLSPEC_HIDDEN; ++HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, ++ unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN; ++void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN; ++void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch) DECLSPEC_HIDDEN; ++void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, ++ BOOL srgb_mode) DECLSPEC_HIDDEN; ++void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN; ++HRESULT wined3d_volume_map(struct wined3d_volume *volume, ++ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) DECLSPEC_HIDDEN; ++void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN; ++HRESULT wined3d_volume_unmap(struct wined3d_volume *volume) DECLSPEC_HIDDEN; ++void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, ++ const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; ++ ++struct wined3d_surface_dib ++{ ++ HBITMAP DIBsection; ++ void *bitmap_data; ++#endif /* STAGING_CSMT */ + UINT bitmap_size; + }; + +@@ -2487,7 +2621,11 @@ + struct wined3d_surface_ops + { + HRESULT (*surface_private_setup)(struct wined3d_surface *surface); ++#if defined(STAGING_CSMT) + void (*surface_frontbuffer_updated)(struct wined3d_surface *surface); ++#else /* STAGING_CSMT */ ++ void (*surface_unmap)(struct wined3d_surface *surface); ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_surface +@@ -2495,12 +2633,26 @@ + struct wined3d_resource resource; + const struct wined3d_surface_ops *surface_ops; + struct wined3d_texture *container; ++#if defined(STAGING_CSMT) + + DWORD flags; + + UINT pow2Width; + UINT pow2Height; + ++#else /* STAGING_CSMT */ ++ void *user_memory; ++ DWORD locations; ++ ++ DWORD flags; ++ ++ UINT pitch; ++ UINT pow2Width; ++ UINT pow2Height; ++ ++ /* PBO */ ++ GLuint pbo; ++#endif /* STAGING_CSMT */ + GLuint rb_multisample; + GLuint rb_resolved; + GLenum texture_target; +@@ -2544,11 +2696,22 @@ + GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context, + unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; + void surface_load_ds_location(struct wined3d_surface *surface, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; + void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, + struct wined3d_context *context) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; ++void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; ++void surface_load_ds_location(struct wined3d_surface *surface, ++ struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; ++void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, ++ struct wined3d_context *context) DECLSPEC_HIDDEN; ++HRESULT surface_load_location(struct wined3d_surface *surface, ++ struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; + void wined3d_surface_prepare(struct wined3d_surface *surface, struct wined3d_context *context, + DWORD location) DECLSPEC_HIDDEN; +@@ -2560,6 +2723,7 @@ + const struct wined3d_gl_info *gl_info, void *mem, unsigned int pitch) DECLSPEC_HIDDEN; + HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point, + struct wined3d_surface *src_surface, const RECT *src_rect) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, + GLenum target, unsigned int level, unsigned int layer, DWORD flags, + struct wined3d_surface **surface) DECLSPEC_HIDDEN; +@@ -2574,6 +2738,17 @@ + void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void wined3d_surface_getdc_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void wined3d_surface_releasedc_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++void surface_validate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; ++HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc, ++ GLenum target, unsigned int level, unsigned int layer, DWORD flags, ++ struct wined3d_surface **surface) DECLSPEC_HIDDEN; ++void wined3d_surface_destroy(struct wined3d_surface *surface) DECLSPEC_HIDDEN; ++void surface_prepare_map_memory(struct wined3d_surface *surface) DECLSPEC_HIDDEN; ++void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, ++ const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point, ++ BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context, + const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; +@@ -2595,8 +2770,10 @@ + GLuint name; + }; + ++#if defined(STAGING_CSMT) + void wined3d_sampler_destroy(struct wined3d_sampler *sampler) DECLSPEC_HIDDEN; + ++#endif /* STAGING_CSMT */ + struct wined3d_vertex_declaration_element + { + const struct wined3d_format *format; +@@ -2625,8 +2802,10 @@ + BOOL half_float_conv_needed; + }; + ++#if defined(STAGING_CSMT) + void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; + ++#endif /* STAGING_CSMT */ + struct wined3d_saved_states + { + DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1]; +@@ -2694,6 +2873,7 @@ + void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN; + + void state_cleanup(struct wined3d_state *state) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + HRESULT state_init(struct wined3d_state *state, const struct wined3d_gl_info *gl_info, + const struct wined3d_d3d_info *d3d_info, DWORD flags) DECLSPEC_HIDDEN; + void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN; +@@ -2744,6 +2924,32 @@ + void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, struct wined3d_context *context, + struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb, ++ const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info, ++ DWORD flags) DECLSPEC_HIDDEN; ++void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN; ++ ++struct wined3d_cs_ops ++{ ++ void *(*require_space)(struct wined3d_cs *cs, size_t size); ++ void (*submit)(struct wined3d_cs *cs); ++}; ++ ++struct wined3d_cs ++{ ++ const struct wined3d_cs_ops *ops; ++ struct wined3d_device *device; ++ struct wined3d_fb_state fb; ++ struct wined3d_state state; ++ ++ size_t data_size; ++ void *data; ++}; ++ ++struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; ++void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, + DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; +@@ -2793,6 +2999,7 @@ + void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, + struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, const float *constants, + UINT vector4f_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, +@@ -2856,6 +3063,7 @@ + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, + unsigned int depth_pitch) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + /* Direct3D terminology with little modifications. We do not have an issued state + * because only the driver knows about it, but we have a created state because d3d +@@ -2870,8 +3078,12 @@ + struct wined3d_query_ops + { + HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags); ++#if defined(STAGING_CSMT) + BOOL (*query_poll)(struct wined3d_query *query); + BOOL (*query_issue)(struct wined3d_query *query, DWORD flags); ++#else /* STAGING_CSMT */ ++ HRESULT (*query_issue)(struct wined3d_query *query, DWORD flags); ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_query +@@ -2885,12 +3097,16 @@ + enum wined3d_query_type type; + DWORD data_size; + void *extendedData; ++#if defined(STAGING_CSMT) + + LONG counter_main, counter_retrieved; + struct list poll_list_entry; + }; + + void wined3d_query_destroy(struct wined3d_query *query) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++}; ++#endif /* STAGING_CSMT */ + + /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other + * fixed function semantics as D3DCOLOR or FLOAT16 */ +@@ -2917,7 +3133,9 @@ + GLenum buffer_object_usage; + GLenum buffer_type_hint; + DWORD flags; ++#if defined(STAGING_CSMT) + BOOL ignore_discard; ++#endif /* STAGING_CSMT */ + void *map_ptr; + + struct wined3d_map_range *maps; +@@ -2942,11 +3160,15 @@ + BYTE *buffer_get_sysmem(struct wined3d_buffer *This, struct wined3d_context *context) DECLSPEC_HIDDEN; + void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_context *context, + const struct wined3d_state *state) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + void buffer_invalidate_bo_range(struct wined3d_buffer *This, UINT offset, UINT size) DECLSPEC_HIDDEN; + void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) DECLSPEC_HIDDEN; + void buffer_create_buffer_object(struct wined3d_buffer *This, + struct wined3d_context *context) DECLSPEC_HIDDEN; + void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++void buffer_mark_used(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + struct wined3d_rendertarget_view + { +@@ -2985,8 +3207,10 @@ + return surface_from_resource(resource); + } + ++#if defined(STAGING_CSMT) + void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + ++#endif /* STAGING_CSMT */ + struct wined3d_shader_resource_view + { + LONG refcount; +@@ -2999,8 +3223,12 @@ + struct wined3d_swapchain_ops + { + void (*swapchain_present)(struct wined3d_swapchain *swapchain, const RECT *src_rect, ++#if defined(STAGING_CSMT) + const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags, + struct wined3d_surface *depth_stencil); ++#else /* STAGING_CSMT */ ++ const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags); ++#endif /* STAGING_CSMT */ + }; + + struct wined3d_swapchain +@@ -3039,8 +3267,10 @@ + void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + HRESULT swapchain_create_context_cs(struct wined3d_device *device, + struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + /***************************************************************************** + * Utility function prototypes +@@ -3243,7 +3473,9 @@ + void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, + const struct wined3d_shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx) DECLSPEC_HIDDEN; + BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage usage) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) + void shader_cleanup(struct wined3d_shader *shader) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) + { +diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c +--- a/dlls/winex11.drv/opengl.c ++++ b/dlls/winex11.drv/opengl.c +@@ -1980,7 +1980,9 @@ + escape.code = X11DRV_FLUSH_GL_DRAWABLE; + escape.gl_drawable = 0; + ++#if defined(STAGING_CSMT) + ERR("glFinish\n"); ++#endif /* STAGING_CSMT */ + if ((gl = get_gl_drawable( WindowFromDC( ctx->hdc ), 0 ))) + { + switch (gl->type) +@@ -2006,7 +2008,9 @@ + escape.code = X11DRV_FLUSH_GL_DRAWABLE; + escape.gl_drawable = 0; + ++#if defined(STAGING_CSMT) + ERR("glFlush\n"); ++#endif /* STAGING_CSMT */ + if ((gl = get_gl_drawable( WindowFromDC( ctx->hdc ), 0 ))) + { + switch (gl->type) diff --git a/staging/patchupdate.py b/staging/patchupdate.py index c7abbbe0..6315d0f1 100755 --- a/staging/patchupdate.py +++ b/staging/patchupdate.py @@ -479,7 +479,7 @@ def generate_ifdefined(all_patches, skip_checks=False): fp.write("\n") depends = resolve_dependencies(enabled_patches, i) - for f in patch.modified_files: + for f in sorted(patch.modified_files): # Reconstruct the state after applying the dependencies original = get_wine_file(f)